From bfe522304da217296e2a61040f58e35ec5d6f3f2 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Mon, 16 Aug 2021 09:51:46 +0200 Subject: New upstream version 1.30.6 --- src/core/devices/bluetooth/nm-bluez-manager.c | 2 + src/core/devices/nm-acd-manager.c | 11 +- src/core/devices/nm-device-bond.c | 42 ++++-- src/core/devices/nm-device-ethernet.c | 4 +- src/core/devices/nm-device.c | 147 +++++++++------------ src/core/devices/nm-device.h | 35 ++--- src/core/devices/ovs/nm-device-ovs-interface.c | 10 ++ src/core/devices/wifi/nm-device-iwd.c | 15 ++- src/core/devices/wifi/nm-device-wifi.c | 8 ++ src/core/devices/wifi/nm-iwd-manager.c | 1 + src/core/devices/wwan/nm-modem-broadband.c | 10 +- src/core/dhcp/nm-dhcp-client.c | 7 +- src/core/dhcp/nm-dhcp-client.h | 2 +- src/core/dhcp/nm-dhcp-dhcpcd.c | 42 +++--- src/core/dhcp/nm-dhcp-nettools.c | 29 ++-- src/core/dhcp/nm-dhcp-systemd.c | 46 +++---- src/core/dhcp/nm-dhcp-utils.c | 2 +- src/core/dns/nm-dns-manager.c | 16 +-- src/core/initrd/nmi-cmdline-reader.c | 29 +++- src/core/initrd/tests/test-cmdline-reader.c | 67 +++++++++- src/core/nm-config-data.c | 2 +- src/core/nm-core-utils.c | 12 +- src/core/nm-ip4-config.c | 15 --- src/core/nm-ip6-config.c | 33 ----- src/core/nm-manager.c | 70 +++++++++- src/core/nm-policy.c | 1 + src/core/nm-types.h | 12 +- src/core/platform/nm-platform.c | 124 +++++++++++++++-- src/core/platform/tests/test-common.c | 5 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 3 +- .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 1 + .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 40 +++--- .../ifcfg-test-tc-write-empty.cexpected | 15 +++ .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 80 +++++++++++ .../settings/plugins/keyfile/nms-keyfile-utils.c | 6 +- src/core/supplicant/nm-supplicant-config.c | 5 + src/core/supplicant/nm-supplicant-interface.c | 28 +++- src/core/supplicant/nm-supplicant-manager.c | 33 ++--- src/core/supplicant/nm-supplicant-types.h | 15 +++ src/core/tests/test-systemd.c | 10 +- 41 files changed, 711 insertions(+), 326 deletions(-) create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected (limited to 'src/core') diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index dd998d29..459ea409 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -2879,6 +2879,8 @@ dispose(GObject *object) g_clear_object(&priv->dbus_connection); nm_clear_pointer(&priv->bzobjs, g_hash_table_destroy); + nm_clear_pointer(&priv->conn_data_heads, g_hash_table_destroy); + nm_clear_pointer(&priv->conn_data_elems, g_hash_table_destroy); } static void diff --git a/src/core/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c index b95f90fd..81a28797 100644 --- a/src/core/devices/nm-acd-manager.c +++ b/src/core/devices/nm-acd-manager.c @@ -188,6 +188,7 @@ acd_event(int fd, GIOCondition condition, gpointer data) char to_string_buffer[ACD_EVENT_TO_STRING_BUF_SIZE]; gs_free char *hwaddr_str = NULL; gboolean check_probing_done = FALSE; + char buf[ETH_ALEN * 3]; switch (event->event) { case N_ACD_EVENT_READY: @@ -202,8 +203,9 @@ acd_event(int fd, GIOCondition condition, gpointer data) nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), acd_error_to_string(r)); } else { - _LOGD("announcing address %s", - _nm_utils_inet4_ntop(info->address, address_str)); + _LOGD("announcing address %s (hw-addr %s)", + _nm_utils_inet4_ntop(info->address, address_str), + _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf))); } } check_probing_done = TRUE; @@ -394,6 +396,7 @@ nm_acd_manager_announce_addresses(NMAcdManager *self) int r; int fd; gboolean success = TRUE; + char buf[ETH_ALEN * 3]; r = acd_init(self); if (r) { @@ -428,7 +431,9 @@ nm_acd_manager_announce_addresses(NMAcdManager *self) acd_error_to_string(r)); success = FALSE; } else - _LOGD("announcing address %s", _nm_utils_inet4_ntop(info->address, sbuf)); + _LOGD("announcing address %s (hw-addr %s)", + _nm_utils_inet4_ntop(info->address, sbuf), + _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf))); } } diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index f68c080b..9c1c484f 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -34,7 +34,7 @@ NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, \ NM_SETTING_BOND_OPTION_RESEND_IGMP, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, \ NM_SETTING_BOND_OPTION_USE_CARRIER, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, \ - NM_SETTING_BOND_OPTION_NUM_GRAT_ARP + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY #define OPTIONS_REAPPLY_SUBSET \ NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_UPDELAY, \ @@ -46,7 +46,7 @@ NM_SETTING_BOND_OPTION_MIN_LINKS, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, \ NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, NM_SETTING_BOND_OPTION_RESEND_IGMP, \ NM_SETTING_BOND_OPTION_USE_CARRIER, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, \ - NM_SETTING_BOND_OPTION_NUM_GRAT_ARP + NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY #define OPTIONS_REAPPLY_FULL \ OPTIONS_REAPPLY_SUBSET, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, \ @@ -109,6 +109,24 @@ _set_bond_attr(NMDevice *device, const char *attr, const char *value) int ifindex = nm_device_get_ifindex(device); gboolean ret; + nm_assert(attr && attr[0]); + nm_assert(value); + + if (nm_streq(value, NM_BOND_AD_ACTOR_SYSTEM_DEFAULT) + && nm_streq(attr, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) { + gs_free char *cur_val = NULL; + + /* kernel does not allow setting ad_actor_system to "00:00:00:00:00:00". We would thus + * log an EINVAL error. Avoid that... at least, if the value is already "00:00:00:00:00:00". */ + cur_val = + nm_platform_sysctl_master_get_option(nm_device_get_platform(device), ifindex, attr); + if (nm_streq0(cur_val, NM_BOND_AD_ACTOR_SYSTEM_DEFAULT)) + return TRUE; + + /* OK, the current value is different, and we will proceed setting "00:00:00:00:00:00". + * That will fail, and we will log a warning. There is nothing else to do. */ + } + ret = nm_platform_sysctl_master_set_option(nm_device_get_platform(device), ifindex, attr, value); if (!ret) @@ -426,9 +444,10 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) _LOGD(LOGD_BOND, "bond slave %s is already released", nm_device_get_ip_iface(slave)); if (configure) { - /* When the last slave is released the bond MAC will be set to a random - * value by kernel; remember the current one and restore it afterwards. - */ + NMConnection * applied; + NMSettingWired *s_wired; + const char * cloned_mac; + address = g_strdup(nm_device_get_hw_address(device)); if (ifindex_slave > 0) { @@ -443,9 +462,16 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) } } - nm_platform_process_events(nm_device_get_platform(device)); - if (nm_device_update_hw_address(device)) - nm_device_hw_addr_set(device, address, "restore", FALSE); + if ((applied = nm_device_get_applied_connection(device)) + && ((s_wired = nm_connection_get_setting_wired(applied))) + && ((cloned_mac = nm_setting_wired_get_cloned_mac_address(s_wired)))) { + /* When the last slave is released the bond MAC will be set to a random + * value by kernel; if we have set a cloned-mac-address, we need to + * restore it to the previous value. */ + nm_platform_process_events(nm_device_get_platform(device)); + if (nm_device_update_hw_address(device)) + nm_device_hw_addr_set(device, address, "restore", FALSE); + } /* Kernel bonding code "closes" the slave when releasing it, (which clears * IFF_UP), so we must bring it back up here to ensure carrier changes and diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 44428869..59f6c613 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -730,7 +730,9 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { supplicant_interface_release(self); - wired_auth_cond_fail(self, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + nm_device_state_changed(NM_DEVICE(self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); return; } diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 040dd0b4..3874e586 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -125,7 +125,6 @@ typedef struct { typedef struct { NMDevice *device; guint idle_add_id; - int ifindex; } DeleteOnDeactivateData; typedef struct { @@ -4703,10 +4702,6 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co */ nm_device_update_hw_address(self); - /* Send ARP announcements if did not yet and have addresses. */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !priv->acd.announcing) - nm_device_arp_announce(self); - /* Restart IP configuration if we're waiting for slaves. Do this * after updating the hardware address as IP config may need the * new address. @@ -5053,6 +5048,10 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier) nm_device_remove_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); _carrier_wait_check_queued_act_request(self); } + + /* Send ARP announcements if did not yet and have carrier. */ + if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !priv->acd.announcing) + nm_device_arp_announce(self); } else { if (priv->carrier_wait_id) nm_device_add_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); @@ -5415,11 +5414,11 @@ device_link_changed(NMDevice *self) /* Ensure the assume check is queued before any queued state changes * from the transition to UNAVAILABLE. */ - nm_device_queue_recheck_assume(self); reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; } } + nm_device_queue_recheck_assume(self); nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); } @@ -8362,26 +8361,23 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) static gboolean tc_commit(NMDevice *self) { - NMConnection * connection = NULL; gs_unref_ptrarray GPtrArray *qdiscs = NULL; gs_unref_ptrarray GPtrArray *tfilters = NULL; - NMSettingTCConfig * s_tc = NULL; + NMSettingTCConfig * s_tc; NMPlatform * platform; int ip_ifindex; - platform = nm_device_get_platform(self); - connection = nm_device_get_applied_connection(self); - if (connection) - s_tc = nm_connection_get_setting_tc_config(connection); + s_tc = nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG); + if (!s_tc) + return TRUE; ip_ifindex = nm_device_get_ip_ifindex(self); if (!ip_ifindex) - return s_tc == NULL; + return FALSE; - if (s_tc) { - qdiscs = nm_utils_qdiscs_from_tc_setting(platform, s_tc, ip_ifindex); - tfilters = nm_utils_tfilters_from_tc_setting(platform, s_tc, ip_ifindex); - } + platform = nm_device_get_platform(self); + qdiscs = nm_utils_qdiscs_from_tc_setting(platform, s_tc, ip_ifindex); + tfilters = nm_utils_tfilters_from_tc_setting(platform, s_tc, ip_ifindex); if (!nm_platform_qdisc_sync(platform, ip_ifindex, qdiscs)) return FALSE; @@ -9980,7 +9976,9 @@ nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes) _LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %d prefixes", needed_prefixes); nm_device_dhcp6_renew(self, FALSE); } else { - _LOGI(LOGD_IP6, "ipv6-pd: device doesn't use DHCPv6, can't request prefixes"); + priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF; + _LOGD(LOGD_DEVICE | LOGD_DHCP6, "ipv6-pd: starting DHCPv6 to request a prefix"); + dhcp6_start(self, FALSE); } } @@ -11679,8 +11677,6 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error) nm_utils_share_rules_add_all_rules(share_rules, ip_iface, ip4_addr->address, ip4_addr->plen); - nm_utils_share_rules_apply(share_rules, TRUE); - nm_act_request_set_shared(req, share_rules); conn = nm_act_request_get_applied_connection(req); @@ -11792,7 +11788,6 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) const char * method; int ip_ifindex; int errsv; - gboolean do_announce = FALSE; req = nm_device_get_act_request(self); g_assert(req); @@ -11918,31 +11913,13 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) } } - if (IS_IPv4) { - /* Send ARP announcements */ - - if (nm_device_is_master(self)) { - CList * iter; - SlaveInfo *info; - - /* Skip announcement if there are no device enslaved, for two reasons: - * 1) the master has a temporary MAC address until the first slave comes - * 2) announcements are going to be dropped anyway without slaves - */ - do_announce = FALSE; - - c_list_for_each (iter, &priv->slaves) { - info = c_list_entry(iter, SlaveInfo, lst_slave); - if (info->slave_is_enslaved) { - do_announce = TRUE; - break; - } - } - } else - do_announce = TRUE; - - if (do_announce) - nm_device_arp_announce(self); + if (IS_IPv4 && priv->carrier) { + /* We send ARP announcements only when the link gets carrier, + * otherwise the announcements would be lost. Furthermore, for + * controllers having carrier implies that there is at least one + * port and therefore the MAC address is the correct one. + */ + nm_device_arp_announce(self); } if (IS_IPv4) { @@ -12141,28 +12118,19 @@ nm_device_is_nm_owned(NMDevice *self) static gboolean delete_on_deactivate_link_delete(gpointer user_data) { - DeleteOnDeactivateData *data = user_data; - NMDevice * self = data->device; + DeleteOnDeactivateData *data = user_data; + nm_auto_unref_object NMDevice *self = data->device; + NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + gs_free_error GError *error = NULL; _LOGD(LOGD_DEVICE, - "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)", - data->ifindex, + "delete_on_deactivate: cleanup and delete virtual link (id=%u)", data->idle_add_id); - if (data->device) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(data->device); - gs_free_error GError *error = NULL; - - g_object_remove_weak_pointer(G_OBJECT(data->device), (void **) &data->device); - priv->delete_on_deactivate_data = NULL; + priv->delete_on_deactivate_data = NULL; - if (!nm_device_unrealize(data->device, TRUE, &error)) - _LOGD(LOGD_DEVICE, - "delete_on_deactivate: unrealizing %d failed (%s)", - data->ifindex, - error->message); - } else if (data->ifindex > 0) - nm_platform_link_delete(nm_device_get_platform(self), data->ifindex); + if (!nm_device_unrealize(self, TRUE, &error)) + _LOGD(LOGD_DEVICE, "delete_on_deactivate: unrealizing failed (%s)", error->message); nm_device_emit_recheck_auto_activate(self); @@ -12181,17 +12149,16 @@ delete_on_deactivate_unschedule(NMDevice *self) priv->delete_on_deactivate_data = NULL; g_source_remove(data->idle_add_id); - g_object_remove_weak_pointer(G_OBJECT(self), (void **) &data->device); _LOGD(LOGD_DEVICE, - "delete_on_deactivate: cancel cleanup and delete virtual link #%d (id=%u)", - data->ifindex, + "delete_on_deactivate: cancel cleanup and delete virtual link (id=%u)", data->idle_add_id); + g_object_unref(data->device); g_free(data); } } static void -delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex) +delete_on_deactivate_check_and_schedule(NMDevice *self) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); DeleteOnDeactivateData *data; @@ -12208,16 +12175,13 @@ delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex) return; delete_on_deactivate_unschedule(self); /* always cancel and reschedule */ - data = g_new(DeleteOnDeactivateData, 1); - g_object_add_weak_pointer(G_OBJECT(self), (void **) &data->device); - data->device = self; - data->ifindex = ifindex; + data = g_new(DeleteOnDeactivateData, 1); + data->device = g_object_ref(self); data->idle_add_id = g_idle_add(delete_on_deactivate_link_delete, data); priv->delete_on_deactivate_data = data; _LOGD(LOGD_DEVICE, - "delete_on_deactivate: schedule cleanup and delete virtual link #%d (id=%u)", - ifindex, + "delete_on_deactivate: schedule cleanup and delete virtual link (id=%u)", data->idle_add_id); } @@ -13478,12 +13442,13 @@ nm_device_set_ip_config(NMDevice * self, gboolean commit, GPtrArray * ip4_dev_route_blacklist) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMIPConfig * old_config; - gboolean has_changes = FALSE; - gboolean success = TRUE; - NMSettingsConnection *settings_connection; + NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMIPConfig * old_config; + gboolean has_changes = FALSE; + gboolean success = TRUE; + NMSettingsConnection * settings_connection; + NMIPRouteTableSyncMode route_table_sync_mode; nm_assert_addr_family(addr_family); nm_assert(!new_config || nm_ip_config_get_addr_family(new_config) == addr_family); @@ -13495,11 +13460,18 @@ nm_device_set_ip_config(NMDevice * self, }))); nm_assert(IS_IPv4 || !ip4_dev_route_blacklist); + if (commit && new_config) + route_table_sync_mode = _get_route_table_sync_mode_stateful(self, addr_family); + else + route_table_sync_mode = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE; + _LOGD(LOGD_IPX(IS_IPv4), - "ip%c-config: update (commit=%d, new-config=%p)", + "ip%c-config: update (commit=%d, new-config=" NM_HASH_OBFUSCATE_PTR_FMT + ", route-table-sync-mode=%d)", nm_utils_addr_family_to_char(addr_family), commit, - new_config); + NM_HASH_OBFUSCATE_PTR(new_config), + (int) route_table_sync_mode); /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { @@ -13508,7 +13480,7 @@ nm_device_set_ip_config(NMDevice * self, if (IS_IPv4) { success = nm_ip4_config_commit(NM_IP4_CONFIG(new_config), nm_device_get_platform(self), - _get_route_table_sync_mode_stateful(self, AF_INET)); + route_table_sync_mode); nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self), nm_ip_config_get_ifindex(new_config), ip4_dev_route_blacklist); @@ -13517,7 +13489,7 @@ nm_device_set_ip_config(NMDevice * self, success = nm_ip6_config_commit(NM_IP6_CONFIG(new_config), nm_device_get_platform(self), - _get_route_table_sync_mode_stateful(self, AF_INET6), + route_table_sync_mode, &temporary_not_available); if (!_rt6_temporary_not_available_set(self, temporary_not_available)) @@ -15846,7 +15818,7 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type) /* Check if the device was deactivated, and if so, delete_link. * Don't call delete_link synchronously because we are currently * handling a state change -- which is not reentrant. */ - delete_on_deactivate_check_and_schedule(self, nm_device_get_ip_ifindex(self)); + delete_on_deactivate_check_and_schedule(self); } /* ip_iface should be cleared after flushing all routes and addresses, since @@ -15906,9 +15878,12 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu nm_platform_ip_route_flush(platform, AF_UNSPEC, ifindex); nm_platform_ip_address_flush(platform, AF_UNSPEC, ifindex); - nm_platform_tfilter_sync(platform, ifindex, NULL); - nm_platform_qdisc_sync(platform, ifindex, NULL); set_ipv6_token(self, iid, "::"); + + if (nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG)) { + nm_platform_tfilter_sync(platform, ifindex, NULL); + nm_platform_qdisc_sync(platform, ifindex, NULL); + } } } diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index 72777d0a..68343ef5 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -627,27 +627,28 @@ void nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device); * setting the NM_UNMANAGED_IS_SLAVE to %TRUE makes no sense, this flag has only * meaning to set a slave device as managed if the parent is managed too. */ -typedef enum { /*< skip >*/ - NM_UNMANAGED_NONE = 0, +typedef enum { + NM_UNMANAGED_NONE = 0, - /* these flags are authoritative. If one of them is set, + /* these flags are authoritative. If one of them is set, * the device cannot be managed. */ - NM_UNMANAGED_SLEEPING = (1LL << 0), - NM_UNMANAGED_QUITTING = (1LL << 1), - NM_UNMANAGED_PARENT = (1LL << 2), - NM_UNMANAGED_BY_TYPE = (1LL << 3), - NM_UNMANAGED_PLATFORM_INIT = (1LL << 4), - NM_UNMANAGED_USER_EXPLICIT = (1LL << 5), - NM_UNMANAGED_USER_SETTINGS = (1LL << 6), - - /* These flags can be non-effective and be overwritten + NM_UNMANAGED_SLEEPING = (1LL << 0), + NM_UNMANAGED_QUITTING = (1LL << 1), + NM_UNMANAGED_PARENT = (1LL << 2), + NM_UNMANAGED_BY_TYPE = (1LL << 3), + NM_UNMANAGED_PLATFORM_INIT = (1LL << 4), + NM_UNMANAGED_USER_EXPLICIT = (1LL << 5), + NM_UNMANAGED_USER_SETTINGS = (1LL << 6), + + /* These flags can be non-effective and be overwritten * by other flags. */ - NM_UNMANAGED_BY_DEFAULT = (1LL << 8), - NM_UNMANAGED_USER_CONF = (1LL << 9), - NM_UNMANAGED_USER_UDEV = (1LL << 10), - NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 11), - NM_UNMANAGED_IS_SLAVE = (1LL << 12), + NM_UNMANAGED_BY_DEFAULT = (1LL << 7), + NM_UNMANAGED_USER_CONF = (1LL << 8), + NM_UNMANAGED_USER_UDEV = (1LL << 9), + NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 10), + NM_UNMANAGED_IS_SLAVE = (1LL << 11), + NM_UNMANAGED_ALL = ((1LL << 12) - 1), } NMUnmanagedFlags; typedef enum { diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 5d07c211..0a537f7a 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -77,6 +77,15 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) return nm_ovsdb_is_ready(priv->ovsdb); } +static gboolean +can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object) +{ + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + return nm_ovsdb_is_ready(priv->ovsdb); +} + static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { @@ -427,6 +436,7 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH); + device_class->can_auto_connect = can_auto_connect; device_class->can_update_from_platform_link = can_update_from_platform_link; device_class->deactivate = deactivate; device_class->deactivate_async = deactivate_async; diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 95ade44b..01f2a303 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -588,10 +588,16 @@ deactivate(NMDevice *device) return; } - cleanup_association_attempt(self, TRUE); + cleanup_association_attempt(self, FALSE); priv->act_mode_switch = FALSE; - if (!priv->dbus_station_proxy) + /* Don't trigger any actions on the IWD side until the device is managed */ + if (priv->iwd_autoconnect && nm_device_get_state(device) < NM_DEVICE_STATE_DISCONNECTED) + return; + + if (priv->dbus_station_proxy) + send_disconnect(self); + else reset_mode(self, NULL, NULL, NULL); } @@ -647,6 +653,11 @@ deactivate_async(NMDevice * device, cleanup_association_attempt(self, FALSE); priv->act_mode_switch = FALSE; + if (priv->iwd_autoconnect && nm_device_get_state(device) < NM_DEVICE_STATE_DISCONNECTED) { + nm_utils_invoke_on_idle(cancellable, disconnect_cb_on_idle, user_data); + return; + } + if (priv->dbus_station_proxy) { g_dbus_proxy_call(priv->dbus_station_proxy, "Disconnect", diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 042d4887..c9655eea 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -2565,6 +2565,7 @@ supplicant_iface_notify_current_bss(NMSupplicantInterface *iface, NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); NMRefString * current_bss; NMWifiAP * new_ap = NULL; + NMActRequest * req; current_bss = nm_supplicant_interface_get_current_bss(iface); if (current_bss) @@ -2612,6 +2613,13 @@ supplicant_iface_notify_current_bss(NMSupplicantInterface *iface, } set_current_ap(self, new_ap, TRUE); + + req = nm_device_get_act_request(NM_DEVICE(self)); + if (req) { + nm_active_connection_set_specific_object( + NM_ACTIVE_CONNECTION(req), + new_ap ? nm_dbus_object_get_path(NM_DBUS_OBJECT(new_ap)) : NULL); + } } } diff --git a/src/core/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index b4b019d3..68a74438 100644 --- a/src/core/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -1119,6 +1119,7 @@ object_compare_interfaces(gconstpointer a, gconstpointer b) NM_IWD_KNOWN_NETWORK_INTERFACE, NM_IWD_NETWORK_INTERFACE, NM_IWD_DEVICE_INTERFACE, + NULL, }; int rank_a = G_N_ELEMENTS(interface_order); int rank_b = G_N_ELEMENTS(interface_order); diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index ca028804..1297d964 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -369,10 +369,10 @@ static void connect_ready(MMModemSimple *simple_iface, GAsyncResult *res, NMModemBroadband *self) { ConnectContext *ctx; - GError * error = NULL; - NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; - NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - MMBearer * bearer; + GError * error = NULL; + NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; + NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; + gs_unref_object MMBearer *bearer = NULL; bearer = mm_modem_simple_connect_finish(simple_iface, res, &error); @@ -386,7 +386,7 @@ connect_ready(MMModemSimple *simple_iface, GAsyncResult *res, NMModemBroadband * if (!ctx) return; - self->_priv.bearer = bearer; + self->_priv.bearer = g_steal_pointer(&bearer); if (!self->_priv.bearer) { if (g_error_matches(error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index c38c814e..3b0343fd 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -84,6 +84,11 @@ G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) /*****************************************************************************/ +/* we use pid=-1 for invalid PIDs. Ensure that pid_t can hold negative values. */ +G_STATIC_ASSERT(!(((pid_t) -1) > 0)); + +/*****************************************************************************/ + pid_t nm_dhcp_client_get_pid(NMDhcpClient *self) { @@ -749,7 +754,7 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) _LOGI("canceled DHCP transaction"); nm_assert(priv->pid == -1); - nm_dhcp_client_set_state(self, NM_DHCP_STATE_DONE, NULL, NULL); + nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL); } /*****************************************************************************/ diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index 72ab477d..af3406cc 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -51,7 +51,7 @@ typedef enum { NM_DHCP_STATE_BOUND, /* new lease */ NM_DHCP_STATE_EXTENDED, /* lease extended */ NM_DHCP_STATE_TIMEOUT, /* timed out contacting server */ - NM_DHCP_STATE_DONE, /* client quit or stopped */ + NM_DHCP_STATE_DONE, /* client reported it's stopping */ NM_DHCP_STATE_EXPIRE, /* lease expired or NAKed */ NM_DHCP_STATE_FAIL, /* failed for some reason */ NM_DHCP_STATE_TERMINATED, /* client is no longer running */ diff --git a/src/core/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c index cf9fe5c2..cdb266ed 100644 --- a/src/core/dhcp/nm-dhcp-dhcpcd.c +++ b/src/core/dhcp/nm-dhcp-dhcpcd.c @@ -169,27 +169,29 @@ stop(NMDhcpClient *client, gboolean release) int sig, errsv; pid = nm_dhcp_client_get_pid(client); - sig = release ? SIGALRM : SIGTERM; - _LOGD("sending %s to dhcpcd pid %d", sig == SIGALRM ? "SIGALRM" : "SIGTERM", pid); - - /* dhcpcd-9.x features privilege separation. - * It's not our job to track all these processes so we rely on dhcpcd - * to always cleanup after itself. - * Because it also re-parents itself to PID 1, the process cannot be - * reaped or waited for. - * As such, just send the correct signal. - */ - if (kill(pid, sig) == -1) { - errsv = errno; - _LOGE("failed to kill dhcpcd %d:%s", errsv, strerror(errsv)); - } + if (pid > 1) { + sig = release ? SIGALRM : SIGTERM; + _LOGD("sending %s to dhcpcd pid %d", sig == SIGALRM ? "SIGALRM" : "SIGTERM", pid); + + /* dhcpcd-9.x features privilege separation. + * It's not our job to track all these processes so we rely on dhcpcd + * to always cleanup after itself. + * Because it also re-parents itself to PID 1, the process cannot be + * reaped or waited for. + * As such, just send the correct signal. + */ + if (kill(pid, sig) == -1) { + errsv = errno; + _LOGE("failed to kill dhcpcd %d:%s", errsv, strerror(errsv)); + } - /* When this function exits NM expects the PID to be -1. - * This means we also need to stop watching the pid. - * If we need to know the exit status then we need to refactor NM - * to allow a non -1 to mean we're waiting to exit still. - */ - nm_dhcp_client_stop_watch_child(client, pid); + /* When this function exits NM expects the PID to be -1. + * This means we also need to stop watching the pid. + * If we need to know the exit status then we need to refactor NM + * to allow a non -1 to mean we're waiting to exit still. + */ + nm_dhcp_client_stop_watch_child(client, pid); + } } /*****************************************************************************/ diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index 116e1bdb..c8b80ea6 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -342,16 +342,16 @@ lease_parse_routes(NDhcp4ClientLease *lease, const guint8 *l_data; gsize l_data_len; int r; + guint i; - r = _client_lease_query(lease, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - &l_data, - &l_data_len); - if (r == 0) { - nm_str_buf_reset(sbuf); + for (i = 0; i < 2; i++) { + const guint8 option_code = (i == 0) ? NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE + : NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE; - has_classless = TRUE; + if (_client_lease_query(lease, option_code, &l_data, &l_data_len) != 0) + continue; + nm_str_buf_reset(sbuf); while (lease_option_consume_route(&l_data, &l_data_len, TRUE, &dest, &plen, &gateway)) { _nm_utils_inet4_ntop(dest, dest_str); _nm_utils_inet4_ntop(gateway, gateway_str); @@ -359,6 +359,11 @@ lease_parse_routes(NDhcp4ClientLease *lease, nm_str_buf_append_required_delimiter(sbuf, ' '); nm_str_buf_append_printf(sbuf, "%s/%d %s", dest_str, (int) plen, gateway_str); + if (has_classless) { + /* Ignore private option if the standard one is present */ + continue; + } + if (plen == 0) { /* if there are multiple default routes, we add them with differing * metrics. */ @@ -384,10 +389,8 @@ lease_parse_routes(NDhcp4ClientLease *lease, NULL); } - nm_dhcp_option_add_option(options, - AF_INET, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - nm_str_buf_get_str(sbuf)); + has_classless = TRUE; + nm_dhcp_option_add_option(options, AF_INET, option_code, nm_str_buf_get_str(sbuf)); } r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, &l_data, &l_data_len); @@ -693,8 +696,8 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, v_str = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free); - nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str); - nm_ip4_config_set_nis_domain(ip4_config, v_str); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str ?: ""); + nm_ip4_config_set_nis_domain(ip4_config, v_str ?: ""); } lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf); diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index b92a9073..100807aa 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -85,29 +85,29 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, const struct in_addr * addr_list; char addr_str[NM_UTILS_INET_ADDRSTRLEN]; const char * s; - nm_auto_free_gstring GString *str = NULL; - gs_free sd_dhcp_route **routes = NULL; - const char *const * search_domains = NULL; - guint16 mtu; - int i, num; - const void * data; - gsize data_len; - gboolean metered = FALSE; - gboolean has_router_from_classless = FALSE; - gboolean has_classless_route = FALSE; - gboolean has_static_route = FALSE; - const gint32 ts = nm_utils_get_monotonic_timestamp_sec(); - gint64 ts_time = time(NULL); - struct in_addr a_address; - struct in_addr a_netmask; - struct in_addr a_next_server; - struct in_addr server_id; - struct in_addr broadcast; - const struct in_addr * a_router; - guint32 a_plen; - guint32 a_lifetime; - guint32 renewal; - guint32 rebinding; + nm_auto_free_gstring GString *str = NULL; + nm_auto_free sd_dhcp_route **routes = NULL; + const char *const * search_domains = NULL; + guint16 mtu; + int i, num; + const void * data; + gsize data_len; + gboolean metered = FALSE; + gboolean has_router_from_classless = FALSE; + gboolean has_classless_route = FALSE; + gboolean has_static_route = FALSE; + const gint32 ts = nm_utils_get_monotonic_timestamp_sec(); + gint64 ts_time = time(NULL); + struct in_addr a_address; + struct in_addr a_netmask; + struct in_addr a_next_server; + struct in_addr server_id; + struct in_addr broadcast; + const struct in_addr * a_router; + guint32 a_plen; + guint32 a_lifetime; + guint32 renewal; + guint32 rebinding; gs_free nm_sd_dhcp_option *private_options = NULL; nm_assert(lease != NULL); diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 646411e2..63d90641 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -880,7 +880,7 @@ nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_l n_data--; if (n_data > 0) { - if (memchr(data, n_data, '\0')) { + if (memchr(data, '\0', n_data)) { /* we accept trailing NUL, but none in between. * * https://tools.ietf.org/html/rfc2132#section-2 diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index f318b9b8..59c8898a 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1624,7 +1624,7 @@ _mgr_configs_data_clear(NMDnsManager *self) /*****************************************************************************/ static gboolean -update_dns(NMDnsManager *self, gboolean no_caching, GError **error) +update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError **error) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); const char * nis_domain = NULL; @@ -1815,8 +1815,8 @@ plugin_skip:; NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED); } - /* signal that resolv.conf was changed */ - if (do_update && result == SR_SUCCESS) + /* signal that DNS resolution configs were changed */ + if ((do_update || caching || force_emit) && result == SR_SUCCESS) g_signal_emit(self, signals[CONFIG_CHANGED], 0); nm_clear_pointer(&priv->config_variant, g_variant_unref); @@ -1924,7 +1924,7 @@ changed: if (!priv->updates_queue) { gs_free_error GError *error = NULL; - if (!update_dns(self, FALSE, &error)) + if (!update_dns(self, FALSE, FALSE, &error)) _LOGW("could not commit DNS changes: %s", error->message); } @@ -1965,7 +1965,7 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s if (!priv->updates_queue) { gs_free_error GError *error = NULL; - if (!update_dns(self, FALSE, &error)) + if (!update_dns(self, FALSE, FALSE, &error)) _LOGW("could not commit DNS changes: %s", error->message); } } @@ -2012,7 +2012,7 @@ nm_dns_manager_end_updates(NMDnsManager *self, const char *func) /* Commit all the outstanding changes */ _LOGD("(%s): committing DNS changes (%d)", func, priv->updates_queue); - if (!update_dns(self, FALSE, &error)) + if (!update_dns(self, FALSE, FALSE, &error)) _LOGW("could not commit DNS changes: %s", error->message); memset(priv->prev_hash, 0, sizeof(priv->prev_hash)); @@ -2038,7 +2038,7 @@ nm_dns_manager_stop(NMDnsManager *self) if (priv->dns_touched && priv->plugin && NM_IS_DNS_DNSMASQ(priv->plugin)) { gs_free_error GError *error = NULL; - if (!update_dns(self, TRUE, &error)) + if (!update_dns(self, TRUE, FALSE, &error)) _LOGW("could not commit DNS changes on shutdown: %s", error->message); priv->dns_touched = FALSE; @@ -2363,7 +2363,7 @@ config_changed_cb(NMConfig * config, | NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) { gs_free_error GError *error = NULL; - if (!update_dns(self, FALSE, &error)) + if (!update_dns(self, FALSE, TRUE, &error)) _LOGW("could not commit DNS changes: %s", error->message); } } diff --git a/src/core/initrd/nmi-cmdline-reader.c b/src/core/initrd/nmi-cmdline-reader.c index 508ef2b2..0a24199e 100644 --- a/src/core/initrd/nmi-cmdline-reader.c +++ b/src/core/initrd/nmi-cmdline-reader.c @@ -393,8 +393,9 @@ reader_read_all_connections_from_fw(Reader *reader, const char *sysfs_dir) static void reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) { - NMConnection * connection; - NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL; + NMConnection * connection; + NMSettingConnection *s_con; + NMSettingIPConfig * s_ip4 = NULL, *s_ip6 = NULL; gs_unref_hashtable GHashTable *ibft = NULL; const char * tmp; const char * tmp2; @@ -495,6 +496,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) g_hash_table_add(reader->explicit_ip_connections, g_object_ref(connection)); + s_con = nm_connection_get_setting_connection(connection); s_ip4 = nm_connection_get_setting_ip4_config(connection); s_ip6 = nm_connection_get_setting_ip6_config(connection); @@ -544,6 +546,12 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) nm_assert_not_reached(); if (address) { + /* We don't want to have multiple devices up with the + * same static address. */ + g_object_set(s_con, + NM_SETTING_CONNECTION_MULTI_CONNECT, + NM_CONNECTION_MULTI_CONNECT_SINGLE, + NULL); switch (client_ip_family) { case AF_INET: g_object_set(s_ip4, @@ -599,7 +607,12 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) NULL); } } else if (NM_IN_STRSET(kind, "auto6", "dhcp6")) { - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE, NULL); + g_object_set(s_ip6, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_MAY_FAIL, + FALSE, + NULL); if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) { g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, @@ -764,6 +777,9 @@ reader_parse_master(Reader *reader, char *argument, const char *type_name, const mtu = get_word(&argument, ':'); } + if (mtu) + connection_set(connection, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MTU, mtu); + do { slave = get_word(&slaves, ','); if (slave == NULL) @@ -777,8 +793,6 @@ reader_parse_master(Reader *reader, char *argument, const char *type_name, const NM_SETTING_CONNECTION_MASTER, master, NULL); - if (mtu) - connection_set(connection, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MTU, mtu); } while (slaves && *slaves != '\0'); if (argument && *argument) @@ -916,6 +930,11 @@ reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames) subchannels[0] = get_word(&argument, ','); subchannels[1] = get_word(&argument, ','); + /* Without subchannels we can't univocally match + * a device. */ + if (!subchannels[0] || !subchannels[1]) + return; + if (nm_streq0(nettype, "ctc")) { if (net_ifnames == TRUE) { prefix = "sl"; diff --git a/src/core/initrd/tests/test-cmdline-reader.c b/src/core/initrd/tests/test-cmdline-reader.c index 33fb22d3..e3a3753e 100644 --- a/src/core/initrd/tests/test-cmdline-reader.c +++ b/src/core/initrd/tests/test-cmdline-reader.c @@ -455,6 +455,46 @@ test_if_ip4_manual(void) g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); } +static void +test_if_ip4_manual_no_dev(void) +{ + const char *const * ARGV = NM_MAKE_STRV("ip=192.0.2.2::192.0.2.1:24:::"); + NMConnection * connection; + NMSettingConnection *s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + NMIPAddress * ip_addr; + + connection = _parse_con(ARGV, "default_connection"); + g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection"); + + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); + g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); + g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), + ==, + NM_CONNECTION_MULTI_CONNECT_SINGLE); + + s_ip4 = nm_connection_get_setting_ip4_config(connection); + g_assert(s_ip4); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL); + g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); + g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); + g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); + ip_addr = nm_setting_ip_config_get_address(s_ip4, 0); + g_assert(ip_addr); + g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "192.0.2.2"); + g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 24); + g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.0.2.1"); + + s_ip6 = nm_connection_get_setting_ip6_config(connection); + g_assert(s_ip6); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); +} + static void test_if_ip6_manual(void) { @@ -825,13 +865,14 @@ test_bond(void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const * ARGV = NM_MAKE_STRV("rd.route=192.0.2.53::bong0", - "bond=bong0:eth0,eth1:mode=balance-rr", + "bond=bong0:eth0,eth1:mode=balance-rr:9000", "nameserver=203.0.113.53"); NMConnection * connection; NMSettingConnection * s_con; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMSettingBond * s_bond; + NMSettingWired * s_wired; NMIPRoute * ip_route; const char * master_uuid; @@ -847,6 +888,10 @@ test_bond(void) master_uuid = nm_connection_get_uuid(connection); g_assert(master_uuid); + s_wired = nm_connection_get_setting_wired(connection); + g_assert(s_wired); + g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 9000); + s_ip4 = nm_connection_get_setting_ip4_config(connection); g_assert(s_ip4); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); @@ -1810,6 +1855,24 @@ test_rd_znet_no_ip(void) g_assert_cmpint(g_hash_table_size(connections), ==, 0); } +static void +test_rd_znet_malformed(void) +{ + const char *const *const ARGV0 = NM_MAKE_STRV("rd.znet="); + const char *const *const ARGV1 = NM_MAKE_STRV("rd.znet=,"); + const char *const *const ARGV2 = NM_MAKE_STRV("rd.znet=foobar"); + const char *const *const ARGV3 = NM_MAKE_STRV("rd.znet=qeth,0.0.0800,,,layer2=0,portno=1"); + const char *const *const ARGV[] = {ARGV0, ARGV1, ARGV2, ARGV3}; + guint i; + + for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + + connections = _parse_cons(ARGV[i]); + g_assert_cmpint(g_hash_table_size(connections), ==, 0); + } +} + static void test_bootif_ip(void) { @@ -2142,6 +2205,7 @@ main(int argc, char **argv) g_test_add_func("/initrd/cmdline/if_dhcp6", test_if_dhcp6); g_test_add_func("/initrd/cmdline/if_auto_with_mtu_and_mac", test_if_auto_with_mtu_and_mac); g_test_add_func("/initrd/cmdline/if_ip4_manual", test_if_ip4_manual); + g_test_add_func("/initrd/cmdline/if_ip4_manual_no_dev", test_if_ip4_manual_no_dev); g_test_add_func("/initrd/cmdline/if_ip6_manual", test_if_ip6_manual); g_test_add_func("/initrd/cmdline/if_mac_ifname", test_if_mac_ifname); g_test_add_func("/initrd/cmdline/if_off", test_if_off); @@ -2168,6 +2232,7 @@ main(int argc, char **argv) g_test_add_func("/initrd/cmdline/rd_znet", test_rd_znet); g_test_add_func("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy); g_test_add_func("/initrd/cmdline/rd_znet/no_ip", test_rd_znet_no_ip); + g_test_add_func("/initrd/cmdline/rd_znet/empty", test_rd_znet_malformed); g_test_add_func("/initrd/cmdline/bootif/ip", test_bootif_ip); g_test_add_func("/initrd/cmdline/bootif/no_ip", test_bootif_no_ip); g_test_add_func("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype); diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index c62c6773..d457f505 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -437,7 +437,7 @@ static NMAuthPolkitMode _config_data_get_main_auth_polkit(const NMConfigData *self, gboolean *out_invalid_config) { NMAuthPolkitMode auth_polkit_mode; - const char * str; + gs_free char * str = NULL; str = nm_config_data_get_value(self, NM_CONFIG_KEYFILE_GROUP_MAIN, diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 9075c30d..a27c50dc 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -1956,7 +1956,8 @@ nm_wildcard_match_check(const char *str, const char *const *patterns, guint num_ _pattern_parse(patterns[i], &p, &is_inverted, &is_mandatory); - match = (fnmatch(p, str, 0) == 0); + match = (fnmatch(p, str ?: "", 0) == 0); + if (is_inverted) match = !match; @@ -5065,9 +5066,12 @@ nm_wifi_utils_parse_ies(const guint8 *bytes, case WLAN_EID_VENDOR_SPECIFIC: if (len == 8 && bytes[0] == 0x00 /* OUI: Microsoft */ && bytes[1] == 0x50 && bytes[2] == 0xf2 - && bytes[3] == 0x11) /* OUI type: Network cost */ - NM_SET_OUT(out_metered, (bytes[7] > 1)); /* Cost level > 1 */ - if (elem_len >= 10 && bytes[0] == 0x50 /* OUI: WiFi Alliance */ + && bytes[3] == 0x11) /* OUI type: Network cost */ + { + /* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nct/ */ + NM_SET_OUT(out_metered, (bytes[4] > 1)); /* Cost level > 1 */ + } + if (elem_len >= 10 && bytes[0] == 0x50 /* OUI: WiFi Alliance */ && bytes[1] == 0x6f && bytes[2] == 0x9a && bytes[3] == 0x1c) /* OUI type: OWE Transition Mode */ NM_SET_OUT(out_owe_transition_mode, TRUE); diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c index c49dfb4c..608b7fc8 100644 --- a/src/core/nm-ip4-config.c +++ b/src/core/nm-ip4-config.c @@ -649,21 +649,6 @@ nm_ip4_config_add_dependent_routes(NMIP4Config *self, if (my_addr->external) continue; - /* Pre-generate local route added by kernel */ - r = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL); - route = NMP_OBJECT_CAST_IP4_ROUTE(r); - route->ifindex = ifindex; - route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL; - route->network = my_addr->address; - route->plen = 32; - route->pref_src = my_addr->address; - route->type_coerced = nm_platform_route_type_coerce(RTN_LOCAL); - route->scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST); - route->table_coerced = - nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL); - _add_route(self, r, NULL, NULL); - nm_clear_pointer(&r, nmp_object_unref); - if (nm_utils_ip4_address_is_zeronet(network)) { /* Kernel doesn't add device-routes for destinations that * start with 0.x.y.z. Skip them. */ diff --git a/src/core/nm-ip6-config.c b/src/core/nm-ip6-config.c index 1f7def34..1e36050d 100644 --- a/src/core/nm-ip6-config.c +++ b/src/core/nm-ip6-config.c @@ -396,23 +396,6 @@ nm_ip6_config_add_dependent_routes(NMIP6Config *self, * * For manually added IPv6 routes, add the device routes explicitly. */ - /* Pre-generate multicast route */ - { - nm_auto_nmpobj NMPObject *r = NULL; - NMPlatformIP6Route * route; - - r = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL); - route = NMP_OBJECT_CAST_IP6_ROUTE(r); - route->ifindex = ifindex; - route->network.s6_addr[0] = 0xffu; - route->plen = 8; - route->table_coerced = nm_platform_route_table_coerce(RT_TABLE_LOCAL); - route->type_coerced = nm_platform_route_type_coerce(RTN_UNICAST); - route->metric = 256; - - _add_route(self, r, NULL, NULL); - } - nm_ip_config_iter_ip6_address_for_each (&iter, self, &my_addr) { NMPlatformIP6Route *route; gboolean has_peer; @@ -421,22 +404,6 @@ nm_ip6_config_add_dependent_routes(NMIP6Config *self, if (my_addr->external) continue; - { - nm_auto_nmpobj NMPObject *r = NULL; - - /* Pre-generate local route added by kernel */ - r = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL); - route = NMP_OBJECT_CAST_IP6_ROUTE(r); - route->ifindex = ifindex; - route->network = my_addr->address; - route->plen = 128; - route->type_coerced = nm_platform_route_type_coerce(RTN_LOCAL); - route->metric = 0; - route->table_coerced = - nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL); - _add_route(self, r, NULL, NULL); - } - if (NM_FLAGS_HAS(my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE)) continue; if (my_addr->plen == 0) diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 5a6e05a9..f44306e1 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -363,6 +363,7 @@ static NMActiveConnection *active_connection_find(NMManager * self, NMSettingsConnection * sett_conn, const char * uuid, NMActiveConnectionState max_state, + gboolean also_waiting_auth, GPtrArray ** out_all_matching); static NMConnectivity *concheck_get_mgr(NMManager *self); @@ -833,6 +834,7 @@ _delete_volatile_connection_do(NMManager *self, NMSettingsConnection *connection connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, + TRUE, NULL)) return; @@ -978,6 +980,7 @@ active_connection_find( NMSettingsConnection * sett_conn, const char * uuid, NMActiveConnectionState max_state /* candidates in state @max_state will be found */, + gboolean also_waiting_auth /* return also ACs waiting authorization */, GPtrArray ** out_all_matching) { NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); @@ -1017,11 +1020,14 @@ active_connection_find( if (!best_ac) { AsyncOpData *async_op_data; + if (!also_waiting_auth) + return NULL; + c_list_for_each_entry (async_op_data, &priv->async_op_lst_head, async_op_lst) { NMSettingsConnection *ac_conn; ac = async_op_data->ac_auth.active; - ac_conn = nm_active_connection_get_settings_connection(ac); + ac_conn = _nm_active_connection_get_settings_connection(ac); if (sett_conn && sett_conn != ac_conn) continue; if (uuid && !nm_streq0(uuid, nm_settings_connection_get_uuid(ac_conn))) @@ -1078,6 +1084,7 @@ active_connection_find_by_connection(NMManager * self, sett_conn, sett_conn ? NULL : nm_connection_get_uuid(connection), max_state, + FALSE, out_all_matching); } @@ -1112,6 +1119,7 @@ _get_activatable_connections_filter(NMSettings * settings, sett_conn, NULL, NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + FALSE, NULL); } @@ -2245,6 +2253,7 @@ connection_flags_changed(NMSettings *settings, NMSettingsConnection *connection, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, + FALSE, NULL)) { /* the connection still has an active-connection. It will be purged * when the active connection(s) get(s) removed. */ @@ -2564,6 +2573,7 @@ new_activation_allowed_for_connection(NMManager *self, NMSettingsConnection *con connection, NULL, NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + FALSE, NULL); } @@ -2839,14 +2849,16 @@ recheck_assume_connection(NMManager *self, NMDevice *device) g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); if (!nm_device_get_managed(device, FALSE)) { - nm_device_assume_state_reset(device); + /* If the device is only unmanaged by NM_UNMANAGED_PLATFORM_INIT, + * don't reset the state now but wait until it becomes managed. */ + if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_ALL) != NM_UNMANAGED_PLATFORM_INIT) + nm_device_assume_state_reset(device); _LOG2D(LOGD_DEVICE, device, "assume: don't assume because %s", "not managed"); return FALSE; } state = nm_device_get_state(device); if (state > NM_DEVICE_STATE_DISCONNECTED) { - nm_device_assume_state_reset(device); _LOG2D(LOGD_DEVICE, device, "assume: don't assume due to device state %s", @@ -3161,7 +3173,10 @@ _device_realize_finish(NMManager *self, NMDevice *device, const NMPlatformLink * nm_device_realize_finish(device, plink); if (!nm_device_get_managed(device, FALSE)) { - nm_device_assume_state_reset(device); + /* If the device is only unmanaged by NM_UNMANAGED_PLATFORM_INIT, + * don't reset the state now but wait until it becomes managed. */ + if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_ALL) != NM_UNMANAGED_PLATFORM_INIT) + nm_device_assume_state_reset(device); return; } @@ -3509,6 +3524,45 @@ typedef struct { guint idle_id; } PlatformLinkCbData; +static gboolean +_check_remove_dev_on_link_deleted(NMManager *self, NMDevice *device) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSettingsConnection *const *scons = NULL; + NMConnection * con; + guint i; + + nm_assert(nm_device_is_software(device)); + + /* In general, software devices stick around as unrealized + * until their connection is removed. However, we don't want + * that a NM-generated connection keeps the device alive. + * If there are no other compatible connections, the device + * should be also removed. + */ + + scons = nm_settings_get_connections(priv->settings, NULL); + + for (i = 0; scons[i]; i++) { + con = nm_settings_connection_get_connection(scons[i]); + if (!nm_connection_is_virtual(con)) + continue; + + if (NM_FLAGS_HAS(nm_settings_connection_get_flags(scons[i]), + NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) + continue; + + if (!nm_device_check_connection_compatible(device, con, NULL)) + continue; + + /* Found a virtual connection compatible, the device must + * stay around unrealized. */ + return FALSE; + } + + return TRUE; +} + static gboolean _platform_link_cb_idle(PlatformLinkCbData *data) { @@ -3534,13 +3588,15 @@ _platform_link_cb_idle(PlatformLinkCbData *data) if (device) { if (nm_device_is_software(device)) { nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); - /* Our software devices stick around until their connection is removed */ if (!nm_device_unrealize(device, FALSE, &error)) { _LOG2W(LOGD_DEVICE, device, "failed to unrealize: %s", error->message); g_clear_error(&error); remove_device(self, device, FALSE); } else { - nm_device_update_from_platform_link(device, NULL); + if (_check_remove_dev_on_link_deleted(self, device)) + remove_device(self, device, FALSE); + else + nm_device_update_from_platform_link(device, NULL); } } else { /* Hardware and external devices always get removed when their kernel link is gone */ @@ -4134,6 +4190,7 @@ find_master(NMManager * self, master_connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, + FALSE, NULL); } @@ -4985,6 +5042,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError ** sett_conn, NULL, NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + FALSE, &all_ac_arr); if (ac) { n_all = all_ac_arr ? all_ac_arr->len : ((guint) 1); diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index db4983f8..71aa1ece 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -652,6 +652,7 @@ device_hostname_info_compare(gconstpointer a, gconstpointer b) NM_CMP_FIELD(info1, info2, priority); NM_CMP_FIELD_UNSAFE(info2, info1, is_default); + NM_CMP_FIELD_UNSAFE(info2, info1, IS_IPv4); return 0; } diff --git a/src/core/nm-types.h b/src/core/nm-types.h index ab231459..8a32b7d2 100644 --- a/src/core/nm-types.h +++ b/src/core/nm-types.h @@ -245,12 +245,16 @@ typedef enum { * local table (255). * @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL: NM will sync all tables, including the * local table (255). + * @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE: NM will sync all tables (including + * the local table). It will thereby remove all addresses, that is during + * deactivation. */ typedef enum { - NM_IP_ROUTE_TABLE_SYNC_MODE_NONE = 0, - NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN = 1, - NM_IP_ROUTE_TABLE_SYNC_MODE_FULL = 2, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL = 3, + NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, + NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, + NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL, + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE, } NMIPRouteTableSyncMode; /* settings */ diff --git a/src/core/platform/nm-platform.c b/src/core/platform/nm-platform.c index 0e5f8ab5..459a3307 100644 --- a/src/core/platform/nm-platform.c +++ b/src/core/platform/nm-platform.c @@ -4357,34 +4357,134 @@ nm_platform_ip_route_get_prune_list(NMPlatform * self, GPtrArray * routes_prune; const NMDedupMultiHeadEntry *head_entry; CList * iter; + NMPlatformIP4Route rt_local4; + NMPlatformIP6Route rt_local6; + const NMPlatformLink * pllink; + const NMPlatformLnkVrf * lnk_vrf; + guint32 local_table; nm_assert(NM_IS_PLATFORM(self)); nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); nm_assert(NM_IN_SET(route_table_sync, NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL)); + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL, + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE)); nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)), ifindex); head_entry = nm_platform_lookup(self, &lookup); if (!head_entry) return NULL; + lnk_vrf = nm_platform_link_get_lnk_vrf(self, ifindex, &pllink); + if (!lnk_vrf && pllink && pllink->master > 0) + lnk_vrf = nm_platform_link_get_lnk_vrf(self, pllink->master, NULL); + local_table = lnk_vrf ? lnk_vrf->table : RT_TABLE_LOCAL; + + rt_local4.plen = 0; + rt_local6.plen = 0; + routes_prune = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref); c_list_for_each (iter, &head_entry->lst_entries_head) { - const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj; + const NMPObject * obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj; + const NMPlatformIPXRoute *rt = NMP_OBJECT_CAST_IPX_ROUTE(obj); - if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) { - if (nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj)) - == RT_TABLE_LOCAL) + switch (route_table_sync) { + case NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN: + if (!nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&rt->rx))) continue; - } else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) { - if (!nm_platform_route_table_is_main( - nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj)))) + break; + case NM_IP_ROUTE_TABLE_SYNC_MODE_FULL: + if (nm_platform_ip_route_get_effective_table(&rt->rx) == RT_TABLE_LOCAL) continue; - } else - nm_assert(route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); + break; + case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL: + + /* FIXME: we should better handle routes that are automatically added by kernel. + * + * For now, make a good guess which are those routes and exclude them from + * pruning them. */ + + if (NM_IS_IPv4(addr_family)) { + /* for each IPv4 address kernel adds a route like + * + * local $ADDR dev $IFACE table local proto kernel scope host src $PRIMARY_ADDR + * + * Check whether route could be of that kind. */ + if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table + && rt->rx.plen == 32 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL + && rt->rx.metric == 0 + && rt->r4.scope_inv == nm_platform_route_scope_inv(RT_SCOPE_HOST) + && rt->r4.gateway == INADDR_ANY) { + if (rt_local4.plen == 0) { + rt_local4 = (NMPlatformIP4Route){ + .ifindex = ifindex, + .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), + .plen = 32, + .rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL, + .metric = 0, + .table_coerced = nm_platform_route_table_coerce(local_table), + .scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST), + .gateway = INADDR_ANY, + }; + } + + /* the possible "network" depends on the addresses we have. We don't check that + * carefully. If the other parameters match, we assume that this route is the one + * generated by kernel. */ + rt_local4.network = rt->r4.network; + rt_local4.pref_src = rt->r4.pref_src; + + /* to be more confident about comparing the value, use our nm_platform_ip4_route_cmp() + * implementation. That will also consider parameters that we leave unspecified here. */ + if (nm_platform_ip4_route_cmp(&rt->r4, + &rt_local4, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + == 0) + continue; + } + } else { + /* for each IPv6 address (that is no longer tentative) kernel adds a route like + * + * local $ADDR dev $IFACE table local proto kernel metric 0 pref medium + * + * Same as for the IPv4 case. */ + if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table + && rt->rx.plen == 128 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL + && rt->rx.metric == 0 && rt->r6.rt_pref == NM_ICMPV6_ROUTER_PREF_MEDIUM + && IN6_IS_ADDR_UNSPECIFIED(&rt->r6.gateway)) { + if (rt_local6.plen == 0) { + rt_local6 = (NMPlatformIP6Route){ + .ifindex = ifindex, + .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), + .plen = 128, + .rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL, + .metric = 0, + .table_coerced = nm_platform_route_table_coerce(local_table), + .rt_pref = NM_ICMPV6_ROUTER_PREF_MEDIUM, + .gateway = IN6ADDR_ANY_INIT, + }; + } + + rt_local6.network = rt->r6.network; + + if (nm_platform_ip6_route_cmp(&rt->r6, + &rt_local6, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + == 0) + continue; + } + } + break; + + case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE: + break; + + default: + nm_assert_not_reached(); + break; + } g_ptr_array_add(routes_prune, (gpointer) nmp_object_ref(obj)); } @@ -4679,7 +4779,7 @@ nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex) routes_prune = nm_platform_ip_route_get_prune_list(self, AF_INET, ifindex, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE); success &= nm_platform_ip_route_sync(self, AF_INET, ifindex, NULL, routes_prune, NULL); } if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) { @@ -4688,7 +4788,7 @@ nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex) routes_prune = nm_platform_ip_route_get_prune_list(self, AF_INET6, ifindex, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE); success &= nm_platform_ip_route_sync(self, AF_INET6, ifindex, NULL, routes_prune, NULL); } return success; diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 4a117d59..1b977145 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -1542,7 +1542,10 @@ nmtstp_link_bridge_add(NMPlatform * platform, ll = NMP_OBJECT_CAST_LNK_BRIDGE(NMP_OBJECT_UP_CAST(pllink)->_link.netlink.lnk); - g_assert_cmpint(lnk->forward_delay, ==, ll->forward_delay); + /* account for roundtrip rounding error with clock_t_to_jiffies()/jiffies_to_clock_t(). */ + g_assert_cmpint(lnk->forward_delay, >=, ll->forward_delay - 1); + g_assert_cmpint(lnk->forward_delay, <=, ll->forward_delay); + g_assert_cmpint(lnk->hello_time, ==, ll->hello_time); g_assert_cmpint(lnk->max_age, ==, ll->max_age); g_assert_cmpint(lnk->ageing_time, ==, ll->ageing_time); 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 209957d9..a42c4188 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 @@ -2707,7 +2707,8 @@ make_tc_setting(shvarFile *ifcfg) } if (nm_setting_tc_config_get_num_qdiscs(s_tc) > 0 - || nm_setting_tc_config_get_num_tfilters(s_tc) > 0) + || nm_setting_tc_config_get_num_tfilters(s_tc) > 0 + || svGetValueBoolean(ifcfg, "TC_COMMIT", FALSE)) return NM_SETTING(s_tc); g_object_unref(s_tc); diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 8da5de47..ada1942a 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -1026,6 +1026,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("STABLE_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("STP", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("SUBCHANNELS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("TC_COMMIT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("TEAM_CONFIG", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("TEAM_MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("TEAM_MASTER_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 36ec9225..04a1b63d 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -33,7 +33,7 @@ typedef struct { NMSIfcfgKeyTypeFlags key_flags; } NMSIfcfgKeyTypeInfo; -extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[247]; +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[248]; const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); 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 a968fce0..45b76456 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 @@ -1137,7 +1137,7 @@ write_wired_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) svSetValueStr(ifcfg, "CTCPROT", nm_setting_wired_get_s390_option_by_key(s_wired, "ctcprot")); num_opts = nm_setting_wired_get_num_s390_options(s_wired); - if (s390_subchannels && num_opts) { + if (num_opts > 0) { nm_auto_free_gstring GString *tmp = NULL; for (i = 0; i < num_opts; i++) { @@ -2511,46 +2511,46 @@ write_sriov_setting(NMConnection *connection, shvarFile *ifcfg) } } -static gboolean -write_tc_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) +static void +write_tc_setting(NMConnection *connection, shvarFile *ifcfg) { NMSettingTCConfig *s_tc; - guint i, num, n; + guint num_qdiscs; + guint num_filters; + guint i; + guint n; char tag[64]; s_tc = nm_connection_get_setting_tc_config(connection); if (!s_tc) - return TRUE; + return; - num = nm_setting_tc_config_get_num_qdiscs(s_tc); - for (n = 1, i = 0; i < num; i++) { + num_qdiscs = nm_setting_tc_config_get_num_qdiscs(s_tc); + for (n = 1, i = 0; i < num_qdiscs; i++) { NMTCQdisc * qdisc; gs_free char *str = NULL; qdisc = nm_setting_tc_config_get_qdisc(s_tc, i); - str = nm_utils_tc_qdisc_to_str(qdisc, error); - if (!str) - return FALSE; - + str = nm_utils_tc_qdisc_to_str(qdisc, NULL); + nm_assert(str); svSetValueStr(ifcfg, numbered_tag(tag, "QDISC", n), str); n++; } - num = nm_setting_tc_config_get_num_tfilters(s_tc); - for (n = 1, i = 0; i < num; i++) { + num_filters = nm_setting_tc_config_get_num_tfilters(s_tc); + for (n = 1, i = 0; i < num_filters; i++) { NMTCTfilter * tfilter; gs_free char *str = NULL; tfilter = nm_setting_tc_config_get_tfilter(s_tc, i); - str = nm_utils_tc_tfilter_to_str(tfilter, error); - if (!str) - return FALSE; - + str = nm_utils_tc_tfilter_to_str(tfilter, NULL); + nm_assert(str); svSetValueStr(ifcfg, numbered_tag(tag, "FILTER", n), str); n++; } - return TRUE; + if (num_qdiscs == 0 && num_filters == 0) + svSetValueBoolean(ifcfg, "TC_COMMIT", TRUE); } static void @@ -3373,9 +3373,7 @@ do_write_construct(NMConnection * connection, write_match_setting(connection, ifcfg); write_hostname_setting(connection, ifcfg); write_sriov_setting(connection, ifcfg); - - if (!write_tc_setting(connection, ifcfg, error)) - return FALSE; + write_tc_setting(connection, ifcfg); route_path_is_svformat = utils_has_route_file_new_syntax(route_path); diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected new file mode 100644 index 00000000..4df768b4 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +TC_COMMIT=yes +BOOTPROTO=none +IPADDR=1.1.1.3 +PREFIX=24 +GATEWAY=1.1.1.1 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write TC config" +UUID=${UUID} +DEVICE=eth0 +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 59127d01..9d9ed626 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 @@ -11108,6 +11108,85 @@ test_tc_read(void) g_object_unref(connection); } +static void +test_tc_write_empty(void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + NMSettingWired * s_wired; + NMSettingTCConfig * s_tc; + NMIPAddress * addr; + GError * error = NULL; + + connection = nm_simple_connection_new(); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new(); + nm_connection_add_setting(connection, NM_SETTING(s_con)); + + g_object_set(s_con, + NM_SETTING_CONNECTION_ID, + "Test Write TC config", + NM_SETTING_CONNECTION_UUID, + nm_utils_uuid_generate_a(), + NM_SETTING_CONNECTION_AUTOCONNECT, + TRUE, + NM_SETTING_CONNECTION_INTERFACE_NAME, + "eth0", + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + + g_object_set(s_ip4, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, + "1.1.1.1", + NM_SETTING_IP_CONFIG_MAY_FAIL, + TRUE, + NULL); + + addr = nm_ip_address_new(AF_INET, "1.1.1.3", 24, &error); + g_assert_no_error(error); + nm_setting_ip_config_add_address(s_ip4, addr); + nm_ip_address_unref(addr); + + /* IP6 setting */ + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_ip6)); + + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + + /* TC setting */ + s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new(); + nm_connection_add_setting(connection, NM_SETTING(s_tc)); + + nm_connection_add_setting(connection, nm_setting_proxy_new()); + + nmtst_assert_connection_verifies_without_normalization(connection); + + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test-tc-write-empty.cexpected", + &testfile); + + reread = _connection_from_file(testfile, NULL, TYPE_BOND, NULL); + + nmtst_assert_connection_equals(connection, FALSE, reread, FALSE); +} + static void test_tc_write(void) { @@ -11848,6 +11927,7 @@ main(int argc, char **argv) g_test_add_func(TPATH "tc/read", test_tc_read); g_test_add_func(TPATH "tc/write", test_tc_write); + g_test_add_func(TPATH "tc/write_empty", test_tc_write_empty); g_test_add_func(TPATH "utils/test_well_known_keys", test_well_known_keys); g_test_add_func(TPATH "utils/test_utils_has_route_file_new_syntax", test_utils_has_route_file_new_syntax); diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c index f3dffdae..ca1233f5 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c @@ -137,7 +137,11 @@ nms_keyfile_nmmeta_read(const char * dirname, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_UUID, NULL); - if (!nm_streq0(v_uuid, uuid)) + if (!v_uuid) + return FALSE; + if (strncmp(v_uuid, uuid, uuid_len) != 0) + return FALSE; + if (v_uuid[uuid_len] != '\0') return FALSE; loaded_path = g_key_file_get_string(kf, diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c index eab494b0..bc2a692e 100644 --- a/src/core/supplicant/nm-supplicant-config.c +++ b/src/core/supplicant/nm-supplicant-config.c @@ -841,6 +841,11 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * g_string_append(key_mgmt_conf, " wpa-psk-sha256"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-psk"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)) { + g_string_append(key_mgmt_conf, " sae"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) + g_string_append(key_mgmt_conf, " ft-sae"); + } } else if (nm_streq(key_mgmt, "wpa-eap")) { if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { g_string_append(key_mgmt_conf, " wpa-eap-sha256"); diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index 6d9c604f..a38ebf18 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -586,7 +586,7 @@ _bss_info_properties_changed(NMSupplicantInterface *self, if (v_v) { if (g_variant_lookup(v_v, "Type", "&s", &v_s)) { f = NM_802_11_AP_FLAGS_WPS; - if (nm_streq(v_s, "pcb")) + if (nm_streq(v_s, "pbc")) f |= NM_802_11_AP_FLAGS_WPS_PBC; else if (nm_streq(v_s, "pin")) f |= NM_802_11_AP_FLAGS_WPS_PIN; @@ -1171,19 +1171,24 @@ parse_capabilities(NMSupplicantInterface *self, GVariant *capabilities) const gboolean old_prop_scan_ssid = priv->prop_scan_ssid; const guint32 old_max_scan_ssids = priv->max_scan_ssids; gboolean have_ft = FALSE; + gboolean have_sae = FALSE; gint32 max_scan_ssids; const char ** array; nm_assert(capabilities && g_variant_is_of_type(capabilities, G_VARIANT_TYPE_VARDICT)); if (g_variant_lookup(capabilities, "KeyMgmt", "^a&s", &array)) { - have_ft = g_strv_contains(array, "wpa-ft-psk"); + have_ft = g_strv_contains(array, "wpa-ft-psk"); + have_sae = g_strv_contains(array, "sae"); g_free(array); } priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_FT, have_ft ? NM_TERNARY_TRUE : NM_TERNARY_FALSE); + priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities, + NM_SUPPL_CAP_TYPE_SAE, + have_sae ? NM_TERNARY_TRUE : NM_TERNARY_FALSE); if (g_variant_lookup(capabilities, "Modes", "^a&s", &array)) { /* Setting p2p_capable might toggle _prop_p2p_available_get(). However, @@ -1255,6 +1260,15 @@ _starting_check_ready(NMSupplicantInterface *self) return; } + _LOGD("interface supported features:" + " AP%c" + " FT%c" + " SAE%c" + "", + NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_AP), + NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_FT), + NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_SAE)); + set_state(self, priv->supp_state); } @@ -1278,6 +1292,10 @@ _get_capability(NMSupplicantInterfacePrivate *priv, NMSupplCapType type) value = iface_value; } break; + case NM_SUPPL_CAP_TYPE_SAE: + nm_assert(NM_SUPPL_CAP_MASK_GET(priv->global_capabilities, type) == NM_TERNARY_DEFAULT); + value = NM_SUPPL_CAP_MASK_GET(priv->iface_capabilities, type); + break; default: nm_assert(NM_SUPPL_CAP_MASK_GET(priv->iface_capabilities, type) == NM_TERNARY_DEFAULT); value = NM_SUPPL_CAP_MASK_GET(priv->global_capabilities, type); @@ -1305,9 +1323,13 @@ nm_supplicant_interface_get_capabilities(NMSupplicantInterface *self) caps = NM_SUPPL_CAP_MASK_SET(caps, NM_SUPPL_CAP_TYPE_FT, _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)); + caps = NM_SUPPL_CAP_MASK_SET(caps, + NM_SUPPL_CAP_TYPE_SAE, + _get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)); nm_assert(!NM_FLAGS_ANY(priv->iface_capabilities, - ~(NM_SUPPL_CAP_MASK_T_AP_MASK | NM_SUPPL_CAP_MASK_T_FT_MASK))); + ~(NM_SUPPL_CAP_MASK_T_AP_MASK | NM_SUPPL_CAP_MASK_T_FT_MASK + | NM_SUPPL_CAP_MASK_T_SAE_MASK))); #if NM_MORE_ASSERTS > 10 { diff --git a/src/core/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c index 32554187..7cf1a2bb 100644 --- a/src/core/supplicant/nm-supplicant-manager.c +++ b/src/core/supplicant/nm-supplicant-manager.c @@ -168,19 +168,6 @@ _caps_set(NMSupplicantManagerPrivate *priv, NMSupplCapType type, NMTernary value priv->capabilities = NM_SUPPL_CAP_MASK_SET(priv->capabilities, type, value); } -static char -_caps_to_char(NMSupplicantManagerPrivate *priv, NMSupplCapType type) -{ - NMTernary val; - - val = NM_SUPPL_CAP_MASK_GET(priv->capabilities, type); - if (val == NM_TERNARY_TRUE) - return '+'; - if (val == NM_TERNARY_FALSE) - return '-'; - return '?'; -} - /*****************************************************************************/ static void @@ -395,7 +382,7 @@ _create_iface_complete(NMSupplMgrCreateIfaceHandle *handle, nm_clear_g_cancellable(&handle->cancellable); nm_ref_string_unref(handle->name_owner); - nm_g_slice_free_fcn(handle); + nm_g_slice_free(handle); } static void @@ -1008,15 +995,15 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) " FAST%c" " WFD%c" "", - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_AP), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_PMF), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_FILS), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_P2P), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_FT), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_SHA384), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_MESH), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_FAST), - _caps_to_char(priv, NM_SUPPL_CAP_TYPE_WFD)); + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_AP), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_PMF), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_FILS), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_P2P), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_FT), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_SHA384), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_MESH), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_FAST), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_WFD)); nm_assert(g_hash_table_size(priv->supp_ifaces) == 0); nm_assert(c_list_is_empty(&priv->supp_lst_head)); diff --git a/src/core/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h index adcf02db..ae2db3f6 100644 --- a/src/core/supplicant/nm-supplicant-types.h +++ b/src/core/supplicant/nm-supplicant-types.h @@ -41,6 +41,7 @@ typedef enum { NM_SUPPL_CAP_TYPE_FILS, NM_SUPPL_CAP_TYPE_P2P, NM_SUPPL_CAP_TYPE_FT, + NM_SUPPL_CAP_TYPE_SAE, NM_SUPPL_CAP_TYPE_SHA384, NM_SUPPL_CAP_TYPE_MESH, NM_SUPPL_CAP_TYPE_FAST, @@ -71,6 +72,7 @@ typedef enum { _NM_SUPPL_CAP_MASK_DEFINE(MESH), _NM_SUPPL_CAP_MASK_DEFINE(WFD), _NM_SUPPL_CAP_MASK_DEFINE(FT), + _NM_SUPPL_CAP_MASK_DEFINE(SAE), _NM_SUPPL_CAP_MASK_DEFINE(SHA384), #undef _NM_SUPPL_CAP_MASK_DEFINE } NMSupplCapMask; @@ -114,6 +116,19 @@ NM_SUPPL_CAP_MASK_GET(NMSupplCapMask features, NMSupplCapType type) return (NMTernary)(f - 1); } +static inline char +NM_SUPPL_CAP_TO_CHAR(NMSupplCapMask features, NMSupplCapType type) +{ + NMTernary val; + + val = NM_SUPPL_CAP_MASK_GET(features, type); + if (val == NM_TERNARY_TRUE) + return '+'; + if (val == NM_TERNARY_FALSE) + return '-'; + return '?'; +} + /*****************************************************************************/ /** diff --git a/src/core/tests/test-systemd.c b/src/core/tests/test-systemd.c index 03576c13..fa510366 100644 --- a/src/core/tests/test-systemd.c +++ b/src/core/tests/test-systemd.c @@ -247,11 +247,11 @@ _test_unbase64mem_mem(const char *base64, const guint8 *expected_arr, gsize expe { gs_free char *expected_base64 = NULL; int r; - gs_free guint8 *exp2_arr = NULL; - gs_free guint8 *exp3_arr = NULL; - gsize exp2_len; - gsize exp3_len; - gsize i; + nm_auto_free guint8 *exp2_arr = NULL; + nm_auto_free guint8 *exp3_arr = NULL; + gsize exp2_len; + gsize exp3_len; + gsize i; expected_base64 = g_base64_encode(expected_arr, expected_len); -- cgit 1.3.0-6-gf8a5 From e74c568b07b50b97873fb4ee1d776dedefbd54d6 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Fri, 1 Oct 2021 23:05:04 +0200 Subject: New upstream version 1.32.12 --- src/core/NetworkManagerUtils.c | 270 +- src/core/NetworkManagerUtils.h | 36 +- src/core/devices/adsl/meson.build | 1 - src/core/devices/adsl/nm-atm-manager.c | 4 +- src/core/devices/adsl/nm-device-adsl.c | 10 +- src/core/devices/bluetooth/meson.build | 2 +- src/core/devices/bluetooth/nm-bluez-manager.c | 18 +- src/core/devices/bluetooth/nm-device-bt.c | 18 +- src/core/devices/nm-acd-manager.c | 2 +- src/core/devices/nm-device-6lowpan.c | 2 +- src/core/devices/nm-device-bond.c | 16 +- src/core/devices/nm-device-bridge.c | 18 +- src/core/devices/nm-device-dummy.c | 12 +- src/core/devices/nm-device-ethernet.c | 86 +- src/core/devices/nm-device-factory.c | 4 +- src/core/devices/nm-device-generic.c | 12 +- src/core/devices/nm-device-infiniband.c | 14 +- src/core/devices/nm-device-ip-tunnel.c | 62 +- src/core/devices/nm-device-macsec.c | 66 +- src/core/devices/nm-device-macvlan.c | 18 +- src/core/devices/nm-device-ppp.c | 7 +- src/core/devices/nm-device-private.h | 10 - src/core/devices/nm-device-tun.c | 30 +- src/core/devices/nm-device-utils.c | 356 + src/core/devices/nm-device-utils.h | 98 + src/core/devices/nm-device-veth.c | 10 +- src/core/devices/nm-device-vlan.c | 33 +- src/core/devices/nm-device-vrf.c | 4 +- src/core/devices/nm-device-vxlan.c | 62 +- src/core/devices/nm-device-wireguard.c | 22 +- src/core/devices/nm-device-wpan.c | 4 +- src/core/devices/nm-device.c | 1392 +-- src/core/devices/nm-device.h | 63 +- src/core/devices/nm-lldp-listener.c | 402 +- src/core/devices/nm-lldp-listener.h | 31 +- src/core/devices/ovs/meson.build | 1 - src/core/devices/ovs/nm-device-ovs-bridge.c | 6 +- src/core/devices/ovs/nm-device-ovs-interface.c | 5 +- src/core/devices/ovs/nm-device-ovs-port.c | 4 +- src/core/devices/ovs/nm-ovs-factory.c | 4 +- src/core/devices/ovs/nm-ovsdb.c | 6 +- src/core/devices/team/meson.build | 1 - src/core/devices/team/nm-device-team.c | 32 +- src/core/devices/team/nm-team-factory.c | 4 +- src/core/devices/tests/test-acd.c | 4 +- src/core/devices/tests/test-lldp.c | 66 +- src/core/devices/wifi/meson.build | 2 - src/core/devices/wifi/nm-device-iwd.c | 191 +- src/core/devices/wifi/nm-device-olpc-mesh.c | 32 +- src/core/devices/wifi/nm-device-wifi-p2p.c | 9 +- src/core/devices/wifi/nm-device-wifi.c | 137 +- src/core/devices/wifi/nm-device-wifi.h | 2 +- src/core/devices/wifi/nm-iwd-manager.c | 434 +- src/core/devices/wifi/nm-iwd-manager.h | 1 + src/core/devices/wifi/nm-wifi-ap.c | 153 +- src/core/devices/wifi/nm-wifi-ap.h | 3 +- src/core/devices/wifi/nm-wifi-common.c | 38 +- src/core/devices/wifi/nm-wifi-factory.c | 15 +- src/core/devices/wifi/nm-wifi-p2p-peer.c | 7 +- src/core/devices/wifi/nm-wifi-utils.c | 902 +- src/core/devices/wifi/nm-wifi-utils.h | 9 +- src/core/devices/wifi/tests/test-devices-wifi.c | 58 +- src/core/devices/wwan/meson.build | 2 - src/core/devices/wwan/nm-device-modem.c | 36 +- src/core/devices/wwan/nm-modem-broadband.c | 4 +- src/core/devices/wwan/nm-modem-manager.c | 2 +- src/core/devices/wwan/nm-modem-ofono.c | 172 +- src/core/devices/wwan/nm-modem-ofono.h | 2 + src/core/devices/wwan/nm-modem.c | 13 +- src/core/devices/wwan/nm-wwan-factory.c | 2 +- src/core/dhcp/meson.build | 7 +- src/core/dhcp/nm-dhcp-client.c | 160 +- src/core/dhcp/nm-dhcp-client.h | 29 +- src/core/dhcp/nm-dhcp-dhclient-utils.c | 13 +- src/core/dhcp/nm-dhcp-dhclient.c | 56 +- src/core/dhcp/nm-dhcp-dhcpcanon.c | 5 +- src/core/dhcp/nm-dhcp-dhcpcd.c | 7 +- src/core/dhcp/nm-dhcp-helper.c | 10 +- src/core/dhcp/nm-dhcp-listener.c | 2 +- src/core/dhcp/nm-dhcp-manager.c | 107 +- src/core/dhcp/nm-dhcp-manager.h | 7 +- src/core/dhcp/nm-dhcp-nettools.c | 61 +- src/core/dhcp/nm-dhcp-options.c | 10 +- src/core/dhcp/nm-dhcp-options.h | 3 +- src/core/dhcp/nm-dhcp-systemd.c | 84 +- src/core/dhcp/nm-dhcp-utils.c | 14 +- src/core/dhcp/tests/test-dhcp-dhclient.c | 4 +- src/core/dhcp/tests/test-dhcp-utils.c | 4 +- src/core/dns/nm-dns-dnsmasq.c | 6 +- src/core/dns/nm-dns-dnsmasq.h | 1 + src/core/dns/nm-dns-manager.c | 152 +- src/core/dns/nm-dns-manager.h | 3 +- src/core/dns/nm-dns-plugin.c | 2 +- src/core/dns/nm-dns-plugin.h | 3 +- src/core/dns/nm-dns-systemd-resolved.c | 465 +- src/core/dns/nm-dns-systemd-resolved.h | 31 + src/core/dnsmasq/nm-dnsmasq-manager.c | 2 +- src/core/dnsmasq/nm-dnsmasq-utils.c | 5 +- src/core/dnsmasq/nm-dnsmasq-utils.h | 2 +- src/core/initrd/meson.build | 31 - src/core/initrd/nm-initrd-generator.c | 226 - src/core/initrd/nm-initrd-generator.h | 45 - src/core/initrd/nmi-cmdline-reader.c | 1288 --- src/core/initrd/nmi-dt-reader.c | 371 - src/core/initrd/nmi-ibft-reader.c | 463 - src/core/initrd/tests/meson.build | 24 - .../tests/sysfs-bad-dns1/class/net/eth0/address | 1 - .../sysfs-bad-dns1/firmware/ibft/ethernet0/gateway | 1 - .../sysfs-bad-dns1/firmware/ibft/ethernet0/index | 1 - .../sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr | 1 - .../sysfs-bad-dns1/firmware/ibft/ethernet0/mac | 1 - .../sysfs-bad-dns1/firmware/ibft/ethernet0/origin | 1 - .../firmware/ibft/ethernet0/prefix-len | 1 - .../firmware/ibft/ethernet0/primary-dns | 1 - .../firmware/ibft/ethernet0/secondary-dns | 1 - .../firmware/ibft/ethernet0/subnet-mask | 1 - .../sysfs-bad-dns1/firmware/ibft/ethernet0/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../sysfs-bad-dns1/firmware/ibft/target0/index | 1 - .../sysfs-bad-dns1/firmware/ibft/target0/ip-addr | 1 - .../tests/sysfs-bad-dns1/firmware/ibft/target0/lun | 1 - .../sysfs-bad-dns1/firmware/ibft/target0/port | 1 - .../firmware/ibft/target0/target-name | 1 - .../tests/sysfs-bad-dns2/class/net/eth0/address | 1 - .../sysfs-bad-dns2/firmware/ibft/ethernet0/gateway | 1 - .../sysfs-bad-dns2/firmware/ibft/ethernet0/index | 1 - .../sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr | 1 - .../sysfs-bad-dns2/firmware/ibft/ethernet0/mac | 1 - .../sysfs-bad-dns2/firmware/ibft/ethernet0/origin | 1 - .../firmware/ibft/ethernet0/prefix-len | 1 - .../firmware/ibft/ethernet0/primary-dns | 1 - .../firmware/ibft/ethernet0/secondary-dns | 1 - .../firmware/ibft/ethernet0/subnet-mask | 1 - .../sysfs-bad-dns2/firmware/ibft/ethernet0/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../sysfs-bad-dns2/firmware/ibft/target0/index | 1 - .../sysfs-bad-dns2/firmware/ibft/target0/ip-addr | 1 - .../tests/sysfs-bad-dns2/firmware/ibft/target0/lun | 1 - .../sysfs-bad-dns2/firmware/ibft/target0/port | 1 - .../firmware/ibft/target0/target-name | 1 - .../tests/sysfs-bad-gateway/class/net/eth0/address | 1 - .../firmware/ibft/ethernet0/gateway | 1 - .../firmware/ibft/ethernet0/index | 1 - .../firmware/ibft/ethernet0/ip-addr | 1 - .../sysfs-bad-gateway/firmware/ibft/ethernet0/mac | 1 - .../firmware/ibft/ethernet0/origin | 1 - .../firmware/ibft/ethernet0/prefix-len | 1 - .../firmware/ibft/ethernet0/primary-dns | 1 - .../firmware/ibft/ethernet0/secondary-dns | 1 - .../firmware/ibft/ethernet0/subnet-mask | 1 - .../sysfs-bad-gateway/firmware/ibft/ethernet0/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../sysfs-bad-gateway/firmware/ibft/target0/index | 1 - .../firmware/ibft/target0/ip-addr | 1 - .../sysfs-bad-gateway/firmware/ibft/target0/lun | 1 - .../sysfs-bad-gateway/firmware/ibft/target0/port | 1 - .../firmware/ibft/target0/target-name | 1 - .../tests/sysfs-bad-ipaddr/class/net/eth0/address | 1 - .../firmware/ibft/ethernet0/gateway | 1 - .../sysfs-bad-ipaddr/firmware/ibft/ethernet0/index | 1 - .../firmware/ibft/ethernet0/ip-addr | 1 - .../sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac | 1 - .../firmware/ibft/ethernet0/origin | 1 - .../firmware/ibft/ethernet0/prefix-len | 1 - .../firmware/ibft/ethernet0/primary-dns | 1 - .../firmware/ibft/ethernet0/secondary-dns | 1 - .../firmware/ibft/ethernet0/subnet-mask | 1 - .../sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../sysfs-bad-ipaddr/firmware/ibft/target0/index | 1 - .../sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr | 1 - .../sysfs-bad-ipaddr/firmware/ibft/target0/lun | 1 - .../sysfs-bad-ipaddr/firmware/ibft/target0/port | 1 - .../firmware/ibft/target0/target-name | 1 - .../initrd/tests/sysfs-dhcp/class/net/eth0/address | 1 - .../initrd/tests/sysfs-dhcp/class/net/eth1/address | 1 - .../sysfs-dhcp/firmware/ibft/ethernet0/gateway | 1 - .../tests/sysfs-dhcp/firmware/ibft/ethernet0/index | 1 - .../tests/sysfs-dhcp/firmware/ibft/ethernet0/mac | 1 - .../sysfs-dhcp/firmware/ibft/ethernet0/origin | 1 - .../sysfs-dhcp/firmware/ibft/ethernet0/primary-dns | 1 - .../firmware/ibft/ethernet0/secondary-dns | 1 - .../tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan | 1 - .../sysfs-dhcp/firmware/ibft/ethernet1/gateway | 1 - .../tests/sysfs-dhcp/firmware/ibft/ethernet1/index | 1 - .../tests/sysfs-dhcp/firmware/ibft/ethernet1/mac | 1 - .../sysfs-dhcp/firmware/ibft/ethernet1/origin | 1 - .../sysfs-dhcp/firmware/ibft/ethernet1/primary-dns | 1 - .../firmware/ibft/ethernet1/secondary-dns | 1 - .../tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../tests/sysfs-dhcp/firmware/ibft/target0/index | 1 - .../tests/sysfs-dhcp/firmware/ibft/target0/ip-addr | 1 - .../tests/sysfs-dhcp/firmware/ibft/target0/lun | 1 - .../tests/sysfs-dhcp/firmware/ibft/target0/port | 1 - .../sysfs-dhcp/firmware/ibft/target0/target-name | 1 - .../tests/sysfs-dhcp/firmware/ibft/target1/index | 1 - .../tests/sysfs-dhcp/firmware/ibft/target1/ip-addr | 1 - .../tests/sysfs-dhcp/firmware/ibft/target1/lun | 1 - .../tests/sysfs-dhcp/firmware/ibft/target1/port | 1 - .../sysfs-dhcp/firmware/ibft/target1/target-name | 1 - .../firmware/devicetree/base/chosen/bootpath | Bin 108 -> 0 bytes .../firmware/devicetree/base/chosen/bootp-request | Bin 273 -> 0 bytes .../firmware/devicetree/base/chosen/bootp-response | Bin 300 -> 0 bytes .../firmware/devicetree/base/chosen/bootpath | Bin 37 -> 0 bytes .../firmware/devicetree/base/chosen/broadcast-ip | 1 - .../firmware/devicetree/base/chosen/client-ip | 2 - .../firmware/devicetree/base/chosen/client-name | Bin 9 -> 0 bytes .../firmware/devicetree/base/chosen/domain-name | Bin 15 -> 0 bytes .../firmware/devicetree/base/chosen/gateway-ip | 2 - .../sysfs-dt/firmware/devicetree/base/chosen/name | Bin 7 -> 0 bytes .../firmware/devicetree/base/chosen/netmask-ip | Bin 4 -> 0 bytes .../firmware/devicetree/base/chosen/root-path | Bin 1 -> 0 bytes .../firmware/devicetree/base/chosen/server-ip | 2 - .../firmware/devicetree/base/chosen/tftp-file | Bin 11 -> 0 bytes .../firmware/devicetree/base/chosen/vendor-options | Bin 1 -> 0 bytes .../firmware/devicetree/base/ethernet/device_type | Bin 8 -> 0 bytes .../devicetree/base/ethernet/local-mac-address | 1 - .../firmware/devicetree/base/ethernet/mac-address | 1 - .../firmware/devicetree/base/ethernet/name | Bin 9 -> 0 bytes .../tests/sysfs-static/class/net/eth0/address | 1 - .../tests/sysfs-static/class/net/eth1/address | 1 - .../sysfs-static/firmware/ibft/ethernet0/gateway | 1 - .../sysfs-static/firmware/ibft/ethernet0/index | 1 - .../sysfs-static/firmware/ibft/ethernet0/ip-addr | 1 - .../tests/sysfs-static/firmware/ibft/ethernet0/mac | 1 - .../sysfs-static/firmware/ibft/ethernet0/origin | 1 - .../firmware/ibft/ethernet0/prefix-len | 1 - .../firmware/ibft/ethernet0/primary-dns | 1 - .../firmware/ibft/ethernet0/secondary-dns | 1 - .../firmware/ibft/ethernet0/subnet-mask | 1 - .../sysfs-static/firmware/ibft/ethernet0/vlan | 1 - .../sysfs-static/firmware/ibft/ethernet1/gateway | 1 - .../sysfs-static/firmware/ibft/ethernet1/index | 1 - .../tests/sysfs-static/firmware/ibft/ethernet1/mac | 1 - .../sysfs-static/firmware/ibft/ethernet1/origin | 1 - .../firmware/ibft/ethernet1/primary-dns | 1 - .../firmware/ibft/ethernet1/secondary-dns | 1 - .../sysfs-static/firmware/ibft/ethernet1/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../tests/sysfs-static/firmware/ibft/target0/index | 1 - .../sysfs-static/firmware/ibft/target0/ip-addr | 1 - .../tests/sysfs-static/firmware/ibft/target0/lun | 1 - .../tests/sysfs-static/firmware/ibft/target0/port | 1 - .../sysfs-static/firmware/ibft/target0/target-name | 1 - .../tests/sysfs-static/firmware/ibft/target1/index | 1 - .../sysfs-static/firmware/ibft/target1/ip-addr | 1 - .../tests/sysfs-static/firmware/ibft/target1/lun | 1 - .../tests/sysfs-static/firmware/ibft/target1/port | 1 - .../sysfs-static/firmware/ibft/target1/target-name | 1 - .../initrd/tests/sysfs-vlan/class/net/eth0/address | 1 - .../tests/sysfs-vlan/firmware/ibft/ethernet0/index | 1 - .../sysfs-vlan/firmware/ibft/ethernet0/ip-addr | 1 - .../tests/sysfs-vlan/firmware/ibft/ethernet0/mac | 1 - .../sysfs-vlan/firmware/ibft/ethernet0/origin | 1 - .../sysfs-vlan/firmware/ibft/ethernet0/prefix-len | 1 - .../sysfs-vlan/firmware/ibft/ethernet0/subnet-mask | 1 - .../tests/sysfs-vlan/firmware/ibft/ethernet0/vlan | 1 - .../firmware/ibft/initiator/initiator-name | 1 - .../tests/sysfs-vlan/firmware/ibft/target0/index | 1 - .../tests/sysfs-vlan/firmware/ibft/target0/ip-addr | 1 - .../tests/sysfs-vlan/firmware/ibft/target0/lun | 1 - .../tests/sysfs-vlan/firmware/ibft/target0/port | 1 - .../sysfs-vlan/firmware/ibft/target0/target-name | 1 - src/core/initrd/tests/sysfs/class/net/eth0/address | 1 - src/core/initrd/tests/sysfs/class/net/eth2/address | 1 - .../tests/sysfs/firmware/ibft/acpi_header/oem_id | 1 - .../sysfs/firmware/ibft/acpi_header/oem_table_id | 1 - .../sysfs/firmware/ibft/acpi_header/signature | 1 - .../tests/sysfs/firmware/ibft/ethernet0/dhcp | 1 - .../tests/sysfs/firmware/ibft/ethernet0/flags | 1 - .../tests/sysfs/firmware/ibft/ethernet0/gateway | 1 - .../tests/sysfs/firmware/ibft/ethernet0/hostname | 1 - .../tests/sysfs/firmware/ibft/ethernet0/index | 1 - .../tests/sysfs/firmware/ibft/ethernet0/ip-addr | 1 - .../initrd/tests/sysfs/firmware/ibft/ethernet0/mac | 1 - .../tests/sysfs/firmware/ibft/ethernet0/origin | 1 - .../tests/sysfs/firmware/ibft/ethernet0/prefix-len | 1 - .../sysfs/firmware/ibft/ethernet0/primary-dns | 1 - .../sysfs/firmware/ibft/ethernet0/secondary-dns | 1 - .../sysfs/firmware/ibft/ethernet0/subnet-mask | 1 - .../tests/sysfs/firmware/ibft/ethernet0/vlan | 1 - .../tests/sysfs/firmware/ibft/ethernet2/dhcp | 1 - .../tests/sysfs/firmware/ibft/ethernet2/flags | 1 - .../tests/sysfs/firmware/ibft/ethernet2/gateway | 1 - .../tests/sysfs/firmware/ibft/ethernet2/hostname | 1 - .../tests/sysfs/firmware/ibft/ethernet2/index | 1 - .../tests/sysfs/firmware/ibft/ethernet2/ip-addr | 1 - .../initrd/tests/sysfs/firmware/ibft/ethernet2/mac | 1 - .../tests/sysfs/firmware/ibft/ethernet2/origin | 1 - .../tests/sysfs/firmware/ibft/ethernet2/prefix-len | 1 - .../sysfs/firmware/ibft/ethernet2/primary-dns | 1 - .../sysfs/firmware/ibft/ethernet2/secondary-dns | 1 - .../sysfs/firmware/ibft/ethernet2/subnet-mask | 1 - .../tests/sysfs/firmware/ibft/ethernet2/vlan | 1 - .../tests/sysfs/firmware/ibft/initiator/flags | 1 - .../tests/sysfs/firmware/ibft/initiator/index | 1 - .../sysfs/firmware/ibft/initiator/initiator-name | 1 - .../sysfs/firmware/ibft/initiator/isns-server | 1 - .../firmware/ibft/initiator/pri-radius-server | 1 - .../firmware/ibft/initiator/sec-radius-server | 1 - .../tests/sysfs/firmware/ibft/initiator/slp-server | 1 - .../tests/sysfs/firmware/ibft/target0/chap-type | 1 - .../initrd/tests/sysfs/firmware/ibft/target0/flags | 1 - .../initrd/tests/sysfs/firmware/ibft/target0/index | 1 - .../tests/sysfs/firmware/ibft/target0/ip-addr | 1 - .../initrd/tests/sysfs/firmware/ibft/target0/lun | 1 - .../tests/sysfs/firmware/ibft/target0/nic-assoc | 1 - .../initrd/tests/sysfs/firmware/ibft/target0/port | 1 - .../tests/sysfs/firmware/ibft/target2/chap-type | 1 - .../initrd/tests/sysfs/firmware/ibft/target2/flags | 1 - .../initrd/tests/sysfs/firmware/ibft/target2/index | 1 - .../tests/sysfs/firmware/ibft/target2/ip-addr | 1 - .../initrd/tests/sysfs/firmware/ibft/target2/lun | 1 - .../tests/sysfs/firmware/ibft/target2/nic-assoc | 1 - .../initrd/tests/sysfs/firmware/ibft/target2/port | 1 - .../tests/sysfs/firmware/ibft/target2/target-name | 1 - src/core/initrd/tests/test-cmdline-reader.c | 2247 ----- src/core/initrd/tests/test-dt-reader.c | 144 - src/core/initrd/tests/test-ibft-reader.c | 303 - src/core/main.c | 13 +- src/core/meson.build | 138 +- src/core/ndisc/nm-lndp-ndisc.c | 24 +- src/core/ndisc/nm-ndisc.c | 8 +- src/core/ndisc/nm-ndisc.h | 14 +- src/core/ndisc/tests/test-ndisc-linux.c | 2 +- src/core/nm-act-request.c | 34 +- src/core/nm-act-request.h | 6 +- src/core/nm-active-connection.c | 106 +- src/core/nm-audit-manager.c | 155 +- src/core/nm-auth-manager.c | 4 +- src/core/nm-auth-manager.h | 2 +- src/core/nm-auth-utils.c | 4 +- src/core/nm-checkpoint.c | 34 +- src/core/nm-config-data.c | 291 +- src/core/nm-config-data.h | 122 +- src/core/nm-config.c | 54 +- src/core/nm-config.h | 83 +- src/core/nm-connectivity.c | 8 +- src/core/nm-connectivity.h | 1 + src/core/nm-core-utils.c | 939 +- src/core/nm-core-utils.h | 189 +- src/core/nm-dbus-manager.c | 91 +- src/core/nm-dbus-object.c | 10 +- src/core/nm-dbus-object.h | 15 +- src/core/nm-dbus-utils.c | 4 - src/core/nm-dbus-utils.h | 118 +- src/core/nm-dcb.c | 2 +- src/core/nm-default-daemon.h | 4 +- src/core/nm-dhcp-config.c | 34 +- src/core/nm-dispatcher.c | 24 +- src/core/nm-firewall-manager.c | 623 -- src/core/nm-firewall-manager.h | 54 - src/core/nm-firewall-utils.c | 816 ++ src/core/nm-firewall-utils.h | 29 + src/core/nm-firewalld-manager.c | 669 ++ src/core/nm-firewalld-manager.h | 60 + src/core/nm-hostname-manager.c | 6 +- src/core/nm-iface-helper.c | 11 +- src/core/nm-ip4-config.c | 128 +- src/core/nm-ip4-config.h | 7 +- src/core/nm-ip6-config.c | 99 +- src/core/nm-ip6-config.h | 6 +- src/core/nm-keep-alive.c | 2 +- src/core/nm-l3-config-data.c | 342 +- src/core/nm-l3-config-data.h | 73 +- src/core/nm-l3cfg.c | 75 +- src/core/nm-l3cfg.h | 25 +- src/core/nm-manager.c | 438 +- src/core/nm-netns.c | 16 +- src/core/nm-netns.h | 10 +- src/core/nm-pacrunner-manager.c | 5 +- src/core/nm-policy.c | 48 +- src/core/nm-proxy-config.c | 2 +- src/core/nm-proxy-config.h | 3 +- src/core/nm-rfkill-manager.c | 2 +- src/core/nm-sleep-monitor.c | 4 +- src/core/nm-test-utils-core.h | 38 +- src/core/nm-types.h | 167 - src/core/platform/linux/nl802154.h | 450 - src/core/platform/nm-fake-platform.c | 119 +- src/core/platform/nm-fake-platform.h | 2 +- src/core/platform/nm-linux-platform.c | 9696 -------------------- src/core/platform/nm-linux-platform.h | 30 - src/core/platform/nm-platform-private.h | 29 - src/core/platform/nm-platform.c | 9066 ------------------ src/core/platform/nm-platform.h | 2372 ----- src/core/platform/nmp-object.c | 3457 ------- src/core/platform/nmp-object.h | 1144 --- src/core/platform/nmp-rules-manager.c | 808 -- src/core/platform/nmp-rules-manager.h | 53 - src/core/platform/tests/monitor.c | 2 +- src/core/platform/tests/test-address.c | 6 +- src/core/platform/tests/test-cleanup.c | 9 +- src/core/platform/tests/test-common.c | 54 +- src/core/platform/tests/test-common.h | 31 +- src/core/platform/tests/test-link.c | 114 +- src/core/platform/tests/test-nmp-object.c | 4 +- src/core/platform/tests/test-platform-general.c | 10 +- src/core/platform/tests/test-route.c | 108 +- src/core/platform/tests/test-tc.c | 6 +- src/core/platform/wifi/nm-wifi-utils-nl80211.c | 909 -- src/core/platform/wifi/nm-wifi-utils-nl80211.h | 29 - src/core/platform/wifi/nm-wifi-utils-private.h | 66 - src/core/platform/wifi/nm-wifi-utils-wext.c | 836 -- src/core/platform/wifi/nm-wifi-utils-wext.h | 28 - src/core/platform/wifi/nm-wifi-utils.c | 211 - src/core/platform/wifi/nm-wifi-utils.h | 74 - src/core/platform/wpan/nm-wpan-utils.c | 286 - src/core/platform/wpan/nm-wpan-utils.h | 37 - src/core/ppp/meson.build | 18 +- src/core/ppp/nm-ppp-manager-call.c | 47 +- src/core/ppp/nm-ppp-manager.c | 13 +- src/core/ppp/nm-pppd-plugin.c | 20 +- src/core/settings/nm-agent-manager.c | 4 +- src/core/settings/nm-secret-agent.c | 10 +- src/core/settings/nm-settings-connection.c | 542 +- src/core/settings/nm-settings-connection.h | 12 +- src/core/settings/nm-settings-plugin.c | 2 +- src/core/settings/nm-settings-storage.c | 5 +- src/core/settings/nm-settings-storage.h | 15 +- src/core/settings/nm-settings.c | 250 +- src/core/settings/nm-settings.h | 5 + src/core/settings/plugins/ifcfg-rh/meson.build | 2 - src/core/settings/plugins/ifcfg-rh/nm-ifdown | 47 +- src/core/settings/plugins/ifcfg-rh/nm-ifup | 47 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c | 10 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 93 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-storage.c | 5 +- .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 20 +- .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 4 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 184 +- src/core/settings/plugins/ifcfg-rh/shvar.c | 261 +- src/core/settings/plugins/ifcfg-rh/shvar.h | 3 + .../ifcfg-System_test-bridge-component-a.cexpected | 2 +- .../ifcfg-System_test-bridge-component-b.cexpected | 2 +- ...System_test-wired-802-1X-subj-matches.cexpected | 2 +- .../ifcfg-Test_Write_Bridge_Component.cexpected | 2 +- .../ifcfg-Test_Write_Wired_Static_Routes.cexpected | 2 +- .../ifcfg-test-static-routes-legacy.cexpected | 2 +- .../network-scripts/ifcfg-test-vlan-vlanid-use | 4 + .../ifcfg-test-vlan-vlanid-use.cexpected | 15 + .../ifcfg-test-wifi-wpa-eap-suite-b-192-tls | 1 - .../ifcfg-test-wifi-wpa-eap-ttls-tls | 1 - .../ifcfg-test-write-unknown-4.expected | 6 +- .../ifcfg-test_roundtrip_ethtool-1.cexpected | 14 + .../ifcfg-test_roundtrip_ethtool-2.cexpected | 15 + .../ifcfg-test_roundtrip_ethtool-3.cexpected | 15 + .../ifcfg-test_roundtrip_ethtool-4.cexpected | 15 + .../ifcfg-test_roundtrip_ethtool-5.cexpected | 15 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 325 +- src/core/settings/plugins/ifupdown/meson.build | 2 - .../plugins/ifupdown/nms-ifupdown-parser.c | 26 +- .../plugins/ifupdown/nms-ifupdown-plugin.c | 2 +- .../plugins/ifupdown/tests/test-ifupdown.c | 2 +- .../settings/plugins/keyfile/nms-keyfile-plugin.c | 28 +- .../settings/plugins/keyfile/nms-keyfile-reader.c | 2 +- .../settings/plugins/keyfile/nms-keyfile-storage.c | 7 +- .../settings/plugins/keyfile/nms-keyfile-utils.c | 32 +- .../settings/plugins/keyfile/nms-keyfile-writer.c | 9 +- .../plugins/keyfile/tests/test-keyfile-settings.c | 5 +- src/core/supplicant/nm-supplicant-config.c | 173 +- src/core/supplicant/nm-supplicant-interface.c | 172 +- src/core/supplicant/nm-supplicant-manager.c | 8 +- .../supplicant/nm-supplicant-settings-verify.c | 1 + src/core/supplicant/nm-supplicant-types.h | 11 +- src/core/supplicant/tests/test-supplicant-config.c | 39 +- src/core/systemd/meson.build | 62 - src/core/systemd/nm-default-systemd.h | 18 - src/core/systemd/nm-sd-utils-core.c | 27 - src/core/systemd/nm-sd-utils-core.h | 17 - src/core/systemd/nm-sd-utils-dhcp.c | 41 - src/core/systemd/nm-sd-utils-dhcp.h | 19 - src/core/systemd/nm-sd.c | 113 - src/core/systemd/nm-sd.h | 29 - src/core/systemd/sd-adapt-core/condition.h | 5 - src/core/systemd/sd-adapt-core/conf-parser.h | 3 - src/core/systemd/sd-adapt-core/device-util.h | 3 - src/core/systemd/sd-adapt-core/khash.h | 3 - src/core/systemd/sd-adapt-core/network-util.h | 3 - src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c | 21 - src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h | 88 - src/core/systemd/sd-adapt-core/sd-daemon.h | 3 - src/core/systemd/sd-adapt-core/sd-device.h | 3 - src/core/systemd/sd-adapt-core/udev-util.h | 3 - src/core/systemd/src/libsystemd-network/arp-util.c | 140 - src/core/systemd/src/libsystemd-network/arp-util.h | 18 - .../src/libsystemd-network/dhcp-identifier.c | 228 - .../src/libsystemd-network/dhcp-identifier.h | 62 - .../systemd/src/libsystemd-network/dhcp-internal.h | 69 - .../src/libsystemd-network/dhcp-lease-internal.h | 84 - .../systemd/src/libsystemd-network/dhcp-network.c | 246 - .../systemd/src/libsystemd-network/dhcp-option.c | 358 - .../systemd/src/libsystemd-network/dhcp-packet.c | 173 - .../systemd/src/libsystemd-network/dhcp-protocol.h | 99 - .../src/libsystemd-network/dhcp6-internal.h | 123 - .../src/libsystemd-network/dhcp6-lease-internal.h | 63 - .../systemd/src/libsystemd-network/dhcp6-network.c | 76 - .../systemd/src/libsystemd-network/dhcp6-option.c | 795 -- .../src/libsystemd-network/dhcp6-protocol.h | 120 - .../systemd/src/libsystemd-network/lldp-internal.h | 39 - .../systemd/src/libsystemd-network/lldp-neighbor.c | 794 -- .../systemd/src/libsystemd-network/lldp-neighbor.h | 92 - .../systemd/src/libsystemd-network/lldp-network.c | 80 - .../systemd/src/libsystemd-network/lldp-network.h | 6 - .../src/libsystemd-network/network-internal.c | 245 - .../src/libsystemd-network/network-internal.h | 31 - .../src/libsystemd-network/sd-dhcp-client.c | 2258 ----- .../systemd/src/libsystemd-network/sd-dhcp-lease.c | 1401 --- .../src/libsystemd-network/sd-dhcp6-client.c | 1857 ---- .../src/libsystemd-network/sd-dhcp6-lease.c | 435 - .../systemd/src/libsystemd-network/sd-ipv4acd.c | 543 -- .../systemd/src/libsystemd-network/sd-ipv4ll.c | 342 - src/core/systemd/src/libsystemd-network/sd-lldp.c | 500 - .../systemd/src/libsystemd/sd-event/event-source.h | 220 - .../systemd/src/libsystemd/sd-event/event-util.c | 101 - .../systemd/src/libsystemd/sd-event/event-util.h | 13 - .../systemd/src/libsystemd/sd-event/sd-event.c | 4329 --------- .../systemd/src/libsystemd/sd-id128/id128-util.c | 218 - .../systemd/src/libsystemd/sd-id128/id128-util.h | 38 - .../systemd/src/libsystemd/sd-id128/sd-id128.c | 330 - src/core/systemd/src/systemd/_sd-common.h | 102 - src/core/systemd/src/systemd/sd-dhcp-client.h | 224 - src/core/systemd/src/systemd/sd-dhcp-lease.h | 82 - src/core/systemd/src/systemd/sd-dhcp-option.h | 38 - src/core/systemd/src/systemd/sd-dhcp6-client.h | 180 - src/core/systemd/src/systemd/sd-dhcp6-lease.h | 55 - src/core/systemd/src/systemd/sd-dhcp6-option.h | 37 - src/core/systemd/src/systemd/sd-event.h | 176 - src/core/systemd/src/systemd/sd-id128.h | 124 - src/core/systemd/src/systemd/sd-ipv4acd.h | 60 - src/core/systemd/src/systemd/sd-ipv4ll.h | 62 - src/core/systemd/src/systemd/sd-lldp.h | 194 - src/core/systemd/src/systemd/sd-ndisc.h | 131 - src/core/tests/config/test-config.c | 100 +- src/core/tests/meson.build | 14 +- src/core/tests/test-core-with-expect.c | 7 +- src/core/tests/test-core.c | 30 +- src/core/tests/test-ip4-config.c | 2 +- src/core/tests/test-ip6-config.c | 2 +- src/core/tests/test-l3cfg.c | 12 +- src/core/tests/test-systemd.c | 130 +- src/core/vpn/nm-vpn-connection.c | 78 +- src/core/vpn/nm-vpn-connection.h | 2 +- src/core/vpn/nm-vpn-manager.c | 2 +- 545 files changed, 10247 insertions(+), 59649 deletions(-) create mode 100644 src/core/devices/nm-device-utils.c create mode 100644 src/core/devices/nm-device-utils.h delete mode 100644 src/core/initrd/meson.build delete mode 100644 src/core/initrd/nm-initrd-generator.c delete mode 100644 src/core/initrd/nm-initrd-generator.h delete mode 100644 src/core/initrd/nmi-cmdline-reader.c delete mode 100644 src/core/initrd/nmi-dt-reader.c delete mode 100644 src/core/initrd/nmi-ibft-reader.c delete mode 100644 src/core/initrd/tests/meson.build delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port delete mode 100644 src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name delete mode 100644 src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address delete mode 100644 src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name delete mode 100644 src/core/initrd/tests/sysfs-static/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-static/class/net/eth1/address delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port delete mode 100644 src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name delete mode 100644 src/core/initrd/tests/sysfs-vlan/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name delete mode 100644 src/core/initrd/tests/sysfs/class/net/eth0/address delete mode 100644 src/core/initrd/tests/sysfs/class/net/eth2/address delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/index delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/flags delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/index delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/lun delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target0/port delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/flags delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/index delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/lun delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/port delete mode 100644 src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name delete mode 100644 src/core/initrd/tests/test-cmdline-reader.c delete mode 100644 src/core/initrd/tests/test-dt-reader.c delete mode 100644 src/core/initrd/tests/test-ibft-reader.c delete mode 100644 src/core/nm-firewall-manager.c delete mode 100644 src/core/nm-firewall-manager.h create mode 100644 src/core/nm-firewall-utils.c create mode 100644 src/core/nm-firewall-utils.h create mode 100644 src/core/nm-firewalld-manager.c create mode 100644 src/core/nm-firewalld-manager.h delete mode 100644 src/core/platform/linux/nl802154.h delete mode 100644 src/core/platform/nm-linux-platform.c delete mode 100644 src/core/platform/nm-linux-platform.h delete mode 100644 src/core/platform/nm-platform-private.h delete mode 100644 src/core/platform/nm-platform.c delete mode 100644 src/core/platform/nm-platform.h delete mode 100644 src/core/platform/nmp-object.c delete mode 100644 src/core/platform/nmp-object.h delete mode 100644 src/core/platform/nmp-rules-manager.c delete mode 100644 src/core/platform/nmp-rules-manager.h delete mode 100644 src/core/platform/wifi/nm-wifi-utils-nl80211.c delete mode 100644 src/core/platform/wifi/nm-wifi-utils-nl80211.h delete mode 100644 src/core/platform/wifi/nm-wifi-utils-private.h delete mode 100644 src/core/platform/wifi/nm-wifi-utils-wext.c delete mode 100644 src/core/platform/wifi/nm-wifi-utils-wext.h delete mode 100644 src/core/platform/wifi/nm-wifi-utils.c delete mode 100644 src/core/platform/wifi/nm-wifi-utils.h delete mode 100644 src/core/platform/wpan/nm-wpan-utils.c delete mode 100644 src/core/platform/wpan/nm-wpan-utils.h mode change 100644 => 100755 src/core/settings/plugins/ifcfg-rh/nm-ifdown mode change 100644 => 100755 src/core/settings/plugins/ifcfg-rh/nm-ifup create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-1.cexpected create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-2.cexpected create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-3.cexpected create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-4.cexpected create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-5.cexpected delete mode 100644 src/core/systemd/meson.build delete mode 100644 src/core/systemd/nm-default-systemd.h delete mode 100644 src/core/systemd/nm-sd-utils-core.c delete mode 100644 src/core/systemd/nm-sd-utils-core.h delete mode 100644 src/core/systemd/nm-sd-utils-dhcp.c delete mode 100644 src/core/systemd/nm-sd-utils-dhcp.h delete mode 100644 src/core/systemd/nm-sd.c delete mode 100644 src/core/systemd/nm-sd.h delete mode 100644 src/core/systemd/sd-adapt-core/condition.h delete mode 100644 src/core/systemd/sd-adapt-core/conf-parser.h delete mode 100644 src/core/systemd/sd-adapt-core/device-util.h delete mode 100644 src/core/systemd/sd-adapt-core/khash.h delete mode 100644 src/core/systemd/sd-adapt-core/network-util.h delete mode 100644 src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c delete mode 100644 src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h delete mode 100644 src/core/systemd/sd-adapt-core/sd-daemon.h delete mode 100644 src/core/systemd/sd-adapt-core/sd-device.h delete mode 100644 src/core/systemd/sd-adapt-core/udev-util.h delete mode 100644 src/core/systemd/src/libsystemd-network/arp-util.c delete mode 100644 src/core/systemd/src/libsystemd-network/arp-util.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-identifier.c delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-identifier.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-internal.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-network.c delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-option.c delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-packet.c delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp-protocol.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp6-internal.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp6-network.c delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp6-option.c delete mode 100644 src/core/systemd/src/libsystemd-network/dhcp6-protocol.h delete mode 100644 src/core/systemd/src/libsystemd-network/lldp-internal.h delete mode 100644 src/core/systemd/src/libsystemd-network/lldp-neighbor.c delete mode 100644 src/core/systemd/src/libsystemd-network/lldp-neighbor.h delete mode 100644 src/core/systemd/src/libsystemd-network/lldp-network.c delete mode 100644 src/core/systemd/src/libsystemd-network/lldp-network.h delete mode 100644 src/core/systemd/src/libsystemd-network/network-internal.c delete mode 100644 src/core/systemd/src/libsystemd-network/network-internal.h delete mode 100644 src/core/systemd/src/libsystemd-network/sd-dhcp-client.c delete mode 100644 src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c delete mode 100644 src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c delete mode 100644 src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c delete mode 100644 src/core/systemd/src/libsystemd-network/sd-ipv4acd.c delete mode 100644 src/core/systemd/src/libsystemd-network/sd-ipv4ll.c delete mode 100644 src/core/systemd/src/libsystemd-network/sd-lldp.c delete mode 100644 src/core/systemd/src/libsystemd/sd-event/event-source.h delete mode 100644 src/core/systemd/src/libsystemd/sd-event/event-util.c delete mode 100644 src/core/systemd/src/libsystemd/sd-event/event-util.h delete mode 100644 src/core/systemd/src/libsystemd/sd-event/sd-event.c delete mode 100644 src/core/systemd/src/libsystemd/sd-id128/id128-util.c delete mode 100644 src/core/systemd/src/libsystemd/sd-id128/id128-util.h delete mode 100644 src/core/systemd/src/libsystemd/sd-id128/sd-id128.c delete mode 100644 src/core/systemd/src/systemd/_sd-common.h delete mode 100644 src/core/systemd/src/systemd/sd-dhcp-client.h delete mode 100644 src/core/systemd/src/systemd/sd-dhcp-lease.h delete mode 100644 src/core/systemd/src/systemd/sd-dhcp-option.h delete mode 100644 src/core/systemd/src/systemd/sd-dhcp6-client.h delete mode 100644 src/core/systemd/src/systemd/sd-dhcp6-lease.h delete mode 100644 src/core/systemd/src/systemd/sd-dhcp6-option.h delete mode 100644 src/core/systemd/src/systemd/sd-event.h delete mode 100644 src/core/systemd/src/systemd/sd-id128.h delete mode 100644 src/core/systemd/src/systemd/sd-ipv4acd.h delete mode 100644 src/core/systemd/src/systemd/sd-ipv4ll.h delete mode 100644 src/core/systemd/src/systemd/sd-lldp.h delete mode 100644 src/core/systemd/src/systemd/sd-ndisc.h (limited to 'src/core') diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 54072210..7d3e80be 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -12,19 +12,23 @@ #include #include -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-c-list.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-base/nm-net-aux.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-utils.h" #include "nm-setting-connection.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" -#include "nm-core-internal.h" -#include "platform/nmp-object.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nmp-object.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nm-linux-platform.h" #include "nm-auth-utils.h" -#include "systemd/nm-sd-utils-shared.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" /*****************************************************************************/ @@ -252,7 +256,7 @@ nm_utils_complete_generic(NMPlatform * platform, g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_buf(uuid), + nm_uuid_generate_random_str_arr(uuid), NULL); } @@ -902,10 +906,16 @@ nm_match_spec_device_by_pllink(const NMPlatformLink *pllink, NMPlatformRoutingRule * nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rule, NMPlatformRoutingRule *out_pl) { + gboolean uid_range_has; + guint32 uid_range_start = 0; + guint32 uid_range_end = 0; + nm_assert(rule); nm_assert(nm_ip_routing_rule_validate(rule, NULL)); nm_assert(out_pl); + uid_range_has = nm_ip_routing_rule_get_uid_range(rule, &uid_range_start, &uid_range_end); + *out_pl = (NMPlatformRoutingRule){ .addr_family = nm_ip_routing_rule_get_addr_family(rule), .flags = (nm_ip_routing_rule_get_invert(rule) ? FIB_RULE_INVERT : 0), @@ -932,6 +942,12 @@ nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rule, NMPlatformRoutingRul .table = nm_ip_routing_rule_get_table(rule), .suppress_prefixlen_inverse = ~((guint32) nm_ip_routing_rule_get_suppress_prefixlength(rule)), + .uid_range_has = uid_range_has, + .uid_range = + { + .start = uid_range_start, + .end = uid_range_end, + }, }; nm_ip_routing_rule_get_xifname_bin(rule, TRUE, out_pl->iifname); @@ -1293,9 +1309,9 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, if ((variant = nm_ip_route_get_attribute(s_route, NM_IP_ROUTE_ATTRIBUTE_TYPE)) && g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) { - guint8 type; + int type; - type = nm_utils_route_type_by_name(g_variant_get_string(variant, NULL)); + type = nm_net_aux_rtnl_rtntype_a2n(g_variant_get_string(variant, NULL)); nm_assert(NM_IN_SET(type, RTN_UNICAST, RTN_LOCAL)); r->type_coerced = nm_platform_route_type_coerce(type); @@ -1482,12 +1498,7 @@ nm_utils_ip_addresses_to_dbus(int addr_family, : (guint32) 0, }; - g_variant_builder_add(&builder_legacy, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - dbus_addr, - 3, - sizeof(guint32))); + g_variant_builder_add(&builder_legacy, "@au", nm_g_variant_new_au(dbus_addr, 3)); } else { g_variant_builder_add( &builder_legacy, @@ -1609,12 +1620,7 @@ nm_utils_ip_routes_to_dbus(int addr_family, r->r4.metric, }; - g_variant_builder_add(&builder_legacy, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - dbus_route, - 4, - sizeof(guint32))); + g_variant_builder_add(&builder_legacy, "@au", nm_g_variant_new_au(dbus_route, 4)); } else { g_variant_builder_add(&builder_legacy, "(@ayu@ayu)", @@ -1632,200 +1638,60 @@ nm_utils_ip_routes_to_dbus(int addr_family, /*****************************************************************************/ -typedef struct { - char *table; - char *rule; -} ShareRule; +/* Singleton NMPlatform subclass instance and cached class object */ +NM_DEFINE_SINGLETON_INSTANCE(NMPlatform); -struct _NMUtilsShareRules { - GArray *rules; -}; - -static void -_share_rule_clear(gpointer data) -{ - ShareRule *rule = data; - - g_free(rule->table); - g_free(rule->rule); -} - -NMUtilsShareRules * -nm_utils_share_rules_new(void) -{ - NMUtilsShareRules *self; - - self = g_slice_new(NMUtilsShareRules); - *self = (NMUtilsShareRules){ - .rules = g_array_sized_new(FALSE, FALSE, sizeof(ShareRule), 10), - }; - - g_array_set_clear_func(self->rules, _share_rule_clear); - return self; -} +NM_DEFINE_SINGLETON_REGISTER(NMPlatform); +/** + * nm_platform_setup: + * @instance: the #NMPlatform instance + * + * Failing to set up #NMPlatform singleton results in a fatal error, + * as well as trying to initialize it multiple times without freeing + * it. + * + * NetworkManager will typically use only one platform object during + * its run. Test programs might want to switch platform implementations, + * though. + */ void -nm_utils_share_rules_free(NMUtilsShareRules *self) +nm_platform_setup(NMPlatform *instance) { - if (!self) - return; + g_return_if_fail(NM_IS_PLATFORM(instance)); + g_return_if_fail(!singleton_instance); - g_array_unref(self->rules); - nm_g_slice_free(self); -} - -void -nm_utils_share_rules_add_rule_take(NMUtilsShareRules *self, const char *table, char *rule_take) -{ - ShareRule *rule; + singleton_instance = instance; - g_return_if_fail(self); - g_return_if_fail(table); - g_return_if_fail(rule_take); + nm_singleton_instance_register(); - rule = nm_g_array_append_new(self->rules, ShareRule); - *rule = (ShareRule){ - .table = g_strdup(table), - .rule = g_steal_pointer(&rule_take), - }; + nm_log_dbg(LOGD_CORE, + "setup %s singleton (" NM_HASH_OBFUSCATE_PTR_FMT ")", + "NMPlatform", + NM_HASH_OBFUSCATE_PTR(instance)); } -void -nm_utils_share_rules_apply(NMUtilsShareRules *self, gboolean shared) +/** + * nm_platform_get: + * @self: platform instance + * + * Retrieve #NMPlatform singleton. Use this whenever you want to connect to + * #NMPlatform signals. It is an error to call it before nm_platform_setup(). + * + * Returns: (transfer none): The #NMPlatform singleton reference. + */ +NMPlatform * +nm_platform_get() { - guint i; - - g_return_if_fail(self); + g_assert(singleton_instance); - if (self->rules->len == 0) - return; - - /* depending on whether we share or unshare, we add/remote the rules - * in opposite order. */ - if (shared) - i = self->rules->len - 1; - else - i = 0; - - for (;;) { - gs_free_error GError *error = NULL; - ShareRule * rule; - gs_free const char ** argv = NULL; - gs_free char * cmd = NULL; - int status; - - rule = &g_array_index(self->rules, ShareRule, i); - - cmd = g_strdup_printf("%s --table %s %s %s", - IPTABLES_PATH, - rule->table, - shared ? "--insert" : "--delete", - rule->rule); - argv = nm_utils_strsplit_set(cmd, " "); - - nm_log_info(LOGD_SHARING, "Executing: %s", cmd); - if (!g_spawn_sync("/", - (char **) argv, - (char **) NM_PTRARRAY_EMPTY(const char *), - G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, - NULL, - NULL, - NULL, - NULL, - &status, - &error)) { - nm_log_warn(LOGD_SHARING, "Error executing command: %s", error->message); - goto next; - } - if (WEXITSTATUS(status)) { - nm_log_warn(LOGD_SHARING, "** Command returned exit status %d.", WEXITSTATUS(status)); - } - -next: - if (shared) { - if (i == 0) - break; - i--; - } else { - i++; - if (i >= self->rules->len) - break; - } - } + return singleton_instance; } +/*****************************************************************************/ + void -nm_utils_share_rules_add_all_rules(NMUtilsShareRules *self, - const char * ip_iface, - in_addr_t addr, - guint plen) +nm_linux_platform_setup(void) { - in_addr_t netmask; - in_addr_t network; - char str_mask[NM_UTILS_INET_ADDRSTRLEN]; - char str_addr[NM_UTILS_INET_ADDRSTRLEN]; - - nm_assert(self); - - netmask = _nm_utils_ip4_prefix_to_netmask(plen); - _nm_utils_inet4_ntop(netmask, str_mask); - - network = addr & netmask; - _nm_utils_inet4_ntop(network, str_addr); - - nm_utils_share_rules_add_rule_v( - self, - "nat", - "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", - str_addr, - str_mask, - str_addr, - str_mask); - nm_utils_share_rules_add_rule_v( - self, - "filter", - "FORWARD --destination %s/%s --out-interface %s --match state --state " - "ESTABLISHED,RELATED --jump ACCEPT", - str_addr, - str_mask, - ip_iface); - nm_utils_share_rules_add_rule_v(self, - "filter", - "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", - str_addr, - str_mask, - ip_iface); - nm_utils_share_rules_add_rule_v(self, - "filter", - "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", - ip_iface, - ip_iface); - nm_utils_share_rules_add_rule_v(self, - "filter", - "FORWARD --out-interface %s --jump REJECT", - ip_iface); - nm_utils_share_rules_add_rule_v(self, - "filter", - "FORWARD --in-interface %s --jump REJECT", - ip_iface); - nm_utils_share_rules_add_rule_v( - self, - "filter", - "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", - ip_iface); - nm_utils_share_rules_add_rule_v( - self, - "filter", - "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", - ip_iface); - nm_utils_share_rules_add_rule_v( - self, - "filter", - "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", - ip_iface); - nm_utils_share_rules_add_rule_v( - self, - "filter", - "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", - ip_iface); + nm_platform_setup(nm_linux_platform_new(FALSE, FALSE)); } diff --git a/src/core/NetworkManagerUtils.h b/src/core/NetworkManagerUtils.h index 2afb5a3e..1c86387c 100644 --- a/src/core/NetworkManagerUtils.h +++ b/src/core/NetworkManagerUtils.h @@ -8,10 +8,10 @@ #define __NETWORKMANAGER_UTILS_H__ #include "nm-core-utils.h" -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-setting-ip-config.h" #include "nm-setting-ip6-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" /*****************************************************************************/ @@ -197,18 +197,20 @@ nm_dhcp_lease_get_options(NMDhcpLease *lease) return (GHashTable *) lease; } -static inline void +static inline NMDhcpLease * nm_dhcp_lease_ref(NMDhcpLease *lease) { if (lease) g_hash_table_ref((GHashTable *) lease); + return lease; } -static inline void +static inline NMDhcpLease * nm_dhcp_lease_unref(NMDhcpLease *lease) { if (lease) g_hash_table_unref((GHashTable *) lease); + return NULL; } static inline const char * @@ -224,30 +226,12 @@ NM_AUTO_DEFINE_FCN(NMDhcpLease *, _nm_auto_unref_dhcplease, nm_dhcp_lease_unref) /*****************************************************************************/ -typedef struct _NMUtilsShareRules NMUtilsShareRules; - -NMUtilsShareRules *nm_utils_share_rules_new(void); - -void nm_utils_share_rules_free(NMUtilsShareRules *self); - -void -nm_utils_share_rules_add_rule_take(NMUtilsShareRules *self, const char *table, char *rule_take); - -static inline void -nm_utils_share_rules_add_rule(NMUtilsShareRules *self, const char *table, const char *rule) -{ - nm_utils_share_rules_add_rule_take(self, table, g_strdup(rule)); -} - -#define nm_utils_share_rules_add_rule_v(self, table, ...) \ - nm_utils_share_rules_add_rule_take((self), (table), g_strdup_printf(__VA_ARGS__)) +void nm_platform_setup(NMPlatform *instance); +NMPlatform *nm_platform_get(void); -void nm_utils_share_rules_add_all_rules(NMUtilsShareRules *self, - const char * ip_iface, - in_addr_t addr, - guint plen); +#define NM_PLATFORM_GET (nm_platform_get()) -void nm_utils_share_rules_apply(NMUtilsShareRules *self, gboolean shared); +void nm_linux_platform_setup(void); /*****************************************************************************/ diff --git a/src/core/devices/adsl/meson.build b/src/core/devices/adsl/meson.build index 95f61d95..ef87c6e8 100644 --- a/src/core/devices/adsl/meson.build +++ b/src/core/devices/adsl/meson.build @@ -7,7 +7,6 @@ libnm_device_plugin_adsl = shared_module( 'nm-device-adsl.c', ), dependencies: core_plugin_dep, - c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, diff --git a/src/core/devices/adsl/nm-atm-manager.c b/src/core/devices/adsl/nm-atm-manager.c index 9be9b5ce..bd9ed8cc 100644 --- a/src/core/devices/adsl/nm-atm-manager.c +++ b/src/core/devices/adsl/nm-atm-manager.c @@ -11,8 +11,8 @@ #include "nm-setting-adsl.h" #include "nm-device-adsl.h" #include "devices/nm-device-factory.h" -#include "platform/nm-platform.h" -#include "nm-udev-aux/nm-udev-utils.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-udev-aux/nm-udev-utils.h" /*****************************************************************************/ diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c index 34c062a8..4e4c9dcc 100644 --- a/src/core/devices/adsl/nm-device-adsl.c +++ b/src/core/devices/adsl/nm-device-adsl.c @@ -17,7 +17,7 @@ #include "nm-ip4-config.h" #include "devices/nm-device-private.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "ppp/nm-ppp-manager-call.h" #include "ppp/nm-ppp-status.h" #include "nm-setting-adsl.h" @@ -265,7 +265,7 @@ pppoe_vcc_config(NMDeviceAdsl *self) _LOGD(LOGD_ADSL, "ATM setup successful"); /* otherwise we're good for stage3 */ - nm_platform_link_set_up(nm_device_get_platform(device), priv->nas_ifindex, NULL); + nm_platform_link_change_flags(nm_device_get_platform(device), priv->nas_ifindex, IFF_UP, TRUE); return TRUE; } @@ -674,12 +674,8 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_adsl = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_ADSL, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", - "b", - NM_DEVICE_CARRIER), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), ), ), }; static void diff --git a/src/core/devices/bluetooth/meson.build b/src/core/devices/bluetooth/meson.build index d5f26068..5b196d08 100644 --- a/src/core/devices/bluetooth/meson.build +++ b/src/core/devices/bluetooth/meson.build @@ -8,11 +8,11 @@ libnm_device_plugin_bluetooth_static = static_library( 'nm-device-bt.c', ) + (enable_bluez5_dun ? files('nm-bluez5-dun.c') : files()), dependencies: [ + libnm_core_public_dep, core_default_dep, libnm_wwan_dep, bluez5_dep, ], - c_args: daemon_c_flags, ) libnm_device_plugin_bluetooth_static_dep = declare_dependency( diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index 459ea409..fc081580 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -12,8 +12,9 @@ #include #include -#include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-dbus-aux.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-dbus-manager.h" #include "devices/nm-device-factory.h" #include "devices/nm-device-bridge.h" @@ -23,9 +24,9 @@ #include "nm-device-bt.h" #include "nm-manager.h" #include "nm-bluez5-dun.h" -#include "nm-core-internal.h" -#include "platform/nm-platform.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-std-aux/nm-dbus-compat.h" /*****************************************************************************/ @@ -574,11 +575,12 @@ _bzobj_to_string(const BzDBusObj *bzobj, char *buf, gsize len) #define _LOG_bzobj(bzobj, context) \ G_STMT_START \ { \ - const BzDBusObj *const _bzobj = (bzobj); \ + const BzDBusObj *const _bzobj = (bzobj); \ + const char *const _context = (context); \ char _buf[500]; \ \ _LOGT("change %-21s %s : { %s }", \ - (context), \ + _context, \ _bzobj->object_path, \ _bzobj_to_string(_bzobj, _buf, sizeof(_buf))); \ } \ @@ -1321,7 +1323,7 @@ _conn_create_panu_connection(NMBluezManager *self, BzDBusObj *bzobj) char uuid[37]; gs_free_error GError *error = NULL; - nm_utils_uuid_generate_buf(uuid); + nm_uuid_generate_random_str_arr(uuid); id = g_strdup_printf(_("%s Network"), bzobj->d_device.name); connection = nm_simple_connection_new(); diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index c07be2d3..8f4ceba7 100644 --- a/src/core/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -10,7 +10,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-bluez-common.h" #include "nm-bluez-manager.h" #include "devices/nm-device-private.h" @@ -26,7 +26,7 @@ #include "nm-utils.h" #include "nm-bt-error.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "devices/wwan/nm-modem-manager.h" #include "devices/wwan/nm-modem.h" @@ -1317,16 +1317,12 @@ finalize(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_bluetooth = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_BLUETOOTH, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Name", "s", NM_DEVICE_BT_NAME), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("BtCapabilities", - "u", - NM_DEVICE_BT_CAPABILITIES), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Name", "s", NM_DEVICE_BT_NAME), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("BtCapabilities", + "u", + NM_DEVICE_BT_CAPABILITIES), ), ), }; static void diff --git a/src/core/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c index 81a28797..145947bb 100644 --- a/src/core/devices/nm-acd-manager.c +++ b/src/core/devices/nm-acd-manager.c @@ -12,7 +12,7 @@ #include #include -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "n-acd/src/n-acd.h" diff --git a/src/core/devices/nm-device-6lowpan.c b/src/core/devices/nm-device-6lowpan.c index fe116dd4..96218658 100644 --- a/src/core/devices/nm-device-6lowpan.c +++ b/src/core/devices/nm-device-6lowpan.c @@ -9,7 +9,7 @@ #include "nm-device-private.h" #include "settings/nm-settings.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-6lowpan.h" #include "nm-utils.h" diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 9c1c484f..b208e2c0 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -12,9 +12,9 @@ #include "NetworkManagerUtils.h" #include "nm-device-private.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-ip4-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceBond @@ -601,16 +601,10 @@ nm_device_bond_init(NMDeviceBond *self) static const NMDBusInterfaceInfoExtended interface_info_device_bond = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_BOND, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Slaves", - "ao", - NM_DEVICE_SLAVES), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), ), }; static void diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index c919d85d..a095dc3e 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -12,9 +12,9 @@ #include "NetworkManagerUtils.h" #include "nm-device-private.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceBridge #include "nm-device-logging.h" @@ -1033,7 +1033,7 @@ create_and_realize(NMDevice * device, const char * iface = nm_device_get_iface(device); const char * hwaddr; gs_free char * hwaddr_cloned = NULL; - guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX]; + guint8 mac_address[_NM_UTILS_HWADDR_LEN_MAX]; NMPlatformLnkBridge props; int r; guint32 mtu = 0; @@ -1142,16 +1142,10 @@ nm_device_bridge_init(NMDeviceBridge *self) static const NMDBusInterfaceInfoExtended interface_info_device_bridge = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_BRIDGE, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Slaves", - "ao", - NM_DEVICE_SLAVES), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), ), }; static void diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c index 13cfd3b0..488f0ba0 100644 --- a/src/core/devices/nm-device-dummy.c +++ b/src/core/devices/nm-device-dummy.c @@ -13,10 +13,10 @@ #include "nm-act-request.h" #include "nm-device-private.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-dummy.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceDummy #include "nm-device-logging.h" @@ -121,12 +121,10 @@ nm_device_dummy_init(NMDeviceDummy *self) static const NMDBusInterfaceInfoExtended interface_info_device_dummy = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_DUMMY, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", + "s", + NM_DEVICE_HW_ADDRESS), ), ), }; static void diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 59f6c613..95336c7a 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -14,6 +14,7 @@ #include #include +#include "libnm-glib-aux/nm-uuid.h" #include "nm-device-private.h" #include "nm-act-request.h" #include "nm-ip4-config.h" @@ -24,17 +25,17 @@ #include "ppp/nm-ppp-manager.h" #include "ppp/nm-ppp-manager-call.h" #include "ppp/nm-ppp-status.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nm-platform-utils.h" #include "nm-dcb.h" #include "settings/nm-settings-connection.h" #include "nm-config.h" #include "nm-device-ethernet-utils.h" #include "settings/nm-settings.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" -#include "nm-udev-aux/nm-udev-utils.h" +#include "libnm-udev-aux/nm-udev-utils.h" #include "nm-device-veth.h" #define _NMLOG_DEVICE_TYPE NMDeviceEthernet @@ -922,31 +923,33 @@ link_negotiation_set(NMDevice *device) return; } - /* If link negotiation setting are already in place do nothing and return with success */ - if (!!autoneg == !!link_autoneg && speed == link_speed && duplex == link_duplex) { - _LOGD(LOGD_DEVICE, "set-link: link negotiation is already configured"); - return; - } - if (autoneg && !speed && !duplex) _LOGD(LOGD_DEVICE, "set-link: configure auto-negotiation"); else { _LOGD(LOGD_DEVICE, - "set-link: configure %snegotiation (%u Mbit%s, %s duplex%s)", + "set-link: configure %snegotiation (%u Mbit, %s duplex)", autoneg ? "auto-" : "static ", - speed ?: link_speed, - speed ? "" : "*", - duplex ? nm_platform_link_duplex_type_to_string(duplex) - : nm_platform_link_duplex_type_to_string(link_duplex), - duplex ? "" : "*"); + speed, + nm_platform_link_duplex_type_to_string(duplex)); } if (!priv->ethtool_prev_set) { /* remember the values we had before setting it. */ priv->ethtool_prev_autoneg = link_autoneg; - priv->ethtool_prev_speed = link_speed; - priv->ethtool_prev_duplex = link_duplex; - priv->ethtool_prev_set = TRUE; + if (link_autoneg) { + /* with autoneg, we only support advertising one speed/duplex. Likewise + * our nm_platform_ethtool_get_link_settings() can only return the current + * speed/duplex, but not all the modes that we were advertising. + * + * Do the best we can do: remember to re-enable autoneg, but don't restrict + * the mode. */ + priv->ethtool_prev_speed = 0; + priv->ethtool_prev_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; + } else { + priv->ethtool_prev_speed = link_speed; + priv->ethtool_prev_duplex = link_duplex; + } + priv->ethtool_prev_set = TRUE; } if (!nm_platform_ethtool_set_link_settings(nm_device_get_platform(device), @@ -1718,11 +1721,11 @@ new_default_connection(NMDevice *self) /* Create a stable UUID. The UUID is also the Network_ID for stable-privacy addr-gen-mode, * thus when it changes we will also generate different IPv6 addresses. */ - uuid = _nm_utils_uuid_generate_from_strings("default-wired", - nm_utils_machine_id_str(), - defname, - perm_hw_addr ?: iface, - NULL); + uuid = nm_uuid_generate_from_strings("default-wired", + nm_utils_machine_id_str(), + defname, + perm_hw_addr ?: iface, + NULL); g_object_set(setting, NM_SETTING_CONNECTION_ID, @@ -1747,7 +1750,7 @@ new_default_connection(NMDevice *self) if (dev) uprop = udev_device_get_property_value(dev, "NM_AUTO_DEFAULT_LINK_LOCAL_ONLY"); - if (nm_udev_utils_property_as_boolean(uprop)) { + if (_nm_utils_ascii_str_to_bool(uprop, FALSE)) { setting = nm_setting_ip4_config_new(); g_object_set(setting, NM_SETTING_IP_CONFIG_METHOD, @@ -1786,7 +1789,8 @@ update_connection(NMDevice *device, NMConnection *connection) const char * mac = nm_device_get_hw_address(device); const char * mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; GHashTableIter iter; - gpointer key, value; + const char * key; + const char * value; if (!s_wired) { s_wired = (NMSettingWired *) nm_setting_wired_new(); @@ -1824,8 +1828,8 @@ update_connection(NMDevice *device, NMConnection *connection) _nm_setting_wired_clear_s390_options(s_wired); g_hash_table_iter_init(&iter, priv->s390_options); - while (g_hash_table_iter_next(&iter, &key, &value)) - nm_setting_wired_add_s390_option(s_wired, (const char *) key, (const char *) value); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) + nm_setting_wired_add_s390_option(s_wired, key, value); } static void @@ -2000,24 +2004,16 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps static const NMDBusInterfaceInfoExtended interface_info_device_wired = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_WIRED, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PermHwAddress", - "s", - NM_DEVICE_PERM_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Speed", - "u", - NM_DEVICE_ETHERNET_SPEED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("S390Subchannels", - "as", - NM_DEVICE_ETHERNET_S390_SUBCHANNELS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", - "b", - NM_DEVICE_CARRIER), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PermHwAddress", + "s", + NM_DEVICE_PERM_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Speed", "u", NM_DEVICE_ETHERNET_SPEED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("S390Subchannels", + "as", + NM_DEVICE_ETHERNET_S390_SUBCHANNELS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), ), ), }; static void diff --git a/src/core/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c index 81124a8d..bdc64135 100644 --- a/src/core/devices/nm-device-factory.c +++ b/src/core/devices/nm-device-factory.c @@ -11,9 +11,9 @@ #include #include -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-bluetooth.h" #define PLUGIN_PREFIX "libnm-device-plugin-" diff --git a/src/core/devices/nm-device-generic.c b/src/core/devices/nm-device-generic.c index a319666a..08ea5ac5 100644 --- a/src/core/devices/nm-device-generic.c +++ b/src/core/devices/nm-device-generic.c @@ -8,8 +8,8 @@ #include "nm-device-generic.h" #include "nm-device-private.h" -#include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ @@ -191,16 +191,12 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_generic = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_GENERIC, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE( "TypeDescription", "s", NM_DEVICE_GENERIC_TYPE_DESCRIPTION), ), ), - .legacy_property_changed = TRUE, }; static void diff --git a/src/core/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c index f54ffcf0..37065bc8 100644 --- a/src/core/devices/nm-device-infiniband.c +++ b/src/core/devices/nm-device-infiniband.c @@ -14,9 +14,9 @@ #include "nm-device-private.h" #include "nm-act-request.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define NM_DEVICE_INFINIBAND_IS_PARTITION "is-partition" @@ -366,15 +366,9 @@ nm_device_infiniband_init(NMDeviceInfiniband *self) static const NMDBusInterfaceInfoExtended interface_info_device_infiniband = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_INFINIBAND, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", - "b", - NM_DEVICE_CARRIER), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), ), ), }; static void diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index da6afb3b..c55dd9f6 100644 --- a/src/core/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -16,9 +16,9 @@ #include "nm-device-private.h" #include "nm-manager.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-ip4-config.h" @@ -1050,39 +1050,33 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_ip_tunnel = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "u", NM_DEVICE_IP_TUNNEL_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Local", - "s", - NM_DEVICE_IP_TUNNEL_LOCAL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Remote", - "s", - NM_DEVICE_IP_TUNNEL_REMOTE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ttl", "y", NM_DEVICE_IP_TUNNEL_TTL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Tos", "y", NM_DEVICE_IP_TUNNEL_TOS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L( - "PathMtuDiscovery", - "b", - NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("InputKey", - "s", - NM_DEVICE_IP_TUNNEL_INPUT_KEY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("OutputKey", - "s", - NM_DEVICE_IP_TUNNEL_OUTPUT_KEY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L( - "EncapsulationLimit", - "y", - NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("FlowLabel", - "u", - NM_DEVICE_IP_TUNNEL_FLOW_LABEL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Flags", - "u", - NM_DEVICE_IP_TUNNEL_FLAGS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "u", NM_DEVICE_IP_TUNNEL_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Local", "s", NM_DEVICE_IP_TUNNEL_LOCAL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Remote", + "s", + NM_DEVICE_IP_TUNNEL_REMOTE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ttl", "y", NM_DEVICE_IP_TUNNEL_TTL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Tos", "y", NM_DEVICE_IP_TUNNEL_TOS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PathMtuDiscovery", + "b", + NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("InputKey", + "s", + NM_DEVICE_IP_TUNNEL_INPUT_KEY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("OutputKey", + "s", + NM_DEVICE_IP_TUNNEL_OUTPUT_KEY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("EncapsulationLimit", + "y", + NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FlowLabel", + "u", + NM_DEVICE_IP_TUNNEL_FLOW_LABEL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Flags", + "u", + NM_DEVICE_IP_TUNNEL_FLAGS), ), ), }; static void diff --git a/src/core/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c index 51b820a1..51b7225b 100644 --- a/src/core/devices/nm-device-macsec.c +++ b/src/core/devices/nm-device-macsec.c @@ -11,11 +11,11 @@ #include "nm-act-request.h" #include "nm-device-private.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-manager.h" #include "nm-setting-macsec.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "supplicant/nm-supplicant-manager.h" #include "supplicant/nm-supplicant-interface.h" #include "supplicant/nm-supplicant-config.h" @@ -870,40 +870,36 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_macsec = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_MACSEC, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Sci", "t", NM_DEVICE_MACSEC_SCI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("IcvLength", - "y", - NM_DEVICE_MACSEC_ICV_LENGTH), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("CipherSuite", - "t", - NM_DEVICE_MACSEC_CIPHER_SUITE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Window", - "u", - NM_DEVICE_MACSEC_WINDOW), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("EncodingSa", - "y", - NM_DEVICE_MACSEC_ENCODING_SA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Validation", - "s", - NM_DEVICE_MACSEC_VALIDATION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Encrypt", - "b", - NM_DEVICE_MACSEC_ENCRYPT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Protect", - "b", - NM_DEVICE_MACSEC_PROTECT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("IncludeSci", - "b", - NM_DEVICE_MACSEC_INCLUDE_SCI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Es", "b", NM_DEVICE_MACSEC_ES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Scb", "b", NM_DEVICE_MACSEC_SCB), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ReplayProtect", - "b", - NM_DEVICE_MACSEC_REPLAY_PROTECT), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Sci", "t", NM_DEVICE_MACSEC_SCI), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("IcvLength", + "y", + NM_DEVICE_MACSEC_ICV_LENGTH), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("CipherSuite", + "t", + NM_DEVICE_MACSEC_CIPHER_SUITE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Window", "u", NM_DEVICE_MACSEC_WINDOW), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("EncodingSa", + "y", + NM_DEVICE_MACSEC_ENCODING_SA), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Validation", + "s", + NM_DEVICE_MACSEC_VALIDATION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Encrypt", + "b", + NM_DEVICE_MACSEC_ENCRYPT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Protect", + "b", + NM_DEVICE_MACSEC_PROTECT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("IncludeSci", + "b", + NM_DEVICE_MACSEC_INCLUDE_SCI), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Es", "b", NM_DEVICE_MACSEC_ES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Scb", "b", NM_DEVICE_MACSEC_SCB), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ReplayProtect", + "b", + NM_DEVICE_MACSEC_REPLAY_PROTECT), ), ), }; static void diff --git a/src/core/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c index e8b39ed6..7302ecdf 100644 --- a/src/core/devices/nm-device-macvlan.c +++ b/src/core/devices/nm-device-macvlan.c @@ -13,7 +13,7 @@ #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-manager.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-macvlan.h" #include "nm-setting-wired.h" @@ -502,17 +502,13 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_macvlan = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_MACVLAN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "s", NM_DEVICE_MACVLAN_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("NoPromisc", - "b", - NM_DEVICE_MACVLAN_NO_PROMISC), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Tab", - "b", - NM_DEVICE_MACVLAN_TAP), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "s", NM_DEVICE_MACVLAN_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NoPromisc", + "b", + NM_DEVICE_MACVLAN_NO_PROMISC), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Tab", "b", NM_DEVICE_MACVLAN_TAP), ), ), }; static void diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c index 4040f2d3..8df245bb 100644 --- a/src/core/devices/nm-device-ppp.c +++ b/src/core/devices/nm-device-ppp.c @@ -13,7 +13,7 @@ #include "nm-device-private.h" #include "nm-manager.h" #include "nm-setting-pppoe.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "ppp/nm-ppp-manager.h" #include "ppp/nm-ppp-manager-call.h" #include "ppp/nm-ppp-status.h" @@ -274,10 +274,7 @@ dispose(GObject *object) } static const NMDBusInterfaceInfoExtended interface_info_device_ppp = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( - NM_DBUS_INTERFACE_DEVICE_PPP, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), - .legacy_property_changed = TRUE, + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(NM_DBUS_INTERFACE_DEVICE_PPP, ), }; static void diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index 8675a699..eb37b14f 100644 --- a/src/core/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -17,14 +17,6 @@ typedef enum { NM_DEVICE_STAGE_STATE_COMPLETED = 2, } NMDeviceStageState; -typedef enum { - NM_DEVICE_IP_STATE_NONE, - NM_DEVICE_IP_STATE_WAIT, - NM_DEVICE_IP_STATE_CONF, - NM_DEVICE_IP_STATE_DONE, - NM_DEVICE_IP_STATE_FAIL, -} NMDeviceIPState; - enum NMActStageReturn { NM_ACT_STAGE_RETURN_FAILURE = 0, /* Hard failure of activation */ NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */ @@ -117,8 +109,6 @@ nm_device_activate_ip6_state_done(NMDevice *self) return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_DONE; } -void nm_device_set_dhcp_anycast_address(NMDevice *device, const char *addr); - gboolean nm_device_dhcp4_renew(NMDevice *device, gboolean release); gboolean nm_device_dhcp6_renew(NMDevice *device, gboolean release); diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index edca69e9..ebccddfc 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -14,10 +14,10 @@ #include "nm-act-request.h" #include "nm-device-private.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-tun.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceTun #include "nm-device-logging.h" @@ -444,22 +444,18 @@ nm_device_tun_init(NMDeviceTun *self) static const NMDBusInterfaceInfoExtended interface_info_device_tun = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_TUN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Owner", "x", NM_DEVICE_TUN_OWNER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Group", "x", NM_DEVICE_TUN_GROUP), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "s", NM_DEVICE_TUN_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("NoPi", "b", NM_DEVICE_TUN_NO_PI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("VnetHdr", - "b", - NM_DEVICE_TUN_VNET_HDR), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("MultiQueue", - "b", - NM_DEVICE_TUN_MULTI_QUEUE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Owner", "x", NM_DEVICE_TUN_OWNER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Group", "x", NM_DEVICE_TUN_GROUP), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "s", NM_DEVICE_TUN_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NoPi", "b", NM_DEVICE_TUN_NO_PI), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("VnetHdr", "b", NM_DEVICE_TUN_VNET_HDR), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("MultiQueue", + "b", + NM_DEVICE_TUN_MULTI_QUEUE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", + "s", + NM_DEVICE_HW_ADDRESS), ), ), }; static void diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c new file mode 100644 index 00000000..f40ca570 --- /dev/null +++ b/src/core/devices/nm-device-utils.c @@ -0,0 +1,356 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "src/core/nm-default-daemon.h" +#include "src/core/dns/nm-dns-manager.h" +#include "src/core/dns/nm-dns-systemd-resolved.h" + +#include "nm-device-utils.h" +#include "nm-core-utils.h" + +/*****************************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE( + nm_device_state_queued_state_to_str, + NMDeviceState, + NM_UTILS_LOOKUP_DEFAULT(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNKNOWN, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNMANAGED, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unmanaged"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNAVAILABLE, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unavailable"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_DISCONNECTED, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "disconnected"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_PREPARE, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "prepare"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_CONFIG, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "config"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_NEED_AUTH, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "need-auth"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_IP_CONFIG, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-config"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_IP_CHECK, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-check"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_SECONDARIES, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "secondaries"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_ACTIVATED, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "activated"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_DEACTIVATING, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "deactivating"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_FAILED, + NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"), ); + +const char * +nm_device_state_to_str(NMDeviceState state) +{ + return nm_device_state_queued_state_to_str(state) + + NM_STRLEN(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE); +} + +NM_UTILS_LOOKUP_STR_DEFINE( + nm_device_state_reason_to_str, + NMDeviceStateReason, + NM_UTILS_LOOKUP_DEFAULT(NULL), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NOW_MANAGED, "managed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NOW_UNMANAGED, "unmanaged"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONFIG_FAILED, "config-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, "ip-config-unavailable"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, "ip-config-expired"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NO_SECRETS, "no-secrets"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, "supplicant-disconnect"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED, + "supplicant-config-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, "supplicant-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, "supplicant-timeout"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_START_FAILED, "ppp-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_DISCONNECT, "ppp-disconnect"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_FAILED, "ppp-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_START_FAILED, "dhcp-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_ERROR, "dhcp-error"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_FAILED, "dhcp-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SHARED_START_FAILED, "sharing-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SHARED_FAILED, "sharing-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, "autoip-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_ERROR, "autoip-error"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_FAILED, "autoip-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_BUSY, "modem-busy"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, "modem-no-dialtone"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, "modem-no-carrier"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, "modem-dial-timeout"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, "modem-dial-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, "modem-init-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_APN_FAILED, "gsm-apn-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, + "gsm-registration-idle"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED, + "gsm-registration-denied"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT, + "gsm-registration-timeout"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, + "gsm-registration-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, "gsm-pin-check-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, "firmware-missing"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_REMOVED, "removed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SLEEPING, "sleeping"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, "connection-removed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_USER_REQUESTED, "user-requested"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CARRIER, "carrier-changed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, "connection-assumed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, "supplicant-available"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, "modem-not-found"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_BT_FAILED, "bluetooth-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, "gsm-sim-not-inserted"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, "gsm-sim-pin-required"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, "gsm-sim-puk-required"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, "gsm-sim-wrong"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_INFINIBAND_MODE, "infiniband-mode"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, "dependency-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_BR2684_FAILED, "br2684-bridge-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE, + "modem-manager-unavailable"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, "ssid-not-found"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED, + "secondary-connection-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, "dcb-fcoe-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, "teamd-control-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_FAILED, "modem-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, "modem-available"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, "sim-pin-incorrect"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NEW_ACTIVATION, "new-activation"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PARENT_CHANGED, "parent-changed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, + "parent-managed-changed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_OVSDB_FAILED, "ovsdb-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, + "sriov-configuration-failed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), ); + +NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_str, + NMDeviceMtuSource, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_PARENT, "parent"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_IP_CONFIG, "ip-config"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_CONNECTION, + "connection"), ); + +NM_UTILS_LOOKUP_STR_DEFINE(nm_device_sys_iface_state_to_str, + NMDeviceSysIfaceState, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_ASSUME, "assume"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_MANAGED, "managed"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_REMOVED, + "removed"), ); + +NM_UTILS_LOOKUP_STR_DEFINE(nm_device_ip_state_to_str, + NMDeviceIPState, + NM_UTILS_LOOKUP_DEFAULT_WARN("unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_WAIT, "wait"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_CONF, "conf"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_DONE, "done"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAIL, "fail"), ); + +/*****************************************************************************/ + +#define SD_RESOLVED_DNS (1UL << 0) +/* Don't answer request from locally synthesized records (which includes /etc/hosts) */ +#define SD_RESOLVED_NO_SYNTHESIZE (1UL << 11) + +typedef struct { + int addr_family; + NMIPAddr address; + gulong cancellable_id; + GTask * task; + NMDnsSystemdResolvedResolveHandle *resolved_handle; +} ResolveAddrInfo; + +#define _NMLOG_PREFIX_NAME "resolve-addr" +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG2(level, info, ...) \ + G_STMT_START \ + { \ + if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \ + ResolveAddrInfo *_info = (info); \ + char _addr_str[NM_UTILS_INET_ADDRSTRLEN]; \ + \ + _nm_log((level), \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ + _NMLOG_PREFIX_NAME "[" NM_HASH_OBFUSCATE_PTR_FMT \ + ",%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_HASH_OBFUSCATE_PTR(_info), \ + nm_utils_inet_ntop(_info->addr_family, &_info->address, _addr_str) \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +static void +resolve_addr_info_free(ResolveAddrInfo *info) +{ + nm_assert(info->cancellable_id == 0); + nm_assert(!info->resolved_handle); + g_object_unref(info->task); + g_free(info); +} + +static void +resolve_addr_complete(ResolveAddrInfo *info, char *hostname_take, GError *error_take) +{ + nm_assert(!!hostname_take != !!error_take); + + nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task), &info->cancellable_id); + if (error_take) + g_task_return_error(info->task, error_take); + else + g_task_return_pointer(info->task, hostname_take, g_free); + + resolve_addr_info_free(info); +} + +static void +resolve_addr_helper_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + ResolveAddrInfo *info = user_data; + gs_free_error GError *error = NULL; + gs_free char * output = NULL; + + output = nm_utils_spawn_helper_finish(result, &error); + if (nm_utils_error_is_cancelled(error)) + return; + + _LOG2D(info, "helper returned hostname '%s'", output); + + resolve_addr_complete(info, g_steal_pointer(&output), g_steal_pointer(&error)); +} + +static void +resolve_addr_spawn_helper(ResolveAddrInfo *info) +{ + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + + nm_utils_inet_ntop(info->addr_family, &info->address, addr_str); + _LOG2D(info, "start lookup via nm-daemon-helper"); + nm_utils_spawn_helper(NM_MAKE_STRV("resolve-address", addr_str), + g_task_get_cancellable(info->task), + resolve_addr_helper_cb, + info); +} + +static void +resolve_addr_resolved_cb(NMDnsSystemdResolved * resolved, + NMDnsSystemdResolvedResolveHandle * handle, + const NMDnsSystemdResolvedAddressResult *names, + guint names_len, + guint64 flags, + GError * error, + gpointer user_data) +{ + ResolveAddrInfo *info = user_data; + + info->resolved_handle = NULL; + + if (nm_utils_error_is_cancelled(error)) + return; + + if (error) { + gs_free char *dbus_error = NULL; + + _LOG2D(info, "error resolving via systemd-resolved: %s", error->message); + + dbus_error = g_dbus_error_get_remote_error(error); + if (nm_streq0(dbus_error, "org.freedesktop.resolve1.DnsError.NXDOMAIN")) { + resolve_addr_complete(info, NULL, g_error_copy(error)); + return; + } + + resolve_addr_spawn_helper(info); + return; + } + + if (names_len == 0) { + _LOG2D(info, "systemd-resolved returned no result"); + resolve_addr_complete(info, g_strdup(""), NULL); + return; + } + + _LOG2D(info, "systemd-resolved returned hostname '%s'", names[0].name); + resolve_addr_complete(info, g_strdup(names[0].name), NULL); +} + +static void +resolve_addr_cancelled(GObject *object, gpointer user_data) +{ + ResolveAddrInfo *info = user_data; + GError * error = NULL; + + nm_clear_g_signal_handler(g_task_get_cancellable(info->task), &info->cancellable_id); + nm_clear_pointer(&info->resolved_handle, nm_dns_systemd_resolved_resolve_cancel); + nm_utils_error_set_cancelled(&error, FALSE, NULL); + resolve_addr_complete(info, NULL, error); +} + +void +nm_device_resolve_address(int addr_family, + gconstpointer address, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer cb_data) +{ + ResolveAddrInfo * info; + NMDnsSystemdResolved *resolved; + + info = g_new(ResolveAddrInfo, 1); + *info = (ResolveAddrInfo){ + .task = nm_g_task_new(NULL, cancellable, nm_device_resolve_address, callback, cb_data), + .addr_family = addr_family, + .address = nm_ip_addr_init(addr_family, address), + }; + + if (cancellable) { + gulong signal_id; + + signal_id = + g_cancellable_connect(cancellable, G_CALLBACK(resolve_addr_cancelled), info, NULL); + if (signal_id == 0) { + /* the request is already cancelled. Return. */ + return; + } + info->cancellable_id = signal_id; + } + + resolved = (NMDnsSystemdResolved *) nm_dns_manager_get_systemd_resolved(nm_dns_manager_get()); + if (resolved) { + _LOG2D(info, "start lookup via systemd-resolved"); + info->resolved_handle = + nm_dns_systemd_resolved_resolve_address(resolved, + 0, + addr_family, + address, + SD_RESOLVED_DNS | SD_RESOLVED_NO_SYNTHESIZE, + 20000, + resolve_addr_resolved_cb, + info); + return; + } + + resolve_addr_spawn_helper(info); +} + +char * +nm_device_resolve_address_finish(GAsyncResult *result, GError **error) +{ + GTask *task = G_TASK(result); + + nm_assert(nm_g_task_is_valid(result, NULL, nm_device_resolve_address)); + + return g_task_propagate_pointer(task, error); +} diff --git a/src/core/devices/nm-device-utils.h b/src/core/devices/nm-device-utils.h new file mode 100644 index 00000000..8bc957a4 --- /dev/null +++ b/src/core/devices/nm-device-utils.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef __DEVICES_NM_DEVICE_UTILS_H__ +#define __DEVICES_NM_DEVICE_UTILS_H__ + +/*****************************************************************************/ + +const char *nm_device_state_to_str(NMDeviceState state); +const char *nm_device_state_reason_to_str(NMDeviceStateReason reason); + +#define nm_device_state_reason_to_str_a(reason) \ + NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_str, reason) + +static inline NMDeviceStateReason +nm_device_state_reason_check(NMDeviceStateReason reason) +{ + /* the device-state-reason serves mostly informational purpose during a state + * change. In some cases however, decisions are made based on the reason. + * I tend to think that interpreting the state reason to derive some behaviors + * is confusing, because the cause and effect are so far apart. + * + * This function is here to mark source that inspects the reason to make + * a decision -- contrary to places that set the reason. Thus, by grepping + * for nm_device_state_reason_check() you can find the "effect" to a certain + * reason. + */ + return reason; +} + +/*****************************************************************************/ + +#define NM_PENDING_ACTION_AUTOACTIVATE "autoactivate" +#define NM_PENDING_ACTION_IN_STATE_CHANGE "in-state-change" +#define NM_PENDING_ACTION_RECHECK_AVAILABLE "recheck-available" +#define NM_PENDING_ACTION_CARRIER_WAIT "carrier-wait" +#define NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT "waiting-for-supplicant" +#define NM_PENDING_ACTION_WIFI_SCAN "wifi-scan" +#define NM_PENDING_ACTION_WAITING_FOR_COMPANION "waiting-for-companion" +#define NM_PENDING_ACTION_LINK_INIT "link-init" + +#define NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "queued-state-change-" +#define NM_PENDING_ACTIONPREFIX_ACTIVATION "activation-" + +const char *nm_device_state_queued_state_to_str(NMDeviceState state); + +/*****************************************************************************/ + +typedef enum { + NM_DEVICE_MTU_SOURCE_NONE, + NM_DEVICE_MTU_SOURCE_PARENT, + NM_DEVICE_MTU_SOURCE_IP_CONFIG, + NM_DEVICE_MTU_SOURCE_CONNECTION, +} NMDeviceMtuSource; + +const char *nm_device_mtu_source_to_str(NMDeviceMtuSource mtu_source); + +/*****************************************************************************/ + +typedef enum _nm_packed { + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_ASSUME, + NM_DEVICE_SYS_IFACE_STATE_MANAGED, + + /* the REMOVED state applies when the device is manually set to unmanaged + * or the link was externally removed. In both cases, we move the device + * to UNMANAGED state, without touching the link -- be it, because the link + * is already gone or because we want to release it (give it up). + */ + NM_DEVICE_SYS_IFACE_STATE_REMOVED, +} NMDeviceSysIfaceState; + +const char *nm_device_sys_iface_state_to_str(NMDeviceSysIfaceState sys_iface_state); + +/*****************************************************************************/ + +typedef enum { + NM_DEVICE_IP_STATE_NONE, + NM_DEVICE_IP_STATE_WAIT, + NM_DEVICE_IP_STATE_CONF, + NM_DEVICE_IP_STATE_DONE, + NM_DEVICE_IP_STATE_FAIL, +} NMDeviceIPState; + +const char *nm_device_ip_state_to_str(NMDeviceIPState ip_state); + +/*****************************************************************************/ + +/*****************************************************************************/ + +void nm_device_resolve_address(int addr_family, + gconstpointer address, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer cb_data); + +char *nm_device_resolve_address_finish(GAsyncResult *result, GError **error); + +#endif /* __DEVICES_NM_DEVICE_UTILS_H__ */ diff --git a/src/core/devices/nm-device-veth.c b/src/core/devices/nm-device-veth.c index e0ba843d..28831b75 100644 --- a/src/core/devices/nm-device-veth.c +++ b/src/core/devices/nm-device-veth.c @@ -7,11 +7,11 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-device-veth.h" #include "nm-device-private.h" #include "nm-manager.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-veth.h" @@ -161,12 +161,8 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) static const NMDBusInterfaceInfoExtended interface_info_device_veth = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_VETH, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Peer", - "o", - NM_DEVICE_VETH_PEER), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Peer", "o", NM_DEVICE_VETH_PEER), ), ), }; static void diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c index bfde60ef..548245f8 100644 --- a/src/core/devices/nm-device-vlan.c +++ b/src/core/devices/nm-device-vlan.c @@ -16,11 +16,12 @@ #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-manager.h" -#include "nm-core-internal.h" -#include "platform/nmp-object.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nm-platform-utils.h" #define _NMLOG_DEVICE_TYPE NMDeviceVlan #include "nm-device-logging.h" @@ -436,7 +437,7 @@ update_connection(NMDevice *device, NMConnection *connection) const NMPlatformLink *plink; const NMPObject * polnk; guint vlan_id; - guint vlan_flags; + _NMVlanFlags vlan_flags; if (!s_vlan) { s_vlan = (NMSettingVlan *) nm_setting_vlan_new(); @@ -463,9 +464,9 @@ update_connection(NMDevice *device, NMConnection *connection) if (polnk) vlan_flags = polnk->lnk_vlan.flags; else - vlan_flags = NM_VLAN_FLAG_REORDER_HEADERS; - if (vlan_flags != nm_setting_vlan_get_flags(s_vlan)) - g_object_set(s_vlan, NM_SETTING_VLAN_FLAGS, (NMVlanFlags) vlan_flags, NULL); + vlan_flags = _NM_VLAN_FLAG_REORDER_HEADERS; + if (NM_VLAN_FLAGS_CAST(vlan_flags) != nm_setting_vlan_get_flags(s_vlan)) + g_object_set(s_vlan, NM_SETTING_VLAN_FLAGS, NM_VLAN_FLAGS_CAST(vlan_flags), NULL); if (polnk) { _nm_setting_vlan_set_priorities(s_vlan, @@ -507,7 +508,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) nm_platform_link_vlan_change(nm_device_get_platform(device), nm_device_get_ifindex(device), - NM_VLAN_FLAGS_ALL, + _NM_VLAN_FLAGS_ALL, nm_setting_vlan_get_flags(s_vlan), TRUE, ingress_map, @@ -546,17 +547,11 @@ nm_device_vlan_init(NMDeviceVlan *self) static const NMDBusInterfaceInfoExtended interface_info_device_vlan = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_VLAN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("VlanId", - "u", - NM_DEVICE_VLAN_ID), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("VlanId", "u", NM_DEVICE_VLAN_ID), ), ), }; static void @@ -674,7 +669,7 @@ get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const c * device, we create one for it using the VLAN ID and the parent * interface's name. */ - return nm_utils_new_vlan_name(parent_iface, nm_setting_vlan_get_id(s_vlan)); + return nmp_utils_new_vlan_name(parent_iface, nm_setting_vlan_get_id(s_vlan)); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index 4fec59ba..2a1f42c6 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -4,12 +4,12 @@ #include "nm-device-vrf.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-device-factory.h" #include "nm-device-private.h" #include "nm-manager.h" #include "nm-setting-vrf.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "settings/nm-settings.h" #define _NMLOG_DEVICE_TYPE NMDeviceVrf diff --git a/src/core/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c index f16a52c4..f9dfad2a 100644 --- a/src/core/devices/nm-device-vxlan.c +++ b/src/core/devices/nm-device-vxlan.c @@ -9,7 +9,7 @@ #include "nm-device-private.h" #include "nm-manager.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-utils.h" #include "nm-device-factory.h" #include "nm-setting-vxlan.h" @@ -17,7 +17,7 @@ #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-ip4-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceVxlan #include "nm-device-logging.h" @@ -576,38 +576,34 @@ nm_device_vxlan_init(NMDeviceVxlan *self) static const NMDBusInterfaceInfoExtended interface_info_device_vxlan = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_VXLAN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Id", "u", NM_DEVICE_VXLAN_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Group", "s", NM_DEVICE_VXLAN_GROUP), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Local", "s", NM_DEVICE_VXLAN_LOCAL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Tos", "y", NM_DEVICE_VXLAN_TOS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ttl", "y", NM_DEVICE_VXLAN_TTL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Learning", - "b", - NM_DEVICE_VXLAN_LEARNING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ageing", "u", NM_DEVICE_VXLAN_AGEING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Limit", "u", NM_DEVICE_VXLAN_LIMIT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DstPort", - "q", - NM_DEVICE_VXLAN_DST_PORT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("SrcPortMin", - "q", - NM_DEVICE_VXLAN_SRC_PORT_MIN), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("SrcPortMax", - "q", - NM_DEVICE_VXLAN_SRC_PORT_MAX), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Proxy", "b", NM_DEVICE_VXLAN_PROXY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Rsc", "b", NM_DEVICE_VXLAN_RSC), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("L2miss", "b", NM_DEVICE_VXLAN_L2MISS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("L3miss", - "b", - NM_DEVICE_VXLAN_L3MISS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Id", "u", NM_DEVICE_VXLAN_ID), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Group", "s", NM_DEVICE_VXLAN_GROUP), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Local", "s", NM_DEVICE_VXLAN_LOCAL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Tos", "y", NM_DEVICE_VXLAN_TOS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ttl", "y", NM_DEVICE_VXLAN_TTL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Learning", + "b", + NM_DEVICE_VXLAN_LEARNING), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ageing", "u", NM_DEVICE_VXLAN_AGEING), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Limit", "u", NM_DEVICE_VXLAN_LIMIT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DstPort", + "q", + NM_DEVICE_VXLAN_DST_PORT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("SrcPortMin", + "q", + NM_DEVICE_VXLAN_SRC_PORT_MIN), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("SrcPortMax", + "q", + NM_DEVICE_VXLAN_SRC_PORT_MAX), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Proxy", "b", NM_DEVICE_VXLAN_PROXY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Rsc", "b", NM_DEVICE_VXLAN_RSC), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("L2miss", "b", NM_DEVICE_VXLAN_L2MISS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("L3miss", + "b", + NM_DEVICE_VXLAN_L3MISS), ), ), }; static void diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index 5bee09e6..aa9c46eb 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -11,12 +11,12 @@ #include #include "nm-setting-wireguard.h" -#include "nm-core-internal.h" -#include "nm-glib-aux/nm-secret-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-secret-utils.h" #include "nm-device-private.h" -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" -#include "platform/nmp-rules-manager.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nmp-rules-manager.h" #include "nm-device-factory.h" #include "nm-active-connection.h" #include "nm-act-request.h" @@ -66,7 +66,7 @@ G_STATIC_ASSERT(NM_WIREGUARD_SYMMETRIC_KEY_LEN == NMP_WIREGUARD_SYMMETRIC_KEY_LE * timestamp. */ #define RETRY_IN_MSEC_ASAP ((gint64) G_MAXINT64) -#define RETRY_IN_MSEC_MAX ((gint64)(30 * 60 * 1000)) +#define RETRY_IN_MSEC_MAX ((gint64) (30 * 60 * 1000)) typedef enum { LINK_CONFIG_MODE_FULL, @@ -669,7 +669,7 @@ _peers_resolve_retry_reschedule(NMDeviceWireGuard *self, gint64 new_next_try_at_ * than expected. Also, rate-limit to 500 msec. */ interval_ms = NM_CLAMP((new_next_try_at_nsec - now) / NM_UTILS_NSEC_PER_MSEC, (gint64) 500, - (gint64)(24 * 60 * 60 * 1000)); + (gint64) (24 * 60 * 60 * 1000)); _LOGT(LOGD_DEVICE, "wireguard-peers: schedule rechecking peer endpoints in %u msec", @@ -1939,11 +1939,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) switch (prop_id) { case PROP_PUBLIC_KEY: - g_value_take_variant(value, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, - priv->lnk_curr.public_key, - sizeof(priv->lnk_curr.public_key), - 1)); + g_value_take_variant( + value, + nm_g_variant_new_ay(priv->lnk_curr.public_key, sizeof(priv->lnk_curr.public_key))); break; case PROP_LISTEN_PORT: g_value_set_uint(value, priv->lnk_curr.listen_port); diff --git a/src/core/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c index 2f3b16ff..73d79410 100644 --- a/src/core/devices/nm-device-wpan.c +++ b/src/core/devices/nm-device-wpan.c @@ -15,10 +15,10 @@ #include "nm-act-request.h" #include "nm-device-private.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-wpan.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceWpan #include "nm-device-logging.h" diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 3874e586..50386d00 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -23,22 +23,23 @@ #include #include -#include "nm-std-aux/unaligned.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-glib-aux/nm-random-utils.h" -#include "systemd/nm-sd-utils-shared.h" - -#include "nm-base/nm-ethtool-base.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-std-aux/unaligned.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-random-utils.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" + +#include "libnm-base/nm-ethtool-base.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-device-private.h" #include "nm-l3cfg.h" #include "nm-l3-config-data.h" #include "NetworkManagerUtils.h" #include "nm-manager.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" -#include "platform/nmp-object.h" -#include "platform/nmp-rules-manager.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nmp-rules-manager.h" #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" #include "dhcp/nm-dhcp-manager.h" @@ -51,7 +52,8 @@ #include "dnsmasq/nm-dnsmasq-manager.h" #include "nm-dhcp-config.h" #include "nm-rfkill-manager.h" -#include "nm-firewall-manager.h" +#include "nm-firewall-utils.h" +#include "nm-firewalld-manager.h" #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" #include "nm-setting-ethtool.h" @@ -65,12 +67,13 @@ #include "c-list/src/c-list.h" #include "dns/nm-dns-manager.h" #include "nm-acd-manager.h" -#include "nm-core-internal.h" -#include "systemd/nm-sd.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-systemd-core/nm-sd.h" #include "nm-lldp-listener.h" #include "nm-audit-manager.h" #include "nm-connectivity.h" #include "nm-dbus-interface.h" +#include "nm-hostname-manager.h" #include "nm-device-generic.h" #include "nm-device-vlan.h" @@ -207,6 +210,7 @@ typedef struct { NMOptionBool requested[_NM_ETHTOOL_ID_FEATURE_NUM]; NMEthtoolCoalesceState *coalesce; NMEthtoolRingState * ring; + NMEthtoolPauseState * pause; } EthtoolState; typedef enum { @@ -217,7 +221,6 @@ typedef enum { typedef struct { ResolverState state; - GResolver * resolver; GInetAddress *address; GCancellable *cancellable; char * hostname; @@ -496,11 +499,18 @@ typedef struct _NMDevicePrivate { NMDeviceStageState stage1_sriov_state : 3; - /* Generic DHCP stuff */ - char *dhcp_anycast_address; + bool ip_config_started : 1; char *current_stable_id; + union { + struct { + GSource *ip_req_timeout_source_6; + GSource *ip_req_timeout_source_4; + }; + GSource *ip_req_timeout_source_x[2]; + }; + /* Proxy Configuration */ NMProxyConfig * proxy_config; NMPacrunnerConfId *pacrunner_conf_id; @@ -592,9 +602,9 @@ typedef struct _NMDevicePrivate { gulong dnsmasq_state_id; /* Firewall */ - FirewallState fw_state : 4; - NMFirewallManager * fw_mgr; - NMFirewallManagerCallId *fw_call; + FirewallState fw_state : 4; + NMFirewalldManager * fw_mgr; + NMFirewalldManagerCallId *fw_call; /* IPv4LL stuff */ sd_ipv4ll *ipv4ll; @@ -693,6 +703,8 @@ typedef struct _NMDevicePrivate { } stats; bool mtu_force_set_done : 1; + + NMOptionBool promisc_reset; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -764,139 +776,7 @@ static void sriov_op_cb(GError *error, gpointer user_data); static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self); static gboolean device_link_changed(NMDevice *self); - -/*****************************************************************************/ - -static NM_UTILS_LOOKUP_STR_DEFINE( - queued_state_to_string, - NMDeviceState, - NM_UTILS_LOOKUP_DEFAULT(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNKNOWN, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNMANAGED, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unmanaged"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNAVAILABLE, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unavailable"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_DISCONNECTED, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "disconnected"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_PREPARE, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "prepare"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_CONFIG, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "config"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_NEED_AUTH, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "need-auth"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_IP_CONFIG, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-config"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_IP_CHECK, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-check"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_SECONDARIES, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "secondaries"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_ACTIVATED, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "activated"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_DEACTIVATING, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "deactivating"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_FAILED, - NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"), ); - -const char * -nm_device_state_to_str(NMDeviceState state) -{ - return queued_state_to_string(state) + NM_STRLEN(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE); -} - -NM_UTILS_LOOKUP_STR_DEFINE( - nm_device_state_reason_to_str, - NMDeviceStateReason, - NM_UTILS_LOOKUP_DEFAULT(NULL), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNKNOWN, "unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NONE, "none"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NOW_MANAGED, "managed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NOW_UNMANAGED, "unmanaged"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONFIG_FAILED, "config-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, "ip-config-unavailable"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, "ip-config-expired"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NO_SECRETS, "no-secrets"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, "supplicant-disconnect"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED, - "supplicant-config-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, "supplicant-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, "supplicant-timeout"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_START_FAILED, "ppp-start-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_DISCONNECT, "ppp-disconnect"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PPP_FAILED, "ppp-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_START_FAILED, "dhcp-start-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_ERROR, "dhcp-error"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DHCP_FAILED, "dhcp-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SHARED_START_FAILED, "sharing-start-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SHARED_FAILED, "sharing-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, "autoip-start-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_ERROR, "autoip-error"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_FAILED, "autoip-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_BUSY, "modem-busy"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, "modem-no-dialtone"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, "modem-no-carrier"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, "modem-dial-timeout"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, "modem-dial-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, "modem-init-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_APN_FAILED, "gsm-apn-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, - "gsm-registration-idle"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED, - "gsm-registration-denied"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT, - "gsm-registration-timeout"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, - "gsm-registration-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, "gsm-pin-check-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, "firmware-missing"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_REMOVED, "removed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SLEEPING, "sleeping"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, "connection-removed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_USER_REQUESTED, "user-requested"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CARRIER, "carrier-changed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, "connection-assumed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, "supplicant-available"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, "modem-not-found"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_BT_FAILED, "bluetooth-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, "gsm-sim-not-inserted"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, "gsm-sim-pin-required"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, "gsm-sim-puk-required"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, "gsm-sim-wrong"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_INFINIBAND_MODE, "infiniband-mode"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, "dependency-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_BR2684_FAILED, "br2684-bridge-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE, - "modem-manager-unavailable"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, "ssid-not-found"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED, - "secondary-connection-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, "dcb-fcoe-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, "teamd-control-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_FAILED, "modem-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, "modem-available"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, "sim-pin-incorrect"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NEW_ACTIVATION, "new-activation"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PARENT_CHANGED, "parent-changed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, - "parent-managed-changed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_OVSDB_FAILED, "ovsdb-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, - "sriov-configuration-failed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), ); - -#define reason_to_string_a(reason) NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_str, reason) - -static NM_UTILS_LOOKUP_STR_DEFINE(mtu_source_to_str, - NMDeviceMtuSource, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_NONE, "none"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_PARENT, "parent"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_IP_CONFIG, - "ip-config"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_CONNECTION, - "connection"), ); +static void check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update); /*****************************************************************************/ @@ -908,7 +788,6 @@ _hostname_resolver_free(HostnameResolver *resolver) nm_clear_g_source(&resolver->timeout_id); nm_clear_g_cancellable(&resolver->cancellable); - nm_g_object_unref(resolver->resolver); nm_g_object_unref(resolver->address); g_free(resolver->hostname); nm_g_slice_free(resolver); @@ -952,8 +831,7 @@ _prop_get_connection_stable_id(NMDevice * self, * Especially with ${RANDOM} stable-id we want to generate *one* configuration * for each activation. */ if (G_UNLIKELY(!priv->current_stable_id)) { - gs_free char * default_id = NULL; - gs_free char * generated = NULL; + gs_free char * generated = NULL; NMUtilsStableType stable_type; NMSettingConnection *s_con; gboolean hwaddr_is_fake; @@ -966,11 +844,10 @@ _prop_get_connection_stable_id(NMDevice * self, stable_id = nm_setting_connection_get_stable_id(s_con); if (!stable_id) { - default_id = + stable_id = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA, NM_CON_DEFAULT("connection.stable-id"), self); - stable_id = default_id; } uuid = nm_connection_get_uuid(connection); @@ -1029,7 +906,6 @@ _prop_get_ipv6_dhcp_duid(NMDevice * self, { NMSettingIPConfig *s_ip6; const char * duid; - gs_free char * duid_default = NULL; const char * duid_error; GBytes * duid_out; gboolean duid_enforce = TRUE; @@ -1042,10 +918,9 @@ _prop_get_ipv6_dhcp_duid(NMDevice * self, duid = nm_setting_ip6_config_get_dhcp_duid(NM_SETTING_IP6_CONFIG(s_ip6)); if (!duid) { - duid_default = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA, - NM_CON_DEFAULT("ipv6.dhcp-duid"), - self); - duid = duid_default; + duid = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv6.dhcp-duid"), + self); if (!duid) duid = "lease"; } @@ -1396,7 +1271,7 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family) _LOGT(LOGD_DEVICE, "ipv%c.route-table = %u%s", nm_utils_addr_family_to_char(addr_family), - (guint)(route_table ?: RT_TABLE_MAIN), + (guint) (route_table ?: RT_TABLE_MAIN), route_table != 0u ? "" : " (policy routing not enabled)"); return route_table; @@ -1500,6 +1375,40 @@ out: return timeout; } +static guint32 +_prop_get_ipvx_required_timeout(NMDevice *self, int addr_family) +{ + NMConnection * connection; + NMSettingIPConfig *s_ip; + int timeout; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert_addr_family(addr_family); + + connection = nm_device_get_applied_connection(self); + if (!connection) + return 0; + + s_ip = nm_connection_get_setting_ip_config(connection, addr_family); + if (!s_ip) + return 0; + + timeout = nm_setting_ip_config_get_required_timeout(s_ip); + nm_assert(timeout >= -1); + + if (timeout > -1) + return (guint32) timeout; + + return nm_config_data_get_connection_default_int64( + NM_CONFIG_GET_DATA, + NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.required-timeout") + : NM_CON_DEFAULT("ipv6.required-timeout"), + self, + 0, + G_MAXINT32, + 0); +} + /** * _prop_get_ipvx_dhcp_iaid: * @self: the #NMDevice @@ -1522,7 +1431,6 @@ _prop_get_ipvx_dhcp_iaid(NMDevice * self, const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; const char * iaid_str; - gs_free char * iaid_str_free = NULL; guint32 iaid; const char * iface; const char * fail_reason; @@ -1531,11 +1439,10 @@ _prop_get_ipvx_dhcp_iaid(NMDevice * self, s_ip = nm_connection_get_setting_ip_config(connection, addr_family); iaid_str = nm_setting_ip_config_get_dhcp_iaid(s_ip); if (!iaid_str) { - iaid_str_free = nm_config_data_get_connection_default( - NM_CONFIG_GET_DATA, - IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-iaid") : NM_CON_DEFAULT("ipv6.dhcp-iaid"), - self); - iaid_str = iaid_str_free; + iaid_str = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA, + IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-iaid") + : NM_CON_DEFAULT("ipv6.dhcp-iaid"), + self); if (!iaid_str) { iaid_str = NM_IAID_IFNAME; is_explicit = FALSE; @@ -1566,7 +1473,7 @@ _prop_get_ipvx_dhcp_iaid(NMDevice * self, iaid = unaligned_read_be32(&pllink->l_address.data[pllink->l_address.len - 4]); goto out_good; } else if (nm_streq0(iaid_str, NM_IAID_PERM_MAC)) { - guint8 hwaddr_buf[NM_UTILS_HWADDR_LEN_MAX]; + guint8 hwaddr_buf[_NM_UTILS_HWADDR_LEN_MAX]; const char *hwaddr_str; gsize hwaddr_len; @@ -1692,12 +1599,10 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family) } static const char * -_prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con, char **out_mud_url) +_prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con) { - const char * mud_url; - gs_free char *s = NULL; - - nm_assert(out_mud_url && !*out_mud_url); + const char *mud_url; + const char *s; mud_url = nm_setting_connection_get_mud_url(s_con); @@ -1714,7 +1619,7 @@ _prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con, char ** if (nm_streq(s, NM_CONNECTION_MUD_URL_NONE)) return NULL; if (nm_sd_http_url_is_valid_https(s)) - return (*out_mud_url = g_steal_pointer(&s)); + return s; } return NULL; @@ -1725,10 +1630,9 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * { NMSettingIPConfig *s_ip4; const char * client_id; - gs_free char * client_id_default = NULL; guint8 * client_id_buf; const char * fail_reason; - guint8 hwaddr_bin_buf[NM_UTILS_HWADDR_LEN_MAX]; + guint8 hwaddr_bin_buf[_NM_UTILS_HWADDR_LEN_MAX]; const guint8 * hwaddr_bin; int arp_type; gsize hwaddr_len; @@ -1739,13 +1643,12 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * client_id = nm_setting_ip4_config_get_dhcp_client_id(NM_SETTING_IP4_CONFIG(s_ip4)); if (!client_id) { - client_id_default = - nm_config_data_get_connection_default(NM_CONFIG_GET_DATA, - NM_CON_DEFAULT("ipv4.dhcp-client-id"), - self); - if (client_id_default && client_id_default[0]) { + client_id = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv4.dhcp-client-id"), + self); + if (client_id && !client_id[0]) { /* a non-empty client-id is always valid, see nm_dhcp_utils_client_id_string_to_bytes(). */ - client_id = client_id_default; + client_id = NULL; } } @@ -1877,8 +1780,7 @@ out_good: static GBytes * _prop_get_ipv4_dhcp_vendor_class_identifier(NMDevice *self, NMSettingIP4Config *s_ip4) { - gs_free char *config_data_prop = NULL; - gs_free char *to_free = NULL; + gs_free char *to_free = NULL; const char * conn_prop; GBytes * bytes = NULL; const char * bin; @@ -1888,13 +1790,13 @@ _prop_get_ipv4_dhcp_vendor_class_identifier(NMDevice *self, NMSettingIP4Config * if (!conn_prop) { /* set in NetworkManager.conf ? */ - config_data_prop = nm_config_data_get_connection_default( + conn_prop = nm_config_data_get_connection_default( NM_CONFIG_GET_DATA, NM_CON_DEFAULT("ipv4.dhcp-vendor-class-identifier"), self); - if (config_data_prop && nm_utils_validate_dhcp4_vendor_class_id(config_data_prop, NULL)) - conn_prop = config_data_prop; + if (conn_prop && !nm_utils_validate_dhcp4_vendor_class_id(conn_prop, NULL)) + conn_prop = NULL; } if (conn_prop) { @@ -1960,16 +1862,11 @@ _prop_get_ipv6_ip6_privacy(NMDevice *self) } static const char * -_prop_get_x_cloned_mac_address(NMDevice * self, - NMConnection *connection, - gboolean is_wifi, - char ** out_addr) +_prop_get_x_cloned_mac_address(NMDevice *self, NMConnection *connection, gboolean is_wifi) { NMSetting * setting; const char *addr = NULL; - nm_assert(out_addr && !*out_addr); - setting = nm_connection_get_setting(connection, is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED); if (setting) { @@ -1978,7 +1875,7 @@ _prop_get_x_cloned_mac_address(NMDevice * self, } if (!addr) { - gs_free char *a = NULL; + const char *a; a = nm_config_data_get_connection_default( NM_CONFIG_GET_DATA, @@ -1993,36 +1890,28 @@ _prop_get_x_cloned_mac_address(NMDevice * self, NMSettingMacRandomization v; /* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */ - a = nm_config_data_get_connection_default( + v = nm_config_data_get_connection_default_int64( NM_CONFIG_GET_DATA, NM_CON_DEFAULT("wifi.mac-address-randomization"), - self); - v = _nm_utils_ascii_str_to_int64(a, - 10, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, - NM_SETTING_MAC_RANDOMIZATION_ALWAYS, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT); + self, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT); if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS) addr = NM_CLONED_MAC_RANDOM; } } else if (NM_CLONED_MAC_IS_SPECIAL(a) || nm_utils_hwaddr_valid(a, ETH_ALEN)) - addr = *out_addr = g_steal_pointer(&a); + addr = a; } return addr; } static const char * -_prop_get_x_generate_mac_address_mask(NMDevice * self, - NMConnection *connection, - gboolean is_wifi, - char ** out_value) +_prop_get_x_generate_mac_address_mask(NMDevice *self, NMConnection *connection, gboolean is_wifi) { NMSetting * setting; - const char *value = NULL; - char * a; - - nm_assert(out_value && !*out_value); + const char *value; setting = nm_connection_get_setting(connection, is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED); @@ -2035,15 +1924,11 @@ _prop_get_x_generate_mac_address_mask(NMDevice * self, return value; } - a = nm_config_data_get_connection_default( + return nm_config_data_get_connection_default( NM_CONFIG_GET_DATA, is_wifi ? NM_CON_DEFAULT("wifi.generate-mac-address-mask") : NM_CON_DEFAULT("ethernet.generate-mac-address-mask"), self); - if (!a) - return NULL; - *out_value = a; - return a; } /*****************************************************************************/ @@ -2271,6 +2156,113 @@ _ethtool_ring_set(NMDevice * self, _LOGD(LOGD_DEVICE, "ethtool: ring settings successfully set"); } +static void +_ethtool_pause_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state) +{ + gs_free NMEthtoolPauseState *pause = NULL; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert(NM_IS_PLATFORM(platform)); + nm_assert(ethtool_state); + + pause = g_steal_pointer(ðtool_state->pause); + if (!pause) + return; + + if (!nm_platform_ethtool_set_pause(platform, ethtool_state->ifindex, pause)) + _LOGW(LOGD_DEVICE, "ethtool: failure resetting one or more pause settings"); + else + _LOGD(LOGD_DEVICE, "ethtool: pause settings successfully reset"); +} + +static void +_ethtool_pause_set(NMDevice * self, + NMPlatform * platform, + EthtoolState * ethtool_state, + NMSettingEthtool *s_ethtool) +{ + NMEthtoolPauseState pause_old; + NMEthtoolPauseState pause_new; + GHashTable * hash; + GHashTableIter iter; + const char * name; + GVariant * variant; + gboolean has_old = FALSE; + NMTernary pause_autoneg = NM_TERNARY_DEFAULT; + NMTernary pause_rx = NM_TERNARY_DEFAULT; + NMTernary pause_tx = NM_TERNARY_DEFAULT; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert(NM_IS_PLATFORM(platform)); + nm_assert(NM_IS_SETTING_ETHTOOL(s_ethtool)); + nm_assert(ethtool_state); + nm_assert(!ethtool_state->pause); + + hash = _nm_setting_option_hash(NM_SETTING(s_ethtool), FALSE); + if (!hash) + return; + + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { + NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name); + + if (!nm_ethtool_id_is_pause(ethtool_id)) + continue; + + nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); + + if (!has_old) { + if (!nm_platform_ethtool_get_link_pause(platform, ethtool_state->ifindex, &pause_old)) { + _LOGW(LOGD_DEVICE, + "ethtool: failure setting pause options (cannot read " + "existing setting)"); + return; + } + has_old = TRUE; + } + + switch (ethtool_id) { + case NM_ETHTOOL_ID_PAUSE_AUTONEG: + pause_autoneg = g_variant_get_boolean(variant); + break; + case NM_ETHTOOL_ID_PAUSE_RX: + pause_rx = g_variant_get_boolean(variant); + break; + case NM_ETHTOOL_ID_PAUSE_TX: + pause_tx = g_variant_get_boolean(variant); + break; + default: + nm_assert_not_reached(); + } + } + + if (!has_old) + return; + + if (pause_rx != NM_TERNARY_DEFAULT || pause_tx != NM_TERNARY_DEFAULT) { + /* this implies to explicitly disable autoneg. */ + nm_assert(pause_autoneg != NM_TERNARY_TRUE); + pause_autoneg = NM_TERNARY_FALSE; + } + + pause_new = pause_old; + if (pause_autoneg != NM_TERNARY_DEFAULT) + pause_new.autoneg = !!pause_autoneg; + if (pause_rx != NM_TERNARY_DEFAULT) + pause_new.rx = !!pause_rx; + if (pause_tx != NM_TERNARY_DEFAULT) + pause_new.tx = !!pause_tx; + + ethtool_state->pause = nm_memdup(&pause_old, sizeof(pause_old)); + + if (!nm_platform_ethtool_set_pause(platform, ethtool_state->ifindex, &pause_new)) { + _LOGW(LOGD_DEVICE, "ethtool: failure setting pause settings"); + return; + } + + _LOGD(LOGD_DEVICE, "ethtool: pause settings successfully set"); +} + static void _ethtool_state_reset(NMDevice *self) { @@ -2287,6 +2279,8 @@ _ethtool_state_reset(NMDevice *self) _ethtool_coalesce_reset(self, platform, ethtool_state); if (ethtool_state->ring) _ethtool_ring_reset(self, platform, ethtool_state); + if (ethtool_state->pause) + _ethtool_pause_reset(self, platform, ethtool_state); } static void @@ -2320,8 +2314,10 @@ _ethtool_state_set(NMDevice *self) _ethtool_features_set(self, platform, ethtool_state, s_ethtool); _ethtool_coalesce_set(self, platform, ethtool_state, s_ethtool); _ethtool_ring_set(self, platform, ethtool_state, s_ethtool); + _ethtool_pause_set(self, platform, ethtool_state, s_ethtool); - if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring) + if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring + || ethtool_state->pause) priv->ethtool_state = g_steal_pointer(ðtool_state); } @@ -2520,15 +2516,6 @@ applied_config_reset_nameservers(AppliedConfig *config) /*****************************************************************************/ -static NM_UTILS_LOOKUP_STR_DEFINE( - _sys_iface_state_to_str, - NMDeviceSysIfaceState, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_ASSUME, "assume"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_MANAGED, "managed"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_REMOVED, "removed"), ); - NMDeviceSysIfaceState nm_device_sys_iface_state_get(NMDevice *self) { @@ -2567,8 +2554,8 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st if (priv->sys_iface_state != sys_iface_state) { _LOGT(LOGD_DEVICE, "sys-iface-state: %s -> %s", - _sys_iface_state_to_str(priv->sys_iface_state), - _sys_iface_state_to_str(sys_iface_state)); + nm_device_sys_iface_state_to_str(priv->sys_iface_state), + nm_device_sys_iface_state_to_str(sys_iface_state)); priv->sys_iface_state_ = sys_iface_state; } @@ -2599,6 +2586,42 @@ _active_connection_set_state_flags(NMDevice *self, NMActivationStateFlags flags) /*****************************************************************************/ +static gboolean +set_interface_flags_full(NMDevice * self, + NMDeviceInterfaceFlags mask, + NMDeviceInterfaceFlags interface_flags, + gboolean notify) +{ + NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDeviceInterfaceFlags f; + + nm_assert(!!mask); + nm_assert(!NM_FLAGS_ANY(mask, ~_NM_DEVICE_INTERFACE_FLAG_ALL)); + nm_assert(!NM_FLAGS_ANY(interface_flags, ~mask)); + + f = (priv->interface_flags & ~mask) | (interface_flags & mask); + + if (f == priv->interface_flags) + return FALSE; + + priv->interface_flags = f; + if (notify) + _notify(self, PROP_INTERFACE_FLAGS); + return TRUE; +} + +static gboolean +set_interface_flags(NMDevice * self, + NMDeviceInterfaceFlags interface_flags, + gboolean set, + gboolean notify) +{ + return set_interface_flags_full(self, + interface_flags, + set ? interface_flags : NM_DEVICE_INTERFACE_FLAG_NONE, + notify); +} + void nm_device_assume_state_get(NMDevice * self, gboolean * out_assume_state_guess_assume, @@ -2809,23 +2832,72 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities) /*****************************************************************************/ -static NM_UTILS_LOOKUP_STR_DEFINE(_ip_state_to_string, - NMDeviceIPState, - NM_UTILS_LOOKUP_DEFAULT_WARN("unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_NONE, "none"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_WAIT, "wait"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_CONF, "conf"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_DONE, "done"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAIL, "fail"), ); +static gboolean +ip_required_timeout_x(NMDevice *self, int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + _LOGD(LOGD_CORE, + "required-timeout expired for IPv%c", + nm_utils_addr_family_to_char(addr_family)); + nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[NM_IS_IPv4(addr_family)]); + check_ip_state(self, FALSE, TRUE); + return G_SOURCE_CONTINUE; +} + +static gboolean +ip_required_timeout_4(gpointer data) +{ + return ip_required_timeout_x(data, AF_INET); +} + +static gboolean +ip_required_timeout_6(gpointer data) +{ + return ip_required_timeout_x(data, AF_INET6); +} static void _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const int IS_IPv4 = NM_IS_IPv4(addr_family); + guint timeout_msec; + int v4; nm_assert_addr_family(addr_family); + if (new_state == NM_DEVICE_IP_STATE_CONF && !priv->ip_config_started) { + /* Start the required-timeout timers when one of IPv4/IPv6 + * enters the CONF state. This means that if there is no carrier and + * ipv4.method=auto,ipv6.method=manual, the timeout for IPv4 will + * start as soon as connection is activated, even if DHCPv4 did not + * start yet. + */ + priv->ip_config_started = TRUE; + + for (v4 = 1; v4 >= 0; v4--) { + char buf[32]; + + nm_assert(!priv->ip_req_timeout_source_x[v4]); + if ((timeout_msec = _prop_get_ipvx_required_timeout(self, v4 ? AF_INET : AF_INET6))) { + _LOGD(LOGD_CORE, + "required-timeout in %s msec for IPv%c", + timeout_msec == G_MAXINT32 ? "∞" : nm_sprintf_buf(buf, "%u", timeout_msec), + v4 ? '4' : '6'); + + if (timeout_msec == G_MAXINT32) { + priv->ip_req_timeout_source_x[v4] = g_source_ref(nm_g_source_sentinel_get(0)); + } else { + priv->ip_req_timeout_source_x[v4] = + nm_g_timeout_add_source(timeout_msec, + v4 ? ip_required_timeout_4 : ip_required_timeout_6, + self); + } + } + } + } + if (priv->ip_state_x[IS_IPv4] == new_state) return; @@ -2833,7 +2905,7 @@ _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) "ip%c-state: set to %d (%s)", nm_utils_addr_family_to_char(addr_family), (int) new_state, - _ip_state_to_string(new_state)); + nm_device_ip_state_to_str(new_state)); priv->ip_state_x_[IS_IPv4] = new_state; @@ -2942,10 +3014,10 @@ nm_device_take_over_link(NMDevice *self, int ifindex, char **old_name, GError ** /* Rename the link to the device ifname */ if (up) - nm_platform_link_set_down(platform, ifindex); + nm_platform_link_change_flags(platform, ifindex, IFF_UP, FALSE); success = nm_platform_link_set_name(platform, ifindex, nm_device_get_iface(self)); if (up) - nm_platform_link_set_up(platform, ifindex, NULL); + nm_platform_link_change_flags(platform, ifindex, IFF_UP, TRUE); if (!success) { nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "failure renaming link %d", ifindex); @@ -3073,7 +3145,7 @@ _set_ip_ifindex(NMDevice *self, int ifindex, const char *ifname) nm_platform_link_set_user_ipv6ll_enabled(platform, priv->ip_ifindex, TRUE); if (!nm_platform_link_is_up(platform, priv->ip_ifindex)) - nm_platform_link_set_up(platform, priv->ip_ifindex, NULL); + nm_platform_link_change_flags(platform, priv->ip_ifindex, IFF_UP, TRUE); } /* We don't care about any saved values from the old iface */ @@ -4865,7 +4937,6 @@ void nm_device_update_dynamic_ip_setup(NMDevice *self) { NMDevicePrivate *priv; - GError * error = NULL; g_return_if_fail(NM_IS_DEVICE(self)); @@ -4898,17 +4969,6 @@ nm_device_update_dynamic_ip_setup(NMDevice *self) if (priv->dnsmasq_manager) { /* FIXME: todo */ } - - if (priv->lldp_listener && nm_lldp_listener_is_running(priv->lldp_listener)) { - nm_lldp_listener_stop(priv->lldp_listener); - if (!nm_lldp_listener_start(priv->lldp_listener, nm_device_get_ifindex(self), &error)) { - _LOGD(LOGD_DEVICE, - "LLDP listener %p could not be restarted: %s", - priv->lldp_listener, - error->message); - g_clear_error(&error); - } - } } /*****************************************************************************/ @@ -5025,18 +5085,12 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier) if (NM_FLAGS_ALL(priv->capabilities, NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) { - if (carrier) - priv->interface_flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER; - else - priv->interface_flags &= ~NM_DEVICE_INTERFACE_FLAG_CARRIER; - notify_flags = TRUE; + notify_flags = set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_CARRIER, carrier, FALSE); } priv->carrier = carrier; - if (notify_flags) - nm_gobject_notify_together(self, PROP_CARRIER, PROP_INTERFACE_FLAGS); - else - _notify(self, PROP_CARRIER); + + nm_gobject_notify_together(self, PROP_CARRIER, notify_flags ? PROP_INTERFACE_FLAGS : PROP_0); if (priv->carrier) { _LOGI(LOGD_DEVICE, "carrier: link connected"); @@ -5215,11 +5269,11 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self) if (addr->plen != 64) continue; - lifetime = nm_utils_lifetime_get(addr->timestamp, - addr->lifetime, - addr->preferred, - NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000, - &preferred); + lifetime = nmp_utils_lifetime_get(addr->timestamp, + addr->lifetime, + addr->preferred, + NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000, + &preferred); if (!lifetime) continue; @@ -5271,6 +5325,8 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink) flags |= NM_DEVICE_INTERFACE_FLAG_UP; if (plink && NM_FLAGS_HAS(plink->n_ifi_flags, IFF_LOWER_UP)) flags |= NM_DEVICE_INTERFACE_FLAG_LOWER_UP; + if (plink && NM_FLAGS_HAS(plink->n_ifi_flags, IFF_PROMISC)) + flags |= NM_DEVICE_INTERFACE_FLAG_PROMISC; if (NM_FLAGS_ALL(priv->capabilities, NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) { @@ -5281,10 +5337,12 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink) flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER; } - if (flags != priv->interface_flags) { - priv->interface_flags = flags; - _notify(self, PROP_INTERFACE_FLAGS); - } + set_interface_flags_full(self, + NM_DEVICE_INTERFACE_FLAG_UP | NM_DEVICE_INTERFACE_FLAG_LOWER_UP + | NM_DEVICE_INTERFACE_FLAG_CARRIER + | NM_DEVICE_INTERFACE_FLAG_PROMISC, + flags, + TRUE); } static gboolean @@ -5891,16 +5949,19 @@ sriov_op_queue(NMDevice * self, static void device_init_static_sriov_num_vfs(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gs_free char * value = NULL; - int num_vfs; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); if (priv->ifindex > 0 && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) { - value = nm_config_data_get_device_config(NM_CONFIG_GET_DATA, - NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS, - self, - NULL); - num_vfs = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT32, -1); + int num_vfs; + + num_vfs = nm_config_data_get_device_config_int64(NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS, + self, + 10, + 0, + G_MAXINT32, + -1, + -1); if (num_vfs >= 0) sriov_op_queue(self, num_vfs, NM_OPTION_BOOL_DEFAULT, NULL, NULL); } @@ -6618,6 +6679,7 @@ check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update) gboolean ip4_disabled = FALSE, ip6_disabled = FALSE; NMSettingIPConfig *s_ip4, *s_ip6; NMDeviceState state; + int IS_IPv4; if (full_state_update && nm_device_get_state(self) != NM_DEVICE_STATE_IP_CONFIG) return; @@ -6647,6 +6709,13 @@ check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update) return; } + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_CONF + && priv->ip_req_timeout_source_x[IS_IPv4]) { + return; + } + } + if ((priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL || (ip4_disabled && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE)) && (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL @@ -7170,6 +7239,16 @@ _get_maybe_ipv6_disabled(NMDevice *self) return (nm_platform_sysctl_get_int32(platform, NMP_SYSCTL_PATHID_ABSOLUTE(path), 0) == 0); } +/* + * nm_device_generate_connection: + * + * Generates a connection from an existing interface. + * + * If the device doesn't have an IP configuration and it's not a port or a + * controller, then no connection gets generated and the function returns + * %NULL. In such case, @maybe_later is set to %TRUE if a connection can be + * generated later when an IP address is assigned to the interface. + */ NMConnection * nm_device_generate_connection(NMDevice *self, NMDevice *master, @@ -7214,7 +7293,7 @@ nm_device_generate_connection(NMDevice *self, g_object_set(s_con, NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_buf(uuid), + nm_uuid_generate_random_str_arr(uuid), NM_SETTING_CONNECTION_ID, ifname, NM_SETTING_CONNECTION_AUTOCONNECT, @@ -7426,6 +7505,8 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e gs_free char * conn_iface = NULL; NMDeviceClass * klass; NMSettingMatch * s_match; + const GSList * specs; + gboolean has_match = FALSE; klass = NM_DEVICE_GET_CLASS(self); if (klass->connection_type_check_compatible) { @@ -7466,11 +7547,10 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e s_match = (NMSettingMatch *) nm_connection_get_setting(connection, NM_TYPE_SETTING_MATCH); if (s_match) { const char *const *patterns; - const char * device_driver; guint num_patterns = 0; patterns = nm_setting_match_get_interface_names(s_match, &num_patterns); - if (!nm_wildcard_match_check(device_iface, patterns, num_patterns)) { + if (num_patterns > 0 && !nm_wildcard_match_check(device_iface, patterns, num_patterns)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "device does not satisfy match.interface-name property"); @@ -7485,9 +7565,9 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e error)) return FALSE; - device_driver = nm_device_get_driver(self); - patterns = nm_setting_match_get_drivers(s_match, &num_patterns); - if (!nm_wildcard_match_check(device_driver, patterns, num_patterns)) { + patterns = nm_setting_match_get_drivers(s_match, &num_patterns); + if (num_patterns > 0 + && !nm_wildcard_match_check(nm_device_get_driver(self), patterns, num_patterns)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "device does not satisfy match.driver property"); @@ -7495,7 +7575,7 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e } patterns = nm_setting_match_get_paths(s_match, &num_patterns); - if (!nm_wildcard_match_check(priv->path, patterns, num_patterns)) { + if (num_patterns > 0 && !nm_wildcard_match_check(priv->path, patterns, num_patterns)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "device does not satisfy match.path property"); @@ -7503,6 +7583,15 @@ check_connection_compatible(NMDevice *self, NMConnection *connection, GError **e } } + specs = + nm_config_data_get_device_allowed_connections_specs(NM_CONFIG_GET_DATA, self, &has_match); + if (has_match && !nm_utils_connection_match_spec_list(connection, specs, FALSE)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_DISALLOWED, + "device configuration doesn't allow this connection"); + return FALSE; + } + return TRUE; } @@ -7569,7 +7658,7 @@ nm_device_check_slave_connection_compatible(NMDevice *self, NMConnection *slave) * * Returns: %TRUE if the device is capable of assuming connections, %FALSE if not */ -static gboolean +gboolean nm_device_can_assume_connections(NMDevice *self) { return !!NM_DEVICE_GET_CLASS(self)->update_connection; @@ -7924,14 +8013,6 @@ master_ready_cb(NMActiveConnection *active, GParamSpec *pspec, NMDevice *self) nm_device_activate_schedule_stage1_device_prepare(self, FALSE); } -static void -lldp_neighbors_changed(NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) -{ - NMDevice *self = NM_DEVICE(user_data); - - _notify(self, PROP_LLDP_NEIGHBORS); -} - static NMPlatformVF * sriov_vf_config_to_platform(NMDevice *self, NMSriovVF *vf, GError **error) { @@ -8219,38 +8300,56 @@ act_stage2_config(NMDevice *self, NMDeviceStateReason *out_failure_reason) } static void -lldp_init(NMDevice *self, gboolean restart) +_lldp_neighbors_changed_cb(NMLldpListener *lldp_listener, gpointer user_data) +{ + _notify(user_data, PROP_LLDP_NEIGHBORS); +} + +static void +lldp_setup(NMDevice *self, NMTernary enabled) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int ifindex; + gboolean notify_lldp_neighbors = FALSE; + gboolean notify_interface_flags = FALSE; - if (priv->ifindex > 0 && _prop_get_connection_lldp(self)) { - gs_free_error GError *error = NULL; + ifindex = nm_device_get_ifindex(self); - if (priv->lldp_listener) { - if (restart && nm_lldp_listener_is_running(priv->lldp_listener)) - nm_lldp_listener_stop(priv->lldp_listener); - } else { - priv->lldp_listener = nm_lldp_listener_new(); - g_signal_connect(priv->lldp_listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - G_CALLBACK(lldp_neighbors_changed), - self); - } + if (ifindex <= 0) + enabled = FALSE; + else if (enabled == NM_TERNARY_DEFAULT) + enabled = _prop_get_connection_lldp(self); - if (!nm_lldp_listener_is_running(priv->lldp_listener)) { - if (nm_lldp_listener_start(priv->lldp_listener, nm_device_get_ifindex(self), &error)) - _LOGD(LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); - else { - _LOGD(LOGD_DEVICE, - "LLDP listener %p could not be started: %s", - priv->lldp_listener, - error->message); - } + if (priv->lldp_listener) { + if (!enabled || nm_lldp_listener_get_ifindex(priv->lldp_listener) != ifindex) { + nm_clear_pointer(&priv->lldp_listener, nm_lldp_listener_destroy); + notify_lldp_neighbors = TRUE; } - } else { - if (priv->lldp_listener) - nm_lldp_listener_stop(priv->lldp_listener); } + + if (enabled && !priv->lldp_listener) { + gs_free_error GError *error = NULL; + + priv->lldp_listener = + nm_lldp_listener_new(ifindex, _lldp_neighbors_changed_cb, self, &error); + if (!priv->lldp_listener) { + /* This really shouldn't happen. It's likely a bug. Investigate when this happens! */ + _LOGW(LOGD_DEVICE, + "LLDP listener for ifindex %d could not be started: %s", + ifindex, + error->message); + } else + notify_lldp_neighbors = TRUE; + } + + notify_interface_flags = set_interface_flags(self, + NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, + !!priv->lldp_listener, + FALSE); + + nm_gobject_notify_together(self, + notify_lldp_neighbors ? PROP_LLDP_NEIGHBORS : PROP_0, + notify_interface_flags ? PROP_INTERFACE_FLAGS : PROP_0); } /* set-mode can be: @@ -8401,8 +8500,10 @@ activate_stage2_device_config(NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceClass * klass; NMActStageReturn ret; + NMSettingWired * s_wired; gboolean no_firmware = FALSE; CList * iter; + NMTernary accept_all_mac_addresses; nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); @@ -8460,7 +8561,30 @@ activate_stage2_device_config(NMDevice *self) nm_device_queue_recheck_assume(info->slave); } - lldp_init(self, TRUE); + s_wired = nm_device_get_applied_setting(self, NM_TYPE_SETTING_WIRED); + accept_all_mac_addresses = + s_wired ? nm_setting_wired_get_accept_all_mac_addresses(s_wired) : NM_TERNARY_DEFAULT; + if (accept_all_mac_addresses != NM_TERNARY_DEFAULT) { + int ifindex = nm_device_get_ip_ifindex(self); + + if (ifindex > 0) { + int ifi_flags = + nm_platform_link_get_ifi_flags(nm_device_get_platform(self), ifindex, IFF_PROMISC); + + if (ifi_flags >= 0 && ((!!ifi_flags) != (!!accept_all_mac_addresses))) { + nm_platform_link_change_flags(nm_device_get_platform(self), + ifindex, + IFF_PROMISC, + !!accept_all_mac_addresses); + if (priv->promisc_reset == NM_OPTION_BOOL_DEFAULT) + priv->promisc_reset = !accept_all_mac_addresses; + } + } + } + + lldp_setup(self, NM_TERNARY_DEFAULT); + + _commit_mtu(self, NULL); nm_device_activate_schedule_stage3_ip_config_start(self); } @@ -8877,6 +9001,21 @@ ensure_con_ip_config(NMDevice *self, int addr_family) /*****************************************************************************/ +static const char * +_device_get_dhcp_anycast_address(NMDevice *self) +{ + NMDeviceClass *klass; + + nm_assert(NM_IS_DEVICE(self)); + + klass = NM_DEVICE_GET_CLASS(self); + + if (klass->get_dhcp_anycast_address) + return klass->get_dhcp_anycast_address(self); + + return NULL; +} + static void dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) { @@ -9234,7 +9373,7 @@ dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state) _LOGD(LOGD_DHCP4, "DHCPv4 failed (ip_state %s, was_active %d)", - _ip_state_to_string(priv->ip_state_4), + nm_device_ip_state_to_str(priv->ip_state_4), priv->dhcp_data_4.was_active); /* The client is always left running after a failure. */ @@ -9382,12 +9521,13 @@ dhcp4_start(NMDevice *self) gs_unref_bytes GBytes *hwaddr = NULL; gs_unref_bytes GBytes *bcast_hwaddr = NULL; gs_unref_bytes GBytes *client_id = NULL; - gs_free char * mud_url_free = NULL; NMConnection * connection; NMSettingConnection * s_con; GError * error = NULL; const NMPlatformLink * pllink; const char *const * reject_servers; + gboolean request_broadcast; + const char * str; connection = nm_device_get_applied_connection(self); g_return_val_if_fail(connection, FALSE); @@ -9401,10 +9541,22 @@ dhcp4_start(NMDevice *self) nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config); priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET); + request_broadcast = FALSE; + pllink = nm_platform_link_get(nm_device_get_platform(self), nm_device_get_ip_ifindex(self)); if (pllink) { hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address); bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast); + + str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink), + "ID_NET_DHCP_BROADCAST"); + if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) { + /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces + * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast + * messages while not fully configured. + */ + request_broadcast = TRUE; + } } client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr); @@ -9413,28 +9565,29 @@ dhcp4_start(NMDevice *self) reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip4, NULL); g_warn_if_fail(priv->dhcp_data_4.client == NULL); - priv->dhcp_data_4.client = - nm_dhcp_manager_start_ip4(nm_dhcp_manager_get(), - nm_netns_get_multi_idx(nm_device_get_netns(self)), - nm_device_get_ip_iface(self), - nm_device_get_ip_ifindex(self), - hwaddr, - bcast_hwaddr, - nm_connection_get_uuid(connection), - nm_device_get_route_table(self, AF_INET), - nm_device_get_route_metric(self, AF_INET), - nm_setting_ip_config_get_dhcp_send_hostname(s_ip4), - nm_setting_ip_config_get_dhcp_hostname(s_ip4), - nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)), - _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET), - _prop_get_connection_mud_url(self, s_con, &mud_url_free), - client_id, - _prop_get_ipvx_dhcp_timeout(self, AF_INET), - priv->dhcp_anycast_address, - NULL, - vendor_class_identifier, - reject_servers, - &error); + priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4( + nm_dhcp_manager_get(), + nm_netns_get_multi_idx(nm_device_get_netns(self)), + nm_device_get_ip_iface(self), + nm_device_get_ip_ifindex(self), + hwaddr, + bcast_hwaddr, + nm_connection_get_uuid(connection), + nm_device_get_route_table(self, AF_INET), + nm_device_get_route_metric(self, AF_INET), + request_broadcast ? NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST : NM_DHCP_CLIENT_FLAGS_NONE, + nm_setting_ip_config_get_dhcp_send_hostname(s_ip4), + nm_setting_ip_config_get_dhcp_hostname(s_ip4), + nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)), + _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET), + _prop_get_connection_mud_url(self, s_con), + client_id, + _prop_get_ipvx_dhcp_timeout(self, AF_INET), + _device_get_dhcp_anycast_address(self), + NULL, + vendor_class_identifier, + reject_servers, + &error); if (!priv->dhcp_data_4.client) { _LOGW(LOGD_DHCP4, "failure to start DHCP: %s", error->message); g_clear_error(&error); @@ -9665,7 +9818,7 @@ dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state) _LOGD(LOGD_DHCP6, "DHCPv6 failed (ip_state %s, was_active %d)", - _ip_state_to_string(priv->ip_state_6), + nm_device_ip_state_to_str(priv->ip_state_6), priv->dhcp_data_6.was_active); /* The client is always left running after a failure. */ @@ -9831,12 +9984,12 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) gs_unref_bytes GBytes * duid = NULL; gboolean enforce_duid = FALSE; const NMPlatformLink * pllink; - gs_free char * mud_url_free = NULL; - GError * error = NULL; + GError * error = NULL; guint32 iaid; gboolean iaid_explicit; NMSettingConnection * s_con; const NMPlatformIP6Address *ll_addr = NULL; + int ip_ifindex; g_return_val_if_fail(connection, FALSE); @@ -9846,9 +9999,9 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) nm_assert(s_con); if (priv->ext_ip6_config_captured) { - ll_addr = nm_ip6_config_find_first_address(priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); + ll_addr = nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); } if (!ll_addr) { @@ -9856,7 +10009,13 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) return FALSE; } - pllink = nm_platform_link_get(nm_device_get_platform(self), nm_device_get_ip_ifindex(self)); + ip_ifindex = nm_device_get_ip_ifindex(self); + if (ip_ifindex <= 0) { + _LOGD(LOGD_DHCP6, "can't start DHCPv6: interface is gone"); + return FALSE; + } + + pllink = nm_platform_link_get(nm_device_get_platform(self), ip_ifindex); if (pllink) hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address); @@ -9867,22 +10026,23 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) nm_dhcp_manager_get(), nm_device_get_multi_index(self), nm_device_get_ip_iface(self), - nm_device_get_ip_ifindex(self), + ip_ifindex, &ll_addr->address, nm_connection_get_uuid(connection), nm_device_get_route_table(self, AF_INET6), nm_device_get_route_metric(self, AF_INET6), + (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY + : NM_DHCP_CLIENT_FLAGS_NONE, nm_setting_ip_config_get_dhcp_send_hostname(s_ip6), nm_setting_ip_config_get_dhcp_hostname(s_ip6), _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6), - _prop_get_connection_mud_url(self, s_con, &mud_url_free), + _prop_get_connection_mud_url(self, s_con), duid, enforce_duid, iaid, iaid_explicit, _prop_get_ipvx_dhcp_timeout(self, AF_INET6), - priv->dhcp_anycast_address, - (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, + _device_get_dhcp_anycast_address(self), nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip6)), priv->dhcp6.needed_prefixes, &error); @@ -10088,9 +10248,9 @@ linklocal6_check_complete(NMDevice *self) } if (!priv->ext_ip6_config_captured - || !nm_ip6_config_find_first_address(priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) { + || !nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) { /* we don't have a non-tentative link local address yet. Wait longer. */ return; } @@ -10136,10 +10296,10 @@ check_and_add_ipv6ll_addr(NMDevice *self) return; if (priv->ext_ip6_config_captured - && nm_ip6_config_find_first_address(priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) { + && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) { /* Already have an LL address, nothing to do */ return; } @@ -10209,9 +10369,9 @@ linklocal6_start(NMDevice *self) nm_clear_g_source(&priv->linklocal6_timeout_id); if (priv->ext_ip6_config_captured - && nm_ip6_config_find_first_address(priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) + && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) return TRUE; _LOGD(LOGD_DEVICE, @@ -10456,9 +10616,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) _LOGT(LOGD_DEVICE, "mtu: value %u from source '%s' (%u), current source '%s' (%u)%s", (guint) mtu, - mtu_source_to_str(source), + nm_device_mtu_source_to_str(source), (guint) source, - mtu_source_to_str(priv->mtu_source), + nm_device_mtu_source_to_str(priv->mtu_source), (guint) priv->mtu_source, force ? " (forced)" : ""); } @@ -10522,10 +10682,30 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) } } +#define _IP6_MTU_SYS() \ + ({ \ + if (!ip6_mtu_sysctl.initialized) { \ + ip6_mtu_sysctl.value = nm_device_sysctl_ip_conf_get_int_checked(self, \ + AF_INET6, \ + "mtu", \ + 10, \ + 0, \ + G_MAXUINT32, \ + 0); \ + ip6_mtu_sysctl.initialized = TRUE; \ + } \ + ip6_mtu_sysctl.value; \ + }) + if (mtu_desired && NM_DEVICE_GET_CLASS(self)->mtu_force_set && !priv->mtu_force_set_done) { priv->mtu_force_set_done = TRUE; - if (mtu_desired == mtu_plat) { + if (!priv->mtu_initial && !priv->ip6_mtu_initial) { + /* before touching any of the MTU parameters, record the + * original setting to restore on deactivation. */ + priv->mtu_initial = mtu_plat; + priv->ip6_mtu_initial = _IP6_MTU_SYS(); + } mtu_plat--; if (NM_DEVICE_GET_CLASS(self)->set_platform_mtu(self, mtu_desired - 1)) { _LOGD(LOGD_DEVICE, "mtu: force-set MTU to %u", mtu_desired - 1); @@ -10544,20 +10724,6 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) ip6_mtu == ip6_mtu_orig ? "" : nm_sprintf_buf(sbuf2, " (was %u)", (guint) ip6_mtu_orig), ifindex); -#define _IP6_MTU_SYS() \ - ({ \ - if (!ip6_mtu_sysctl.initialized) { \ - ip6_mtu_sysctl.value = nm_device_sysctl_ip_conf_get_int_checked(self, \ - AF_INET6, \ - "mtu", \ - 10, \ - 0, \ - G_MAXUINT32, \ - 0); \ - ip6_mtu_sysctl.initialized = TRUE; \ - } \ - ip6_mtu_sysctl.value; \ - }) if ((mtu_desired && mtu_desired != mtu_plat) || (ip6_mtu && ip6_mtu != _IP6_MTU_SYS())) { gboolean anticipated_failure = FALSE; @@ -10790,9 +10956,9 @@ ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self) * addresses we find inside priv->ip_config_6. */ if (priv->ip_config_6 - && nm_ip6_config_find_first_address(priv->ip_config_6, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)) + && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ip_config_6), + NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)) nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); else nm_device_activate_schedule_ip_config_timeout(self, AF_INET6); @@ -11395,10 +11561,10 @@ activate_stage3_ip_config_start(NMDevice *self) } static void -fw_change_zone_cb(NMFirewallManager * firewall_manager, - NMFirewallManagerCallId *call_id, - GError * error, - gpointer user_data) +fw_change_zone_cb(NMFirewalldManager * firewalld_manager, + NMFirewalldManagerCallId *call_id, + GError * error, + gpointer user_data) { NMDevice * self = user_data; NMDevicePrivate *priv; @@ -11450,12 +11616,12 @@ fw_change_zone(NMDevice *self) nm_assert(s_con); if (priv->fw_call) { - nm_firewall_manager_cancel_call(priv->fw_call); + nm_firewalld_manager_cancel_call(priv->fw_call); nm_assert(!priv->fw_call); } if (G_UNLIKELY(!priv->fw_mgr)) - priv->fw_mgr = g_object_ref(nm_firewall_manager_get()); + priv->fw_mgr = g_object_ref(nm_firewalld_manager_get()); zone = nm_setting_connection_get_zone(s_con); #if WITH_FIREWALLD_ZONE @@ -11467,12 +11633,12 @@ fw_change_zone(NMDevice *self) zone = "nm-shared"; } #endif - priv->fw_call = nm_firewall_manager_add_or_change_zone(priv->fw_mgr, - nm_device_get_ip_iface(self), - zone, - FALSE, /* change zone */ - fw_change_zone_cb, - self); + priv->fw_call = nm_firewalld_manager_add_or_change_zone(priv->fw_mgr, + nm_device_get_ip_iface(self), + zone, + FALSE, /* change zone */ + fw_change_zone_cb, + self); } /* @@ -11632,7 +11798,7 @@ share_init(NMDevice *self, GError **error) } for (i = 0; i < G_N_ELEMENTS(modules); i++) - nm_utils_modprobe(NULL, FALSE, modules[i], NULL); + nmp_utils_modprobe(NULL, FALSE, modules[i], NULL); return TRUE; } @@ -11648,7 +11814,7 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error) NMConnection * conn; NMSettingConnection * s_con; gboolean announce_android_metered; - NMUtilsShareRules * share_rules; + NMFirewallConfig * firewall_config; g_return_val_if_fail(config, FALSE); @@ -11673,11 +11839,9 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error) req = nm_device_get_act_request(self); g_return_val_if_fail(req, FALSE); - share_rules = nm_utils_share_rules_new(); - - nm_utils_share_rules_add_all_rules(share_rules, ip_iface, ip4_addr->address, ip4_addr->plen); + firewall_config = nm_firewall_config_new(ip_iface, ip4_addr->address, ip4_addr->plen); - nm_act_request_set_shared(req, share_rules); + nm_act_request_set_shared(req, firewall_config); conn = nm_act_request_get_applied_connection(req); s_con = nm_connection_get_setting_connection(conn); @@ -11792,13 +11956,15 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) req = nm_device_get_act_request(self); g_assert(req); + nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[IS_IPv4]); + /* Interface must be IFF_UP before IP config can be applied */ ip_ifindex = nm_device_get_ip_ifindex(self); g_return_if_fail(ip_ifindex); if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume(self)) { - nm_platform_link_set_up(nm_device_get_platform(self), ip_ifindex, NULL); + nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE); if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)) _LOGW(LOGD_DEVICE, "interface %s not up for IP configuration", @@ -12660,7 +12826,7 @@ check_and_reapply_connection(NMDevice * self, klass->reapply_connection(self, con_old, con_new); if (priv->state >= NM_DEVICE_STATE_CONFIG) - lldp_init(self, FALSE); + lldp_setup(self, NM_TERNARY_DEFAULT); if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) { s_ip4_old = nm_connection_get_setting_ip4_config(con_old); @@ -12891,9 +13057,10 @@ impl_device_get_applied_connection(NMDBusObject * obj, return; } - var_settings = nm_connection_to_dbus(applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); + var_settings = + nm_connection_to_dbus(applied_connection, NM_CONNECTION_SERIALIZE_WITH_NON_SECRET); if (!var_settings) - var_settings = g_variant_new_array(G_VARIANT_TYPE("{sa{sv}}"), NULL, 0); + var_settings = nm_g_variant_singleton_aLsaLsvII(); g_dbus_method_invocation_return_value( invocation, @@ -13568,7 +13735,7 @@ nm_device_set_ip_config(NMDevice * self, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE, + NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET, "update-external", NULL); } @@ -13660,18 +13827,24 @@ void nm_device_replace_vpn6_config(NMDevice *self, NMIP6Config *old, NMIP6Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDeviceState state; nm_assert(!old || NM_IS_IP6_CONFIG(old)); + nm_assert(!old || nm_ip6_config_get_ifindex(old) > 0); + nm_assert(!old || nm_device_get_ip_ifindex(self) == 0 + || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(old)); nm_assert(!config || NM_IS_IP6_CONFIG(config)); - nm_assert(!old || nm_ip6_config_get_ifindex(old) == nm_device_get_ip_ifindex(self)); - nm_assert(!config || nm_ip6_config_get_ifindex(config) == nm_device_get_ip_ifindex(self)); + nm_assert(!config || nm_ip6_config_get_ifindex(config) > 0); + nm_assert(!config || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(config)); if (!_replace_vpn_config_in_list(&priv->vpn_configs_6, (GObject *) old, (GObject *) config)) return; - /* NULL to use existing configs */ - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "failed to set VPN routes for device"); + state = nm_device_get_state(self); + if (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_ACTIVATED) { + if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) + _LOGW(LOGD_IP6, "failed to set VPN routes for device"); + } } NMIP6Config * @@ -13979,13 +14152,14 @@ nm_device_is_up(NMDevice *self) static gint64 _get_carrier_wait_ms(NMDevice *self) { - gs_free char *value = NULL; - - value = nm_config_data_get_device_config(NM_CONFIG_GET_DATA, - NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT, - self, - NULL); - return _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT32, CARRIER_WAIT_TIME_MS); + return nm_config_data_get_device_config_int64(NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT, + self, + 10, + 0, + G_MAXINT32, + CARRIER_WAIT_TIME_MS, + CARRIER_WAIT_TIME_MS); } gboolean @@ -13995,6 +14169,7 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware) gboolean device_is_up = FALSE; NMDeviceCapabilities capabilities; int ifindex; + int r; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -14010,7 +14185,9 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware) if (ifindex <= 0) { /* assume success. */ } else { - if (!nm_platform_link_set_up(nm_device_get_platform(self), ifindex, no_firmware)) + r = nm_platform_link_change_flags(nm_device_get_platform(self), ifindex, IFF_UP, TRUE); + NM_SET_OUT(no_firmware, (r == -NME_PL_NO_FIRMWARE)); + if (r < 0) return FALSE; } @@ -14097,7 +14274,7 @@ nm_device_take_down(NMDevice *self, gboolean block) return; } - if (!nm_platform_link_set_down(nm_device_get_platform(self), ifindex)) + if (!nm_platform_link_change_flags(nm_device_get_platform(self), ifindex, IFF_UP, FALSE)) return; device_is_up = nm_device_is_up(self); @@ -14827,7 +15004,7 @@ _set_unmanaged_flags(NMDevice * self, flags, NM_PRINT_FMT_QUOTED(allow_state_transition, ", reason ", - reason_to_string_a(reason), + nm_device_state_reason_to_str_a(reason), transition_state ? ", transition-state" : "", "")); @@ -15016,20 +15193,6 @@ nm_device_set_unmanaged_by_quitting(NMDevice *self) /*****************************************************************************/ -void -nm_device_set_dhcp_anycast_address(NMDevice *self, const char *addr) -{ - NMDevicePrivate *priv; - - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(!addr || nm_utils_hwaddr_valid(addr, ETH_ALEN)); - - priv = NM_DEVICE_GET_PRIVATE(self); - - g_free(priv->dhcp_anycast_address); - priv->dhcp_anycast_address = g_strdup(addr); -} - void nm_device_reapply_settings_immediately(NMDevice *self) { @@ -15702,7 +15865,7 @@ _cancel_activation(NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); if (priv->fw_call) { - nm_firewall_manager_cancel_call(priv->fw_call); + nm_firewalld_manager_cancel_call(priv->fw_call); nm_assert(!priv->fw_call); priv->fw_call = NULL; priv->fw_state = FIREWALL_STATE_INITIALIZED; @@ -15732,11 +15895,11 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type) if (cleanup_type == CLEANUP_TYPE_DECONFIGURE && priv->fw_state >= FIREWALL_STATE_INITIALIZED && priv->fw_mgr && !nm_device_sys_iface_state_is_external(self)) { - nm_firewall_manager_remove_from_zone(priv->fw_mgr, - nm_device_get_ip_iface(self), - NULL, - NULL, - NULL); + nm_firewalld_manager_remove_from_zone(priv->fw_mgr, + nm_device_get_ip_iface(self), + NULL, + NULL, + NULL); } priv->fw_state = FIREWALL_STATE_UNMANAGED; g_clear_object(&priv->fw_mgr); @@ -15750,6 +15913,10 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type) _cleanup_ip_pre(self, AF_INET, cleanup_type); _cleanup_ip_pre(self, AF_INET6, cleanup_type); + + priv->ip_config_started = FALSE; + nm_clear_g_source_inst(&priv->ip_req_timeout_source_4); + nm_clear_g_source_inst(&priv->ip_req_timeout_source_6); } static void @@ -15847,7 +16014,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu else _LOGD(LOGD_DEVICE, "deactivating device (reason '%s') [%d]", - reason_to_string_a(reason), + nm_device_state_reason_to_str_a(reason), reason); /* Save whether or not we tried IPv6 for later */ @@ -15902,8 +16069,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - if (priv->lldp_listener) - nm_lldp_listener_stop(priv->lldp_listener); + lldp_setup(self, NM_TERNARY_FALSE); nm_device_update_metered(self); @@ -15954,6 +16120,14 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu _ethtool_state_reset(self); + if (priv->promisc_reset != NM_OPTION_BOOL_DEFAULT && ifindex > 0) { + nm_platform_link_change_flags(nm_device_get_platform(self), + ifindex, + IFF_PROMISC, + !!priv->promisc_reset); + priv->promisc_reset = NM_OPTION_BOOL_DEFAULT; + } + _cleanup_generic_post(self, cleanup_type); } @@ -16068,7 +16242,8 @@ nm_device_spawn_iface_helper(NMDevice *self) hostname = nm_dhcp_client_get_hostname(priv->dhcp_data_4.client); if (hostname) { - if (nm_dhcp_client_get_use_fqdn(priv->dhcp_data_4.client)) + if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(priv->dhcp_data_4.client), + NM_DHCP_CLIENT_FLAGS_USE_FQDN)) g_ptr_array_add(argv, g_strdup("--dhcp4-fqdn")); else g_ptr_array_add(argv, g_strdup("--dhcp4-hostname")); @@ -16335,8 +16510,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, "state change: %s -> %s (reason '%s', sys-iface-state: '%s'%s)", nm_device_state_to_str(old_state), nm_device_state_to_str(state), - reason_to_string_a(reason), - _sys_iface_state_to_str(priv->sys_iface_state), + nm_device_state_reason_to_str_a(reason), + nm_device_sys_iface_state_to_str(priv->sys_iface_state), priv->firmware_missing ? ", missing firmware" : ""); return; } @@ -16345,8 +16520,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, "state change: %s -> %s (reason '%s', sys-iface-state: '%s')", nm_device_state_to_str(old_state), nm_device_state_to_str(state), - reason_to_string_a(reason), - _sys_iface_state_to_str(priv->sys_iface_state)); + nm_device_state_reason_to_str_a(reason), + nm_device_sys_iface_state_to_str(priv->sys_iface_state)); /* in order to prevent triggering any callback caused * by the device not having any pending action anymore @@ -16692,7 +16867,7 @@ queued_state_set(gpointer user_data) _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", nm_device_state_to_str(priv->queued_state.state), - reason_to_string_a(priv->queued_state.reason), + nm_device_state_reason_to_str_a(priv->queued_state.reason), priv->queued_state.id, "change state"); @@ -16704,7 +16879,7 @@ queued_state_set(gpointer user_data) new_reason = priv->queued_state.reason; nm_device_state_changed(self, new_state, new_reason); - nm_device_remove_pending_action(self, queued_state_to_string(new_state), TRUE); + nm_device_remove_pending_action(self, nm_device_state_queued_state_to_str(new_state), TRUE); return G_SOURCE_REMOVE; } @@ -16722,12 +16897,12 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s%s%s%s", nm_device_state_to_str(priv->queued_state.state), - reason_to_string_a(priv->queued_state.reason), + nm_device_state_reason_to_str_a(priv->queued_state.reason), priv->queued_state.id, "ignore queuing same state change", NM_PRINT_FMT_QUOTED(priv->queued_state.reason != reason, " (reason differs: ", - reason_to_string_a(reason), + nm_device_state_reason_to_str_a(reason), ")", "")); return; @@ -16735,20 +16910,21 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r /* Add pending action for the new state before clearing the queued states, so * that we don't accidentally pop all pending states and reach 'startup complete' */ - nm_device_add_pending_action(self, queued_state_to_string(state), TRUE); + nm_device_add_pending_action(self, nm_device_state_queued_state_to_str(state), TRUE); /* We should only ever have one delayed state transition at a time */ if (priv->queued_state.id) { _LOGW(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", nm_device_state_to_str(priv->queued_state.state), - reason_to_string_a(priv->queued_state.reason), + nm_device_state_reason_to_str_a(priv->queued_state.reason), priv->queued_state.id, "replace previously queued state change"); nm_clear_g_source(&priv->queued_state.id); - nm_device_remove_pending_action(self, - queued_state_to_string(priv->queued_state.state), - TRUE); + nm_device_remove_pending_action( + self, + nm_device_state_queued_state_to_str(priv->queued_state.state), + TRUE); } priv->queued_state.state = state; @@ -16758,7 +16934,7 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", nm_device_state_to_str(state), - reason_to_string_a(reason), + nm_device_state_reason_to_str_a(reason), priv->queued_state.id, "queue state change"); } @@ -16774,11 +16950,13 @@ queued_state_clear(NMDevice *self) _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", nm_device_state_to_str(priv->queued_state.state), - reason_to_string_a(priv->queued_state.reason), + nm_device_state_reason_to_str_a(priv->queued_state.reason), priv->queued_state.id, "clear queued state change"); nm_clear_g_source(&priv->queued_state.id); - nm_device_remove_pending_action(self, queued_state_to_string(priv->queued_state.state), TRUE); + nm_device_remove_pending_action(self, + nm_device_state_queued_state_to_str(priv->queued_state.state), + TRUE); } NMDeviceState @@ -16796,7 +16974,7 @@ const char * nm_device_get_hw_address(NMDevice *self) { NMDevicePrivate *priv; - char buf[NM_UTILS_HWADDR_LEN_MAX]; + char buf[_NM_UTILS_HWADDR_LEN_MAX]; gsize l; g_return_val_if_fail(NM_IS_DEVICE(self), NULL); @@ -16890,7 +17068,7 @@ void nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + guint8 buf[_NM_UTILS_HWADDR_LEN_MAX]; size_t len = 0; gboolean success_read; int ifindex; @@ -17008,7 +17186,7 @@ _hw_addr_set(NMDevice * self, NMDevicePrivate *priv; gboolean success = FALSE; int r; - guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; + guint8 addr_bytes[_NM_UTILS_HWADDR_LEN_MAX]; gsize addr_len; gboolean was_taken_down = FALSE; gboolean retry_down; @@ -17209,14 +17387,13 @@ _hw_addr_get_cloned(NMDevice * self, gboolean * preserve, char ** hwaddr, HwAddrType * hwaddr_type, - char ** hwaddr_detail, + const char ** hwaddr_detail, GError ** error) { NMDevicePrivate *priv; - gs_free char * addr_setting_free = NULL; - gs_free char * hw_addr_generated = NULL; - gs_free char * generate_mac_address_mask_tmp = NULL; - const char * addr, *addr_setting; + gs_free char * hw_addr_generated = NULL; + const char * addr; + const char * addr_setting; char * addr_out; HwAddrType type_out; @@ -17229,15 +17406,16 @@ _hw_addr_get_cloned(NMDevice * self, if (!connection) g_return_val_if_reached(FALSE); - addr = addr_setting = - _prop_get_x_cloned_mac_address(self, connection, is_wifi, &addr_setting_free); + addr_setting = _prop_get_x_cloned_mac_address(self, connection, is_wifi); + + addr = addr_setting; if (nm_streq(addr, NM_CLONED_MAC_PRESERVE)) { /* "preserve" means to reset the initial MAC address. */ NM_SET_OUT(preserve, TRUE); NM_SET_OUT(hwaddr, NULL); NM_SET_OUT(hwaddr_type, HW_ADDR_TYPE_UNSET); - NM_SET_OUT(hwaddr_detail, g_steal_pointer(&addr_setting_free) ?: g_strdup(addr_setting)); + NM_SET_OUT(hwaddr_detail, addr_setting); return TRUE; } @@ -17250,8 +17428,7 @@ _hw_addr_get_cloned(NMDevice * self, NM_SET_OUT(preserve, TRUE); NM_SET_OUT(hwaddr, NULL); NM_SET_OUT(hwaddr_type, HW_ADDR_TYPE_UNSET); - NM_SET_OUT(hwaddr_detail, - g_steal_pointer(&addr_setting_free) ?: g_strdup(addr_setting)); + NM_SET_OUT(hwaddr_detail, addr_setting); return TRUE; } else if (!addr) { g_set_error_literal(error, @@ -17271,10 +17448,7 @@ _hw_addr_get_cloned(NMDevice * self, } hw_addr_generated = nm_utils_hw_addr_gen_random_eth( nm_device_get_initial_hw_address(self), - _prop_get_x_generate_mac_address_mask(self, - connection, - is_wifi, - &generate_mac_address_mask_tmp)); + _prop_get_x_generate_mac_address_mask(self, connection, is_wifi)); if (!hw_addr_generated) { g_set_error(error, NM_DEVICE_ERROR, @@ -17302,10 +17476,7 @@ _hw_addr_get_cloned(NMDevice * self, stable_id, nm_device_get_ip_iface(self), nm_device_get_initial_hw_address(self), - _prop_get_x_generate_mac_address_mask(self, - connection, - is_wifi, - &generate_mac_address_mask_tmp)); + _prop_get_x_generate_mac_address_mask(self, connection, is_wifi)); if (!hw_addr_generated) { g_set_error(error, NM_DEVICE_ERROR, @@ -17329,7 +17500,7 @@ _hw_addr_get_cloned(NMDevice * self, NM_SET_OUT(preserve, FALSE); NM_SET_OUT(hwaddr, addr_out); NM_SET_OUT(hwaddr_type, type_out); - NM_SET_OUT(hwaddr_detail, g_steal_pointer(&addr_setting_free) ?: g_strdup(addr_setting)); + NM_SET_OUT(hwaddr_detail, addr_setting); return TRUE; out_no_action: NM_SET_OUT(preserve, FALSE); @@ -17359,7 +17530,7 @@ nm_device_hw_addr_set_cloned(NMDevice *self, NMConnection *connection, gboolean NMDevicePrivate *priv; gboolean preserve = FALSE; gs_free char * hwaddr = NULL; - gs_free char * detail = NULL; + const char * detail = NULL; HwAddrType type = HW_ADDR_TYPE_UNSET; gs_free_error GError *error = NULL; @@ -17599,23 +17770,38 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use { HostnameResolver *resolver; NMDevice * self; - gs_free char * hostname = NULL; gs_free char * addr_str = NULL; + gs_free char * output = NULL; gs_free_error GError *error = NULL; - hostname = g_resolver_lookup_by_address_finish(G_RESOLVER(source), result, &error); + output = nm_device_resolve_address_finish(result, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; - resolver = user_data; - self = resolver->device; - resolver->state = RESOLVER_DONE; - resolver->hostname = g_strdup(hostname); + resolver = user_data; + self = resolver->device; + resolver->state = RESOLVER_DONE; + + if (error) { + _LOGD(LOGD_DNS, + "hostname-from-dns: lookup error for %s: %s", + (addr_str = g_inet_address_to_string(resolver->address)), + error->message); + } else { + gboolean valid; + + resolver->hostname = g_steal_pointer(&output); + valid = nm_hostname_manager_validate_hostname(resolver->hostname); + + _LOGD(LOGD_DNS, + "hostname-from-dns: lookup done for %s, result %s%s%s%s", + (addr_str = g_inet_address_to_string(resolver->address)), + NM_PRINT_FMT_QUOTE_STRING(resolver->hostname), + valid ? "" : " (invalid)"); - _LOGD(LOGD_DNS, - "hostname-from-dns: lookup done for %s, result %s%s%s", - (addr_str = g_inet_address_to_string(resolver->address)), - NM_PRINT_FMT_QUOTE_STRING(hostname)); + if (!valid) + g_clear_pointer(&resolver->hostname, g_free); + } nm_clear_g_cancellable(&resolver->cancellable); g_signal_emit(self, signals[DNS_LOOKUP_DONE], 0); @@ -17713,7 +17899,6 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean if (!resolver) { resolver = g_slice_new(HostnameResolver); *resolver = (HostnameResolver){ - .resolver = g_resolver_get_default(), .device = self, .addr_family = addr_family, .state = RESOLVER_WAIT_ADDRESS, @@ -17721,13 +17906,36 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean priv->hostname_resolver_x[IS_IPv4] = resolver; } - /* Determine the first address of the interface and - * whether it changed from the previous lookup */ + /* Determine the most suitable address of the interface + * and whether it changed from the previous lookup */ ip_config = priv->ip_config_x[IS_IPv4]; if (ip_config) { - const NMPlatformIPAddress *addr; + const NMPlatformIPAddress *addr = NULL; + + if (IS_IPv4) { + addr = nm_ip_config_get_first_address(ip_config); + } else { + /* For IPv6 prefer, in order: + * - !link-local, !deprecated + * - !link-local, deprecated + * - link-local + */ + addr = nm_ip_config_find_first_address(ip_config, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); + if (!addr) { + addr = nm_ip_config_find_first_address( + ip_config, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED); + } + if (!addr) { + addr = nm_ip_config_find_first_address(ip_config, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY); + } + } - addr = nm_ip_config_get_first_address(ip_config); if (addr) { new_address = g_inet_address_new_from_bytes(addr->address_ptr, IS_IPv4 ? G_SOCKET_FAMILY_IPV4 @@ -17763,20 +17971,15 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean } if (address_changed && new_address) { - gs_free char *str = NULL; - - _LOGT(LOGD_DNS, - "hostname-from-dns: starting lookup for address %s", - (str = g_inet_address_to_string(new_address))); - resolver->state = RESOLVER_IN_PROGRESS; resolver->cancellable = g_cancellable_new(); resolver->address = g_steal_pointer(&new_address); - g_resolver_lookup_by_address_async(resolver->resolver, - resolver->address, - resolver->cancellable, - hostname_dns_lookup_callback, - resolver); + + nm_device_resolve_address(addr_family, + g_inet_address_to_bytes(resolver->address), + resolver->cancellable, + hostname_dns_lookup_callback, + resolver); nm_clear_g_source(&resolver->timeout_id); } @@ -17826,7 +18029,6 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDevice * self = NM_DEVICE(object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - GVariantBuilder array_builder; switch (prop_id) { case PROP_UDI: @@ -17977,12 +18179,10 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_uint(value, priv->metered); break; case PROP_LLDP_NEIGHBORS: - if (priv->lldp_listener) - g_value_set_variant(value, nm_lldp_listener_get_neighbors(priv->lldp_listener)); - else { - g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aa{sv}")); - g_value_take_variant(value, g_variant_builder_end(&array_builder)); - } + g_value_set_variant(value, + priv->lldp_listener + ? nm_lldp_listener_get_neighbors(priv->lldp_listener) + : nm_g_variant_singleton_aaLsvI()); break; case PROP_REAL: g_value_set_boolean(value, nm_device_is_real(self)); @@ -18162,6 +18362,8 @@ nm_device_init(NMDevice *self) priv->v4_commit_first_time = TRUE; priv->v6_commit_first_time = TRUE; + + priv->promisc_reset = NM_OPTION_BOOL_DEFAULT; } static GObject * @@ -18191,7 +18393,7 @@ constructor(GType type, guint n_construct_params, GObjectConstructParam *constru } if (priv->hw_addr_perm) { - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + guint8 buf[_NM_UTILS_HWADDR_LEN_MAX]; gsize l; if (!_nm_utils_hwaddr_aton(priv->hw_addr_perm, buf, sizeof(buf), &l)) { @@ -18339,13 +18541,7 @@ dispose(GObject *object) nm_clear_g_source(&priv->device_link_changed_id); nm_clear_g_source(&priv->device_ip_link_changed_id); - if (priv->lldp_listener) { - g_signal_handlers_disconnect_by_func(priv->lldp_listener, - G_CALLBACK(lldp_neighbors_changed), - self); - nm_lldp_listener_stop(priv->lldp_listener); - g_clear_object(&priv->lldp_listener); - } + lldp_setup(self, FALSE); nm_clear_g_source(&priv->concheck_x[0].p_cur_id); nm_clear_g_source(&priv->concheck_x[1].p_cur_id); @@ -18388,7 +18584,6 @@ finalize(GObject *object) g_free(priv->driver_version); g_free(priv->firmware_version); g_free(priv->type_desc); - g_free(priv->dhcp_anycast_address); g_free(priv->current_stable_id); g_hash_table_unref(priv->ip6_saved_properties); @@ -18443,75 +18638,69 @@ static const NMDBusInterfaceInfoExtended interface_info_device = { .handle = impl_device_delete, ), ), .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_state_changed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Udi", "s", NM_DEVICE_UDI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Path", "s", NM_DEVICE_PATH), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Interface", "s", NM_DEVICE_IFACE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("IpInterface", - "s", - NM_DEVICE_IP_IFACE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Driver", "s", NM_DEVICE_DRIVER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DriverVersion", - "s", - NM_DEVICE_DRIVER_VERSION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("FirmwareVersion", - "s", - NM_DEVICE_FIRMWARE_VERSION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Capabilities", - "u", - NM_DEVICE_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip4Address", - "u", - NM_DEVICE_IP4_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("State", "u", NM_DEVICE_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("StateReason", - "(uu)", - NM_DEVICE_STATE_REASON), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActiveConnection", - "o", - NM_DEVICE_ACTIVE_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip4Config", - "o", - NM_DEVICE_IP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp4Config", - "o", - NM_DEVICE_DHCP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip6Config", - "o", - NM_DEVICE_IP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp6Config", - "o", - NM_DEVICE_DHCP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L("Managed", - "b", - NM_DEVICE_MANAGED, - NM_AUTH_PERMISSION_NETWORK_CONTROL, - NM_AUDIT_OP_DEVICE_MANAGED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L("Autoconnect", - "b", - NM_DEVICE_AUTOCONNECT, - NM_AUTH_PERMISSION_NETWORK_CONTROL, - NM_AUDIT_OP_DEVICE_AUTOCONNECT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("FirmwareMissing", - "b", - NM_DEVICE_FIRMWARE_MISSING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("NmPluginMissing", - "b", - NM_DEVICE_NM_PLUGIN_MISSING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DeviceType", - "u", - NM_DEVICE_DEVICE_TYPE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AvailableConnections", - "ao", - NM_DEVICE_AVAILABLE_CONNECTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PhysicalPortId", - "s", - NM_DEVICE_PHYSICAL_PORT_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mtu", "u", NM_DEVICE_MTU), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Metered", "u", NM_DEVICE_METERED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("LldpNeighbors", - "aa{sv}", - NM_DEVICE_LLDP_NEIGHBORS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Real", "b", NM_DEVICE_REAL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Udi", "s", NM_DEVICE_UDI), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Path", "s", NM_DEVICE_PATH), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Interface", "s", NM_DEVICE_IFACE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("IpInterface", "s", NM_DEVICE_IP_IFACE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Driver", "s", NM_DEVICE_DRIVER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DriverVersion", + "s", + NM_DEVICE_DRIVER_VERSION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FirmwareVersion", + "s", + NM_DEVICE_FIRMWARE_VERSION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Capabilities", + "u", + NM_DEVICE_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Address", + "u", + NM_DEVICE_IP4_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("State", "u", NM_DEVICE_STATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("StateReason", + "(uu)", + NM_DEVICE_STATE_REASON), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ActiveConnection", + "o", + NM_DEVICE_ACTIVE_CONNECTION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Config", "o", NM_DEVICE_IP4_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Dhcp4Config", + "o", + NM_DEVICE_DHCP4_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip6Config", "o", NM_DEVICE_IP6_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Dhcp6Config", + "o", + NM_DEVICE_DHCP6_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE("Managed", + "b", + NM_DEVICE_MANAGED, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + NM_AUDIT_OP_DEVICE_MANAGED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE("Autoconnect", + "b", + NM_DEVICE_AUTOCONNECT, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + NM_AUDIT_OP_DEVICE_AUTOCONNECT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FirmwareMissing", + "b", + NM_DEVICE_FIRMWARE_MISSING), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NmPluginMissing", + "b", + NM_DEVICE_NM_PLUGIN_MISSING), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DeviceType", + "u", + NM_DEVICE_DEVICE_TYPE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AvailableConnections", + "ao", + NM_DEVICE_AVAILABLE_CONNECTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PhysicalPortId", + "s", + NM_DEVICE_PHYSICAL_PORT_ID), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mtu", "u", NM_DEVICE_MTU), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Metered", "u", NM_DEVICE_METERED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LldpNeighbors", + "aa{sv}", + NM_DEVICE_LLDP_NEIGHBORS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Real", "b", NM_DEVICE_REAL), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Connectivity", "u", NM_DEVICE_IP4_CONNECTIVITY), @@ -18526,10 +18715,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device = { NM_DEVICE_HW_ADDRESS), ), ), }; -const NMDBusInterfaceInfoExtended nm_interface_info_device_statistics = { +static const NMDBusInterfaceInfoExtended interface_info_device_statistics = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_STATISTICS, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE( "RefreshRateMs", @@ -18555,7 +18743,7 @@ nm_device_class_init(NMDeviceClass *klass) dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/Devices"); dbus_object_class->interface_infos = - NM_DBUS_INTERFACE_INFOS(&interface_info_device, &nm_interface_info_device_statistics); + NM_DBUS_INTERFACE_INFOS(&interface_info_device, &interface_info_device_statistics); object_class->dispose = dispose; object_class->finalize = finalize; diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index 68343ef5..f59b6fa8 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -15,54 +15,7 @@ #include "nm-connection.h" #include "nm-rfkill-manager.h" #include "NetworkManagerUtils.h" - -typedef enum _nm_packed { - NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, - NM_DEVICE_SYS_IFACE_STATE_ASSUME, - NM_DEVICE_SYS_IFACE_STATE_MANAGED, - - /* the REMOVED state applies when the device is manually set to unmanaged - * or the link was externally removed. In both cases, we move the device - * to UNMANAGED state, without touching the link -- be it, because the link - * is already gone or because we want to release it (give it up). - */ - NM_DEVICE_SYS_IFACE_STATE_REMOVED, -} NMDeviceSysIfaceState; - -typedef enum { - NM_DEVICE_MTU_SOURCE_NONE, - NM_DEVICE_MTU_SOURCE_PARENT, - NM_DEVICE_MTU_SOURCE_IP_CONFIG, - NM_DEVICE_MTU_SOURCE_CONNECTION, -} NMDeviceMtuSource; - -static inline NMDeviceStateReason -nm_device_state_reason_check(NMDeviceStateReason reason) -{ - /* the device-state-reason serves mostly informational purpose during a state - * change. In some cases however, decisions are made based on the reason. - * I tend to think that interpreting the state reason to derive some behaviors - * is confusing, because the cause and effect are so far apart. - * - * This function is here to mark source that inspects the reason to make - * a decision -- contrary to places that set the reason. Thus, by grepping - * for nm_device_state_reason_check() you can find the "effect" to a certain - * reason. - */ - return reason; -} - -#define NM_PENDING_ACTION_AUTOACTIVATE "autoactivate" -#define NM_PENDING_ACTION_IN_STATE_CHANGE "in-state-change" -#define NM_PENDING_ACTION_RECHECK_AVAILABLE "recheck-available" -#define NM_PENDING_ACTION_CARRIER_WAIT "carrier-wait" -#define NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT "waiting-for-supplicant" -#define NM_PENDING_ACTION_WIFI_SCAN "wifi-scan" -#define NM_PENDING_ACTION_WAITING_FOR_COMPANION "waiting-for-companion" -#define NM_PENDING_ACTION_LINK_INIT "link-init" - -#define NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "queued-state-change-" -#define NM_PENDING_ACTIONPREFIX_ACTIVATION "activation-" +#include "nm-device-utils.h" /* Properties */ #define NM_DEVICE_UDI "udi" @@ -109,10 +62,10 @@ nm_device_state_reason_check(NMDeviceStateReason reason) * NMDeviceOvsBridge and NMDeviceOvsPort. */ #define NM_DEVICE_SLAVES "slaves" /* partially internal */ -#define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ -#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ -#define NM_DEVICE_IFINDEX "ifindex" /* Internal only */ -#define NM_DEVICE_MASTER "master" /* Internal only */ +#define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ +#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ +#define NM_DEVICE_IFINDEX "ifindex" /* Internal only */ +#define NM_DEVICE_MASTER "master" /* Internal only */ #define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */ /* Internal signals */ @@ -459,6 +412,8 @@ typedef struct _NMDeviceClass { gboolean (*set_platform_mtu)(NMDevice *self, guint32 mtu); + const char *(*get_dhcp_anycast_address)(NMDevice *self); + } NMDeviceClass; GType nm_device_get_type(void); @@ -572,6 +527,7 @@ nm_device_check_connection_compatible(NMDevice *device, NMConnection *connection gboolean nm_device_check_slave_connection_compatible(NMDevice *device, NMConnection *connection); +gboolean nm_device_can_assume_connections(NMDevice *self); gboolean nm_device_unmanage_on_quit(NMDevice *self); gboolean nm_device_spec_match_list(NMDevice *device, const GSList *specs); @@ -862,9 +818,6 @@ struct _NMBtVTableNetworkServer { gboolean (*unregister_bridge)(const NMBtVTableNetworkServer *vtable, NMDevice *device); }; -const char *nm_device_state_to_str(NMDeviceState state); -const char *nm_device_state_reason_to_str(NMDeviceStateReason reason); - gboolean nm_device_is_vpn(NMDevice *self); const char * diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index c60fb3ad..aba972ae 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -9,12 +9,15 @@ #include -#include "nm-std-aux/unaligned.h" -#include "platform/nm-platform.h" -#include "nm-glib-aux/nm-c-list.h" +#include "NetworkManagerUtils.h" +#include "libnm-core-public/nm-errors.h" +#include "libnm-glib-aux/nm-time-utils.h" +#include "libnm-std-aux/unaligned.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-utils.h" -#include "systemd/nm-sd.h" +#include "libnm-systemd-core/nm-sd.h" #define MAX_NEIGHBORS 128 #define MIN_UPDATE_INTERVAL_NSEC (2 * NM_UTILS_NSEC_PER_SEC) @@ -28,34 +31,21 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE(NMLldpListener, PROP_NEIGHBORS, ); - -typedef struct { +struct _NMLldpListener { sd_lldp * lldp_handle; GHashTable *lldp_neighbors; GVariant * variant; + NMLldpListenerNotify notify_callback; + gpointer notify_user_data; + /* the timestamp in nsec until which we delay updates. */ - gint64 ratelimit_next_nsec; - guint ratelimit_id; + GSource *ratelimit_source; + gint64 ratelimit_next_nsec; int ifindex; -} NMLldpListenerPrivate; - -struct _NMLldpListener { - GObject parent; - NMLldpListenerPrivate _priv; -}; - -struct _NMLldpListenerClass { - GObjectClass parent; }; -G_DEFINE_TYPE(NMLldpListener, nm_lldp_listener, G_TYPE_OBJECT) - -#define NM_LLDP_LISTENER_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMLldpListener, NM_IS_LLDP_LISTENER) - /*****************************************************************************/ typedef struct { @@ -71,27 +61,28 @@ typedef struct { #define _NMLOG_PREFIX_NAME "lldp" #define _NMLOG_DOMAIN LOGD_DEVICE -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - const NMLogLevel _level = (level); \ - \ - if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ - char _sbuf[64]; \ - int _ifindex = (self) ? NM_LLDP_LISTENER_GET_PRIVATE(self)->ifindex : 0; \ - \ - _nm_log(_level, \ - _NMLOG_DOMAIN, \ - 0, \ - _ifindex > 0 ? nm_platform_link_get_name(NM_PLATFORM_GET, _ifindex) : NULL, \ - NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((_ifindex > 0) ? nm_sprintf_buf(_sbuf, "[%p,%d]", (self), _ifindex) \ - : ((self) ? nm_sprintf_buf(_sbuf, "[%p]", (self)) : "")) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ + char _sbuf[100]; \ + \ + _nm_log(_level, \ + _NMLOG_DOMAIN, \ + 0, \ + (self) ? nm_platform_link_get_name(NM_PLATFORM_GET, (self)->ifindex) : NULL, \ + NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((self) ? nm_sprintf_buf(_sbuf, \ + "[" NM_HASH_OBFUSCATE_PTR_FMT ",%d]", \ + NM_HASH_OBFUSCATE_PTR(self), \ + (self)->ifindex) \ + : "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ G_STMT_END #define LOG_NEIGH_FMT "CHASSIS=%u/%s PORT=%u/%s" @@ -809,80 +800,73 @@ nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len) /*****************************************************************************/ static void -data_changed_notify(NMLldpListener *self, NMLldpListenerPrivate *priv) +data_changed_notify(NMLldpListener *self) { - nm_clear_g_variant(&priv->variant); - _notify(self, PROP_NEIGHBORS); + nm_clear_g_variant(&self->variant); + + self->notify_callback(self, self->notify_user_data); } static gboolean data_changed_timeout(gpointer user_data) { - NMLldpListener * self = user_data; - NMLldpListenerPrivate *priv; + NMLldpListener *self = user_data; - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), G_SOURCE_REMOVE); - - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - priv->ratelimit_id = 0; - priv->ratelimit_next_nsec = nm_utils_get_monotonic_timestamp_nsec() + MIN_UPDATE_INTERVAL_NSEC; - data_changed_notify(self, priv); - return G_SOURCE_REMOVE; + nm_clear_g_source_inst(&self->ratelimit_source); + self->ratelimit_next_nsec = nm_utils_get_monotonic_timestamp_nsec() + MIN_UPDATE_INTERVAL_NSEC; + data_changed_notify(self); + return G_SOURCE_CONTINUE; } static void data_changed_schedule(NMLldpListener *self) { - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - gint64 now_nsec; + gint64 now_nsec; - if (priv->ratelimit_id != 0) + if (self->ratelimit_source) return; now_nsec = nm_utils_get_monotonic_timestamp_nsec(); - if (now_nsec < priv->ratelimit_next_nsec) { - priv->ratelimit_id = - g_timeout_add_full(G_PRIORITY_LOW, - NM_UTILS_NSEC_TO_MSEC_CEIL(priv->ratelimit_next_nsec - now_nsec), - data_changed_timeout, - self, - NULL); - return; + if (now_nsec < self->ratelimit_next_nsec) { + self->ratelimit_source = nm_g_timeout_source_new( + NM_UTILS_NSEC_TO_MSEC_CEIL(self->ratelimit_next_nsec - now_nsec), + G_PRIORITY_LOW, + data_changed_timeout, + self, + NULL); + } else { + self->ratelimit_source = + nm_g_idle_source_new(G_PRIORITY_LOW, data_changed_timeout, self, NULL); } - priv->ratelimit_id = g_idle_add_full(G_PRIORITY_LOW, data_changed_timeout, self, NULL); + g_source_attach(self->ratelimit_source, NULL); } static void process_lldp_neighbor(NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboolean remove) { - NMLldpListenerPrivate * priv; nm_auto(lldp_neighbor_freep) LldpNeighbor *neigh = NULL; LldpNeighbor * neigh_old; - g_return_if_fail(NM_IS_LLDP_LISTENER(self)); + nm_assert(self); + nm_assert(self->lldp_handle); + nm_assert(self->lldp_neighbors); - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - g_return_if_fail(priv->lldp_handle); g_return_if_fail(neighbor_sd); - nm_assert(priv->lldp_neighbors); - neigh = lldp_neighbor_new(neighbor_sd); if (!neigh) { _LOGT("process: failed to parse neighbor"); return; } - neigh_old = g_hash_table_lookup(priv->lldp_neighbors, neigh); + neigh_old = g_hash_table_lookup(self->lldp_neighbors, neigh); if (remove) { if (neigh_old) { _LOGT("process: %s neigh: " LOG_NEIGH_FMT, "remove", LOG_NEIGH_ARG(neigh)); - g_hash_table_remove(priv->lldp_neighbors, neigh_old); + g_hash_table_remove(self->lldp_neighbors, neigh_old); goto handle_changed; } return; @@ -893,14 +877,14 @@ process_lldp_neighbor(NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gbool _LOGD("process: %s neigh: " LOG_NEIGH_FMT, neigh_old ? "update" : "new", LOG_NEIGH_ARG(neigh)); - g_hash_table_add(priv->lldp_neighbors, g_steal_pointer(&neigh)); + g_hash_table_add(self->lldp_neighbors, g_steal_pointer(&neigh)); handle_changed: data_changed_schedule(self); } static void -lldp_event_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) +lldp_event_handler(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n, void *userdata) { process_lldp_neighbor( userdata, @@ -908,25 +892,57 @@ lldp_event_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void !NM_IN_SET(event, SD_LLDP_EVENT_ADDED, SD_LLDP_EVENT_UPDATED, SD_LLDP_EVENT_REFRESHED)); } -gboolean -nm_lldp_listener_start(NMLldpListener *self, int ifindex, GError **error) +/*****************************************************************************/ + +int +nm_lldp_listener_get_ifindex(NMLldpListener *self) { - NMLldpListenerPrivate *priv; - int ret; + g_return_val_if_fail(self, 0); - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), FALSE); - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); + return self->ifindex; +} - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); +/*****************************************************************************/ - if (priv->lldp_handle) { - g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "already running"); - return FALSE; +GVariant * +nm_lldp_listener_get_neighbors(NMLldpListener *self) +{ + g_return_val_if_fail(self, FALSE); + + if (G_UNLIKELY(!self->variant)) { + gs_free LldpNeighbor **neighbors = NULL; + GVariantBuilder array_builder; + guint i, n; + + g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aa{sv}")); + neighbors = (LldpNeighbor **) + nm_utils_hash_keys_to_array(self->lldp_neighbors, lldp_neighbor_id_cmp_p, NULL, &n); + for (i = 0; i < n; i++) + g_variant_builder_add_value(&array_builder, lldp_neighbor_to_variant(neighbors[i])); + self->variant = g_variant_ref_sink(g_variant_builder_end(&array_builder)); } - ret = sd_lldp_new(&priv->lldp_handle); - if (ret < 0) { + return self->variant; +} + +/*****************************************************************************/ + +NMLldpListener * +nm_lldp_listener_new(int ifindex, + NMLldpListenerNotify notify_callback, + gpointer notify_user_data, + GError ** error) +{ + NMLldpListener *self = NULL; + sd_lldp * lldp_handle; + int r; + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + g_return_val_if_fail(notify_callback, FALSE); + + r = sd_lldp_new(&lldp_handle); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, @@ -934,189 +950,77 @@ nm_lldp_listener_start(NMLldpListener *self, int ifindex, GError **error) return FALSE; } - ret = sd_lldp_set_ifindex(priv->lldp_handle, ifindex); - if (ret < 0) { + r = sd_lldp_set_ifindex(lldp_handle, ifindex); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "failed setting ifindex"); - goto err; + goto fail_handle; } - ret = sd_lldp_set_callback(priv->lldp_handle, lldp_event_handler, self); - if (ret < 0) { - g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "set callback failed"); - goto err; - } + r = sd_lldp_set_neighbors_max(lldp_handle, MAX_NEIGHBORS); + nm_assert(r == 0); - ret = sd_lldp_set_neighbors_max(priv->lldp_handle, MAX_NEIGHBORS); - nm_assert(ret == 0); + self = g_slice_new(NMLldpListener); + *self = (NMLldpListener){ + .ifindex = ifindex, + .notify_callback = notify_callback, + .notify_user_data = notify_user_data, + }; - priv->ifindex = ifindex; + r = sd_lldp_set_callback(lldp_handle, lldp_event_handler, self); + if (r < 0) { + g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "set callback failed"); + goto fail_handle; + } - ret = sd_lldp_attach_event(priv->lldp_handle, NULL, 0); - if (ret < 0) { + r = sd_lldp_attach_event(lldp_handle, NULL, 0); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "attach event failed"); - goto err_free; + goto fail_attached; } - ret = sd_lldp_start(priv->lldp_handle); - if (ret < 0) { + r = sd_lldp_start(lldp_handle); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "start failed"); - goto err; + goto fail_attached; } - priv->lldp_neighbors = g_hash_table_new_full(lldp_neighbor_id_hash, + self->lldp_neighbors = g_hash_table_new_full(lldp_neighbor_id_hash, lldp_neighbor_id_equal, (GDestroyNotify) lldp_neighbor_free, NULL); - - _LOGD("start"); - - return TRUE; - -err: - sd_lldp_detach_event(priv->lldp_handle); -err_free: - sd_lldp_unref(priv->lldp_handle); - priv->lldp_handle = NULL; - priv->ifindex = 0; - return FALSE; + self->lldp_handle = lldp_handle; + + _LOGD("start lldp listener"); + return self; + +fail_attached: + sd_lldp_detach_event(lldp_handle); +fail_handle: + if (self) + nm_g_slice_free(self); + sd_lldp_unref(lldp_handle); + return NULL; } void -nm_lldp_listener_stop(NMLldpListener *self) +nm_lldp_listener_destroy(NMLldpListener *self) { - NMLldpListenerPrivate *priv; - guint size; - gboolean changed = FALSE; - - g_return_if_fail(NM_IS_LLDP_LISTENER(self)); - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - if (priv->lldp_handle) { - _LOGD("stop"); - sd_lldp_stop(priv->lldp_handle); - sd_lldp_detach_event(priv->lldp_handle); - sd_lldp_unref(priv->lldp_handle); - priv->lldp_handle = NULL; - - size = g_hash_table_size(priv->lldp_neighbors); - g_hash_table_remove_all(priv->lldp_neighbors); - nm_clear_pointer(&priv->lldp_neighbors, g_hash_table_unref); - if (size > 0 || priv->ratelimit_id != 0) - changed = TRUE; - } + g_return_if_fail(self); - nm_clear_g_source(&priv->ratelimit_id); - priv->ratelimit_next_nsec = 0; - priv->ifindex = 0; + sd_lldp_stop(self->lldp_handle); + sd_lldp_detach_event(self->lldp_handle); + sd_lldp_unref(self->lldp_handle); - if (changed) - data_changed_notify(self, priv); -} - -gboolean -nm_lldp_listener_is_running(NMLldpListener *self) -{ - NMLldpListenerPrivate *priv; - - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), FALSE); - - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - return !!priv->lldp_handle; -} - -GVariant * -nm_lldp_listener_get_neighbors(NMLldpListener *self) -{ - NMLldpListenerPrivate *priv; - - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), FALSE); - - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - if (G_UNLIKELY(!priv->variant)) { - gs_free LldpNeighbor **neighbors = NULL; - GVariantBuilder array_builder; - guint i, n; - - g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aa{sv}")); - neighbors = (LldpNeighbor **) - nm_utils_hash_keys_to_array(priv->lldp_neighbors, lldp_neighbor_id_cmp_p, NULL, &n); - for (i = 0; i < n; i++) - g_variant_builder_add_value(&array_builder, lldp_neighbor_to_variant(neighbors[i])); - priv->variant = g_variant_ref_sink(g_variant_builder_end(&array_builder)); - } - return priv->variant; -} - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMLldpListener *self = NM_LLDP_LISTENER(object); - - switch (prop_id) { - case PROP_NEIGHBORS: - g_value_set_variant(value, nm_lldp_listener_get_neighbors(self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -nm_lldp_listener_init(NMLldpListener *self) -{ - _LOGT("lldp listener created"); -} + nm_clear_g_source_inst(&self->ratelimit_source); -NMLldpListener * -nm_lldp_listener_new(void) -{ - return g_object_new(NM_TYPE_LLDP_LISTENER, NULL); -} + g_hash_table_destroy(self->lldp_neighbors); -static void -dispose(GObject *object) -{ - nm_lldp_listener_stop(NM_LLDP_LISTENER(object)); - - G_OBJECT_CLASS(nm_lldp_listener_parent_class)->dispose(object); -} - -static void -finalize(GObject *object) -{ - NMLldpListener * self = NM_LLDP_LISTENER(object); - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - nm_lldp_listener_stop(self); - - nm_clear_g_variant(&priv->variant); + nm_g_variant_unref(self->variant); _LOGT("lldp listener destroyed"); - G_OBJECT_CLASS(nm_lldp_listener_parent_class)->finalize(object); -} - -static void -nm_lldp_listener_class_init(NMLldpListenerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - object_class->dispose = dispose; - object_class->finalize = finalize; - object_class->get_property = get_property; - - obj_properties[PROP_NEIGHBORS] = - g_param_spec_variant(NM_LLDP_LISTENER_NEIGHBORS, - "", - "", - G_VARIANT_TYPE("aa{sv}"), - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + nm_g_slice_free(self); } diff --git a/src/core/devices/nm-lldp-listener.h b/src/core/devices/nm-lldp-listener.h index 9d3e2436..762eb3d2 100644 --- a/src/core/devices/nm-lldp-listener.h +++ b/src/core/devices/nm-lldp-listener.h @@ -6,28 +6,21 @@ #ifndef __NM_LLDP_LISTENER__ #define __NM_LLDP_LISTENER__ -#define NM_TYPE_LLDP_LISTENER (nm_lldp_listener_get_type()) -#define NM_LLDP_LISTENER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_LLDP_LISTENER, NMLldpListener)) -#define NM_LLDP_LISTENER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) -#define NM_IS_LLDP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_LLDP_LISTENER)) -#define NM_IS_LLDP_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_LLDP_LISTENER)) -#define NM_LLDP_LISTENER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) - -#define NM_LLDP_LISTENER_NEIGHBORS "neighbors" - -typedef struct _NMLldpListenerClass NMLldpListenerClass; - -GType nm_lldp_listener_get_type(void); -NMLldpListener *nm_lldp_listener_new(void); -gboolean nm_lldp_listener_start(NMLldpListener *self, int ifindex, GError **error); -void nm_lldp_listener_stop(NMLldpListener *self); -gboolean nm_lldp_listener_is_running(NMLldpListener *self); +/*****************************************************************************/ +typedef void (*NMLldpListenerNotify)(NMLldpListener *self, gpointer user_data); + +NMLldpListener *nm_lldp_listener_new(int ifindex, + NMLldpListenerNotify notify_callback, + gpointer notify_user_data, + GError ** error); +void nm_lldp_listener_destroy(NMLldpListener *self); + +int nm_lldp_listener_get_ifindex(NMLldpListener *self); GVariant *nm_lldp_listener_get_neighbors(NMLldpListener *self); +/*****************************************************************************/ + GVariant *nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len); #endif /* __NM_LLDP_LISTENER__ */ diff --git a/src/core/devices/ovs/meson.build b/src/core/devices/ovs/meson.build index 81c29bd6..1974ff4c 100644 --- a/src/core/devices/ovs/meson.build +++ b/src/core/devices/ovs/meson.build @@ -13,7 +13,6 @@ libnm_device_plugin_ovs = shared_module( core_plugin_dep, jansson_dep, ], - c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index 3ae8a481..26a5ba00 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -16,7 +16,7 @@ #include "nm-setting-connection.h" #include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-external-ids.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceOvsBridge #include "devices/nm-device-logging.h" @@ -134,9 +134,7 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ovs_bridge = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), ), }; static void diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 0a537f7a..46a612ac 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -414,10 +414,7 @@ dispose(GObject *object) } static const NMDBusInterfaceInfoExtended interface_info_device_ovs_interface = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( - NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), - .legacy_property_changed = TRUE, + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, ), }; static void diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index 2ecb95e8..f11c5852 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -167,9 +167,7 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ovs_port = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_OVS_PORT, .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), ), ), }; static void diff --git a/src/core/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c index e7af38d8..6f5d8832 100644 --- a/src/core/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -10,8 +10,8 @@ #include "nm-device-ovs-interface.h" #include "nm-device-ovs-port.h" #include "nm-device-ovs-bridge.h" -#include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings.h" #include "devices/nm-device-factory.h" #include "devices/nm-device-private.h" diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index da3a7989..b8d5311a 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -10,10 +10,10 @@ #include #include -#include "nm-glib-aux/nm-jansson.h" -#include "nm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-jansson.h" +#include "libnm-glib-aux/nm-str-buf.h" #include "nm-core-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "devices/nm-device.h" #include "nm-manager.h" #include "nm-setting-ovs-external-ids.h" diff --git a/src/core/devices/team/meson.build b/src/core/devices/team/meson.build index d0ff4caa..b1ee9103 100644 --- a/src/core/devices/team/meson.build +++ b/src/core/devices/team/meson.build @@ -11,7 +11,6 @@ libnm_device_plugin_team = shared_module( jansson_dep, libteamdctl_dep, ], - c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index d2d71729..0f1a8c4c 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -15,15 +15,15 @@ #include #include -#include "nm-glib-aux/nm-jansson.h" +#include "libnm-glib-aux/nm-jansson.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-ip4-config.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/nm-dbus-compat.h" #define _NMLOG_DEVICE_TYPE NMDeviceTeam #include "devices/nm-device-logging.h" @@ -829,12 +829,12 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool "enslaved team port %s config not changed, not connected to teamd", slave_iface); } else { - int err; - char *sanitized_config; + gs_free char *sanitized_config = NULL; + int err; - sanitized_config = g_strdelimit(g_strdup(config), "\r\n", ' '); + sanitized_config = g_strdup(config); + g_strdelimit(sanitized_config, "\r\n", ' '); err = teamdctl_port_config_update_raw(priv->tdc, slave_iface, sanitized_config); - g_free(sanitized_config); if (err != 0) { _LOGE(LOGD_TEAM, "failed to update config for port %s (err=%d)", @@ -1042,17 +1042,13 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_team = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_TEAM, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Slaves", "ao", NM_DEVICE_SLAVES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Config", - "s", - NM_DEVICE_TEAM_CONFIG), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Slaves", "ao", NM_DEVICE_SLAVES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Config", + "s", + NM_DEVICE_TEAM_CONFIG), ), ), }; static void diff --git a/src/core/devices/team/nm-team-factory.c b/src/core/devices/team/nm-team-factory.c index 57b51bf8..e2040d19 100644 --- a/src/core/devices/team/nm-team-factory.c +++ b/src/core/devices/team/nm-team-factory.c @@ -10,8 +10,8 @@ #include "nm-manager.h" #include "devices/nm-device-factory.h" #include "nm-device-team.h" -#include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/devices/tests/test-acd.c b/src/core/devices/tests/test-acd.c index b0af59db..b4b65165 100644 --- a/src/core/devices/tests/test-acd.c +++ b/src/core/devices/tests/test-acd.c @@ -78,8 +78,8 @@ fixture_setup(test_fixture *fixture, gconstpointer user_data) fixture->ifindex1 = nmtstp_link_get_typed(NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex; - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, fixture->ifindex0, NULL)); - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, fixture->ifindex1, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex0, IFF_UP, TRUE) >= 0); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex1, IFF_UP, TRUE) >= 0); fixture->hwaddr0 = nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex0, &fixture->hwaddr0_len); diff --git a/src/core/devices/tests/test-lldp.c b/src/core/devices/tests/test-lldp.c index ef0b1549..c64c7c11 100644 --- a/src/core/devices/tests/test-lldp.c +++ b/src/core/devices/tests/test-lldp.c @@ -13,7 +13,7 @@ #include #include "devices/nm-lldp-listener.h" -#include "systemd/nm-sd.h" +#include "libnm-systemd-core/nm-sd.h" #include "platform/tests/test-common.h" @@ -83,6 +83,7 @@ typedef struct { const uint8_t *frame; const char * as_variant; } TestRecvFrame; + #define TEST_RECV_FRAME_DEFINE(name, _as_variant, ...) \ static const guint8 _##name##_v[] = {__VA_ARGS__}; \ static const TestRecvFrame name = { \ @@ -91,12 +92,18 @@ typedef struct { .frame = _##name##_v, \ } +typedef struct { + int num_called; + GMainLoop *loop_to_quit; +} TestRecvCallbackInfo; + typedef struct { guint expected_num_called; gsize frames_len; const TestRecvFrame *frames[10]; - void (*check)(GMainLoop *loop, NMLldpListener *listener); + void (*check)(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info); } TestRecvData; + #define TEST_RECV_DATA_DEFINE(name, _expected_num_called, _check, ...) \ static const TestRecvData name = { \ .expected_num_called = _expected_num_called, \ @@ -213,7 +220,7 @@ _test_recv_data0_check_do(GMainLoop *loop, NMLldpListener *listener, const TestR } static void -_test_recv_data0_check(GMainLoop *loop, NMLldpListener *listener) +_test_recv_data0_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { _test_recv_data0_check_do(loop, listener, &_test_recv_data0_frame0); } @@ -528,7 +535,7 @@ TEST_RECV_FRAME_DEFINE( ); static void -_test_recv_data1_check(GMainLoop *loop, NMLldpListener *listener) +_test_recv_data1_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { GVariant * neighbors, *attr, *child; gs_unref_variant GVariant *neighbor = NULL; @@ -756,21 +763,17 @@ TEST_RECV_FRAME_DEFINE( ); static void -_test_recv_data2_ttl1_check(GMainLoop *loop, NMLldpListener *listener) +_test_recv_data2_ttl1_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { - gulong notify_id; GVariant *neighbors; _test_recv_data0_check_do(loop, listener, &_test_recv_data2_frame0_ttl1); /* wait for signal. */ - notify_id = g_signal_connect(listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - nmtst_main_loop_quit_on_notify, - loop); + info->loop_to_quit = loop; if (!nmtst_main_loop_run(loop, 5000)) g_assert_not_reached(); - nm_clear_g_signal_handler(listener, ¬ify_id); + info->loop_to_quit = NULL; neighbors = nm_lldp_listener_get_neighbors(listener); nmtst_assert_variant_is_of_type(neighbors, G_VARIANT_TYPE("aa{sv}")); @@ -852,46 +855,37 @@ again: memcpy(fixture->mac, link->l_address.data, ETH_ALEN); } -typedef struct { - int num_called; -} TestRecvCallbackInfo; - static void -lldp_neighbors_changed(NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) +lldp_neighbors_changed(NMLldpListener *lldp_listener, gpointer user_data) { TestRecvCallbackInfo *info = user_data; info->num_called++; + if (info->loop_to_quit) + g_main_loop_quit(info->loop_to_quit); } static void test_recv(TestRecvFixture *fixture, gconstpointer user_data) { - const TestRecvData *data = user_data; - gs_unref_object NMLldpListener *listener = NULL; - GMainLoop * loop; - TestRecvCallbackInfo info = {}; - gsize i_frames; - gulong notify_id; - GError * error = NULL; - guint sd_id; + const TestRecvData * data = user_data; + NMLldpListener * listener; + GMainLoop * loop; + TestRecvCallbackInfo info = {}; + gsize i_frames; + GError * error = NULL; + guint sd_id; if (fixture->ifindex == 0) { g_test_skip("Tun device not available"); return; } - listener = nm_lldp_listener_new(); - g_assert(listener != NULL); - g_assert(nm_lldp_listener_start(listener, fixture->ifindex, &error)); - g_assert_no_error(error); + listener = nm_lldp_listener_new(fixture->ifindex, lldp_neighbors_changed, &info, &error); + nmtst_assert_success(listener, error); - notify_id = g_signal_connect(listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - (GCallback) lldp_neighbors_changed, - &info); - loop = g_main_loop_new(NULL, FALSE); - sd_id = nm_sd_event_attach_default(); + loop = g_main_loop_new(NULL, FALSE); + sd_id = nm_sd_event_attach_default(); for (i_frames = 0; i_frames < data->frames_len; i_frames++) { const TestRecvFrame *f = data->frames[i_frames]; @@ -904,9 +898,9 @@ test_recv(TestRecvFixture *fixture, gconstpointer user_data) g_assert_cmpint(info.num_called, ==, data->expected_num_called); - nm_clear_g_signal_handler(listener, ¬ify_id); + data->check(loop, listener, &info); - data->check(loop, listener); + nm_clear_pointer(&listener, nm_lldp_listener_destroy); nm_clear_g_source(&sd_id); nm_clear_pointer(&loop, g_main_loop_unref); diff --git a/src/core/devices/wifi/meson.build b/src/core/devices/wifi/meson.build index 743937db..85553c53 100644 --- a/src/core/devices/wifi/meson.build +++ b/src/core/devices/wifi/meson.build @@ -22,7 +22,6 @@ libnm_device_plugin_wifi_static = static_library( dependencies: [ core_plugin_dep, ], - c_args: daemon_c_flags, ) libnm_device_plugin_wifi_static_dep = declare_dependency( @@ -38,7 +37,6 @@ libnm_device_plugin_wifi = shared_module( core_plugin_dep, libnm_device_plugin_wifi_static_dep ], - c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 01f2a303..56338743 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -13,16 +13,16 @@ #include "devices/nm-device.h" #include "nm-act-request.h" #include "nm-config.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" -#include "nm-glib-aux/nm-ref-string.h" +#include "libnm-glib-aux/nm-ref-string.h" #include "nm-iwd-manager.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-setting-8021x.h" #include "nm-setting-connection.h" #include "nm-setting-wireless-security.h" #include "nm-setting-wireless.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-utils.h" #include "nm-wifi-common.h" #include "nm-wifi-utils.h" @@ -55,7 +55,7 @@ typedef struct { CList aps_lst_head; NMWifiAP * current_ap; GCancellable * cancellable; - NMDeviceWifiCapabilities capabilities; + _NMDeviceWifiCapabilities capabilities; NMActRequestGetSecretsCallId *wifi_secrets_id; guint periodic_scan_id; guint periodic_update_id; @@ -265,7 +265,7 @@ ap_from_network(NMDeviceIwd *self, .bss_path = bss_path, .last_seen_msec = last_seen_msec, .bssid_valid = TRUE, - .mode = NM_802_11_MODE_INFRA, + .mode = _NM_802_11_MODE_INFRA, .rsn_flags = ap_security_flags_from_network_type(type), .ssid = ssid, .signal_percent = nm_wifi_utils_level_to_quality(signal / 100), @@ -812,7 +812,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * NMSettingWirelessSecurity *s_wireless_sec = nm_connection_get_setting_wireless_security(connection); - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) { + if (!(priv->capabilities & _NM_WIFI_DEVICE_CAP_AP)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "device does not support Access Point mode"); @@ -830,7 +830,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * NMSettingWirelessSecurity *s_wireless_sec = nm_connection_get_setting_wireless_security(connection); - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) { + if (!(priv->capabilities & _NM_WIFI_DEVICE_CAP_ADHOC)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "device does not support Ad-Hoc mode"); @@ -1045,16 +1045,15 @@ complete_connection(NMDevice * device, } ssid_utf8 = iwd_ssid_to_str(ssid); - nm_utils_complete_generic( - nm_device_get_platform(device), - connection, - NM_SETTING_WIRELESS_SETTING_NAME, - existing_connections, - ssid_utf8, - ssid_utf8, - NULL, - nm_setting_wireless_get_mac_address(s_wifi) ? NULL : nm_device_get_iface(device), - TRUE); + nm_utils_complete_generic(nm_device_get_platform(device), + connection, + NM_SETTING_WIRELESS_SETTING_NAME, + existing_connections, + ssid_utf8, + ssid_utf8, + NULL, + NULL, + TRUE); if (hidden) g_object_set(s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); @@ -1317,6 +1316,7 @@ static gboolean try_reply_agent_request(NMDeviceIwd * self, NMConnection * connection, GDBusMethodInvocation *invocation, + gboolean allow_existing, const char ** setting_name, const char ** setting_key, gboolean * replied) @@ -1331,56 +1331,64 @@ try_reply_agent_request(NMDeviceIwd * self, *replied = FALSE; if (nm_streq(method_name, "RequestPassphrase")) { - const char *psk; - if (!s_wireless_sec) return FALSE; - psk = nm_setting_wireless_security_get_psk(s_wireless_sec); - if (psk) { - _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the PSK to the IWD Agent"); + if (allow_existing) { + const char *psk = nm_setting_wireless_security_get_psk(s_wireless_sec); - g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", psk)); - *replied = TRUE; - return TRUE; + if (psk) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the PSK to the IWD Agent"); + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", psk)); + *replied = TRUE; + return TRUE; + } } *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; *setting_key = NM_SETTING_WIRELESS_SECURITY_PSK; return TRUE; } else if (nm_streq(method_name, "RequestPrivateKeyPassphrase")) { - const char *password; - if (!s_8021x) return FALSE; - password = nm_setting_802_1x_get_private_key_password(s_8021x); - if (password) { - _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the private key password to the IWD Agent"); + if (allow_existing) { + const char *password = nm_setting_802_1x_get_private_key_password(s_8021x); - g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", password)); - *replied = TRUE; - return TRUE; + if (password) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, + "Returning the private key password to the IWD Agent"); + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", password)); + *replied = TRUE; + return TRUE; + } } *setting_name = NM_SETTING_802_1X_SETTING_NAME; *setting_key = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD; return TRUE; } else if (nm_streq(method_name, "RequestUserNameAndPassword")) { - const char *identity, *password; + const char *identity; if (!s_8021x) return FALSE; identity = nm_setting_802_1x_get_identity(s_8021x); - password = nm_setting_802_1x_get_password(s_8021x); - if (identity && password) { - _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the username and password to the IWD Agent"); - g_dbus_method_invocation_return_value(invocation, - g_variant_new("(ss)", identity, password)); - *replied = TRUE; - return TRUE; + if (allow_existing) { + const char *password = nm_setting_802_1x_get_password(s_8021x); + + if (identity && password) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, + "Returning the username and password to the IWD Agent"); + + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(ss)", identity, password)); + *replied = TRUE; + return TRUE; + } } *setting_name = NM_SETTING_802_1X_SETTING_NAME; @@ -1390,18 +1398,19 @@ try_reply_agent_request(NMDeviceIwd * self, *setting_key = NM_SETTING_802_1X_PASSWORD; return TRUE; } else if (nm_streq(method_name, "RequestUserPassword")) { - const char *password; - if (!s_8021x) return FALSE; - password = nm_setting_802_1x_get_password(s_8021x); - if (password) { - _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the user password to the IWD Agent"); + if (allow_existing) { + const char *password = nm_setting_802_1x_get_password(s_8021x); - g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", password)); - *replied = TRUE; - return TRUE; + if (password) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the user password to the IWD Agent"); + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", password)); + *replied = TRUE; + return TRUE; + } } *setting_name = NM_SETTING_802_1X_SETTING_NAME; @@ -1452,6 +1461,8 @@ wifi_secrets_cb(NMActRequest * req, gboolean replied; NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; + NMIwdNetworkSecurity security; + NMConnection * connection; nm_utils_user_data_unpack(user_data, &self, &invocation); @@ -1484,9 +1495,18 @@ wifi_secrets_cb(NMActRequest * req, goto secrets_error; } + connection = nm_device_get_applied_connection(device); + + if (nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security) + && security == NM_IWD_NETWORK_SECURITY_PSK) { + if (nm_settings_connection_get_timestamp(nm_device_get_settings_connection(device), NULL)) + get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; + } + if (!try_reply_agent_request(self, - nm_act_request_get_applied_connection(req), + connection, invocation, + TRUE, &setting_name, &setting_key, &replied)) @@ -1512,9 +1532,6 @@ wifi_secrets_cb(NMActRequest * req, return; } - if (nm_settings_connection_get_timestamp(nm_act_request_get_settings_connection(req), NULL)) - get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - /* Request further secrets if we still need something */ wifi_secrets_get_one(self, setting_name, get_secret_flags, setting_key, invocation); return; @@ -1606,8 +1623,6 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) dbus_error = g_dbus_error_get_remote_error(error); if (nm_streq0(dbus_error, "net.connman.iwd.Failed")) { - nm_connection_clear_secrets(connection); - /* If secrets were wrong, we'd be getting a net.connman.iwd.Failed */ reason = NM_DEVICE_STATE_REASON_NO_SECRETS; } else if (nm_streq0(dbus_error, "net.connman.iwd.Aborted") && priv->secrets_failed) { @@ -2621,9 +2636,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) switch (prop_id) { case PROP_MODE: if (!priv->current_ap) - g_value_set_uint(value, NM_802_11_MODE_UNKNOWN); + g_value_set_uint(value, _NM_802_11_MODE_UNKNOWN); else if (nm_wifi_ap_is_hotspot(priv->current_ap)) - g_value_set_uint(value, NM_802_11_MODE_AP); + g_value_set_uint(value, _NM_802_11_MODE_AP); else g_value_set_uint(value, nm_wifi_ap_get_mode(priv->current_ap)); @@ -3045,7 +3060,7 @@ nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object) GVariantIter * iter; const char * mode; gboolean powered; - NMDeviceWifiCapabilities capabilities; + _NMDeviceWifiCapabilities capabilities; if (!nm_g_object_ref_set(&priv->dbus_obj, object)) return; @@ -3107,14 +3122,14 @@ nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object) goto error; } - capabilities = NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN; + capabilities = _NM_WIFI_DEVICE_CAP_CIPHER_CCMP | _NM_WIFI_DEVICE_CAP_RSN; g_variant_get(value, "as", &iter); while (g_variant_iter_next(iter, "&s", &mode)) { if (nm_streq(mode, "ap")) - capabilities |= NM_WIFI_DEVICE_CAP_AP; + capabilities |= _NM_WIFI_DEVICE_CAP_AP; else if (nm_streq(mode, "ad-hoc")) - capabilities |= NM_WIFI_DEVICE_CAP_ADHOC; + capabilities |= _NM_WIFI_DEVICE_CAP_ADHOC; } g_variant_iter_free(iter); @@ -3156,8 +3171,11 @@ nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) const char * setting_key; gboolean replied; NMWifiAP * ap; + gboolean allow_existing = FALSE; NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; + NMIwdNetworkSecurity security; + NMConnection * connection; nm_auto_ref_string NMRefString *network_path = NULL; if (!invocation) { @@ -3261,9 +3279,37 @@ nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) /* Otherwise handle as usual */ } + /* Normally for PSK networks require new secret every time IWD asks for + * it. IWD only queries us if it has not saved the PSK (e.g. by policy) + * or a previous attempt has failed with current secrets so it wants a + * fresh value. It doesn't know about agent-owned secrets so whenever + * possible and the PSK is saved and not asked from NM. However if this + * is a new connection it may include all of the needed settings already + * so allow using these, too. Connection timestamp is set after + * activation or after first activation failure (to 0). + * + * For 802.1x, since IWD assumes the network is pre-provisioned by an + * admin and tested, there's no reason for IWD to save secrets in + * the network config file and there's no reason to ask for a new value + * of a saved (i.e. system-owned) secret because it can't be wrong. + * Since NM has a richer set of secret storage options we never specify + * NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW and let + * nm_settings_connection_get_secrets decide. + */ + connection = nm_device_get_applied_connection(device); + + if (nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security) + && security == NM_IWD_NETWORK_SECURITY_PSK) { + if (nm_settings_connection_get_timestamp(nm_device_get_settings_connection(device), NULL)) + get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; + else + allow_existing = TRUE; + } + if (!try_reply_agent_request(self, - nm_device_get_applied_connection(device), + connection, invocation, + allow_existing, &setting_name, &setting_key, &replied)) { @@ -3274,17 +3320,6 @@ nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) if (replied) return TRUE; - /* Normally require new secrets every time IWD asks for them. - * IWD only queries us if it has not saved the secrets (e.g. by policy) - * or a previous attempt has failed with current secrets so it wants - * a fresh set. However if this is a new connection it may include - * all of the needed settings already so allow using these, too. - * Connection timestamp is set after activation or after first - * activation failure (to 0). - */ - if (nm_settings_connection_get_timestamp(nm_device_get_settings_connection(device), NULL)) - get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - nm_device_state_changed(device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NO_SECRETS); wifi_secrets_get_one(self, setting_name, get_secret_flags, setting_key, invocation); @@ -3463,9 +3498,9 @@ nm_device_iwd_class_init(NMDeviceIwdClass *klass) obj_properties[PROP_MODE] = g_param_spec_uint(NM_DEVICE_IWD_MODE, "", "", - NM_802_11_MODE_UNKNOWN, - NM_802_11_MODE_AP, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_UNKNOWN, + _NM_802_11_MODE_AP, + _NM_802_11_MODE_INFRA, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_BITRATE] = g_param_spec_uint(NM_DEVICE_IWD_BITRATE, @@ -3496,7 +3531,7 @@ nm_device_iwd_class_init(NMDeviceIwdClass *klass) "", 0, G_MAXUINT32, - NM_WIFI_DEVICE_CAP_NONE, + _NM_WIFI_DEVICE_CAP_NONE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_SCANNING] = g_param_spec_boolean(NM_DEVICE_IWD_SCANNING, diff --git a/src/core/devices/wifi/nm-device-olpc-mesh.c b/src/core/devices/wifi/nm-device-olpc-mesh.c index af83c4a3..040350d5 100644 --- a/src/core/devices/wifi/nm-device-olpc-mesh.c +++ b/src/core/devices/wifi/nm-device-olpc-mesh.c @@ -28,7 +28,7 @@ #include "nm-setting-connection.h" #include "nm-setting-olpc-mesh.h" #include "nm-manager.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #define _NMLOG_DEVICE_TYPE NMDeviceOlpcMesh #include "devices/nm-device-logging.h" @@ -122,6 +122,17 @@ complete_connection(NMDevice * device, /*****************************************************************************/ +static const char * +get_dhcp_anycast_address(NMDevice *device) +{ + NMSettingOlpcMesh *s_mesh; + + s_mesh = nm_device_get_applied_setting(device, NM_TYPE_SETTING_OLPC_MESH); + return s_mesh ? nm_setting_olpc_mesh_get_dhcp_anycast_address(s_mesh) : NULL; +} + +/*****************************************************************************/ + static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { @@ -178,7 +189,6 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(device); NMSettingOlpcMesh *s_mesh; GBytes * ssid; - const char * anycast_addr; gboolean success; s_mesh = nm_device_get_applied_setting(device, NM_TYPE_SETTING_OLPC_MESH); @@ -197,9 +207,6 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_FAILURE; } - anycast_addr = nm_setting_olpc_mesh_get_dhcp_anycast_address(s_mesh); - nm_device_set_dhcp_anycast_address(device, anycast_addr); - if (!_mesh_set_channel(self, nm_setting_olpc_mesh_get_channel(s_mesh))) { _LOGW(LOGD_WIFI, "Unable to set the mesh channel"); return NM_ACT_STAGE_RETURN_FAILURE; @@ -492,19 +499,15 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_olpc_mesh = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Companion", - "o", - NM_DEVICE_OLPC_MESH_COMPANION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Companion", + "o", + NM_DEVICE_OLPC_MESH_COMPANION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE( "ActiveChannel", "u", NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL), ), ), - .legacy_property_changed = TRUE, }; static void @@ -531,6 +534,7 @@ nm_device_olpc_mesh_class_init(NMDeviceOlpcMeshClass *klass) device_class->act_stage2_config = act_stage2_config; device_class->state_changed = state_changed; device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device; + device_class->get_dhcp_anycast_address = get_dhcp_anycast_address; obj_properties[PROP_COMPANION] = g_param_spec_string(NM_DEVICE_OLPC_MESH_COMPANION, "", diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index fb987600..a8ea2ed7 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -15,16 +15,16 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "nm-act-request.h" -#include "nm-core-internal.h" -#include "nm-glib-aux/nm-ref-string.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-ref-string.h" #include "nm-ip4-config.h" #include "nm-manager.h" #include "nm-manager.h" #include "nm-setting-wifi-p2p.h" #include "nm-utils.h" #include "nm-wifi-p2p-peer.h" -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #include "settings/nm-settings.h" #define _NMLOG_DEVICE_TYPE NMDeviceWifiP2P @@ -1149,7 +1149,6 @@ static const NMDBusInterfaceInfoExtended interface_info_device_wifi_p2p = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Peers", "ao", NM_DEVICE_WIFI_P2P_PEERS), ), ), - .legacy_property_changed = FALSE, }; /*****************************************************************************/ diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index c9655eea..fca2fde5 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -12,11 +12,11 @@ #include #include -#include "nm-glib-aux/nm-ref-string.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-ref-string.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-device-wifi-p2p.h" #include "nm-wifi-ap.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "devices/nm-device.h" #include "devices/nm-device-private.h" #include "nm-dbus-manager.h" @@ -33,13 +33,13 @@ #include "nm-setting-ip4-config.h" #include "nm-ip4-config.h" #include "nm-setting-ip6-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-auth-utils.h" #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" #include "nm-wifi-utils.h" #include "nm-wifi-common.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceWifi @@ -114,11 +114,11 @@ typedef struct { guint wps_timeout_id; guint sup_timeout_id; /* supplicant association timeout */ - NMDeviceWifiCapabilities capabilities; - NMSettingWirelessWakeOnWLan wowlan_restore; + _NMDeviceWifiCapabilities capabilities; + _NMSettingWirelessWakeOnWLan wowlan_restore; NMDeviceWifiP2P *p2p_device; - NM80211Mode mode; + _NM80211Mode mode; guint32 failed_iface_count; gint32 hw_addr_scan_expire; @@ -487,7 +487,7 @@ _scan_notify_allowed(NMDeviceWifi *self, NMTernary do_kickoff) if (!c_list_is_empty(&priv->scanning_prohibited_lst_head)) { /* something prohibits scanning. */ - } else if (NM_IN_SET(priv->mode, NM_802_11_MODE_ADHOC, NM_802_11_MODE_AP)) { + } else if (NM_IN_SET(priv->mode, _NM_802_11_MODE_ADHOC, _NM_802_11_MODE_AP)) { /* Don't scan when a an AP or Ad-Hoc connection is active as it will * disrupt connected clients or peers. */ } else if (NM_IN_SET(state, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_FAILED)) { @@ -678,7 +678,7 @@ update_seen_bssids_cache(NMDeviceWifi *self, NMWifiAP *ap) return; /* Don't cache the BSSID for Ad-Hoc APs */ - if (nm_wifi_ap_get_mode(ap) != NM_802_11_MODE_INFRA) + if (nm_wifi_ap_get_mode(ap) != _NM_802_11_MODE_INFRA) return; if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_ACTIVATED @@ -712,10 +712,11 @@ set_current_ap(NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available_ priv->current_ap = NULL; if (old_ap) { - NM80211Mode mode = nm_wifi_ap_get_mode(old_ap); + _NM80211Mode mode = nm_wifi_ap_get_mode(old_ap); /* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */ - if (NM_IN_SET(mode, NM_802_11_MODE_ADHOC, NM_802_11_MODE_AP) || nm_wifi_ap_get_fake(old_ap)) + if (NM_IN_SET(mode, _NM_802_11_MODE_ADHOC, _NM_802_11_MODE_AP) + || nm_wifi_ap_get_fake(old_ap)) ap_add_remove(self, FALSE, old_ap, recheck_available_connections); g_object_unref(old_ap); } @@ -750,7 +751,7 @@ periodic_update(NMDeviceWifi *self) return; } - if (priv->mode == NM_802_11_MODE_AP) { + if (priv->mode == _NM_802_11_MODE_AP) { /* In AP mode we currently have nothing to do. */ return; } @@ -845,14 +846,14 @@ remove_all_aps(NMDeviceWifi *self) static gboolean wake_on_wlan_restore(NMDeviceWifi *self) { - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSettingWirelessWakeOnWLan w; + NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + _NMSettingWirelessWakeOnWLan w; w = priv->wowlan_restore; - if (w == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) + if (w == _NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) return TRUE; - priv->wowlan_restore = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; + priv->wowlan_restore = _NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; return nm_platform_wifi_set_wake_on_wlan(NM_PLATFORM_GET, nm_device_get_ifindex(NM_DEVICE(self)), w); @@ -937,14 +938,14 @@ deactivate(NMDevice *device) * (usually older ones) don't scan well in adhoc mode. */ if (nm_platform_wifi_get_mode(nm_device_get_platform(device), ifindex) - != NM_802_11_MODE_INFRA) { + != _NM_802_11_MODE_INFRA) { nm_device_take_down(NM_DEVICE(self), TRUE); - nm_platform_wifi_set_mode(nm_device_get_platform(device), ifindex, NM_802_11_MODE_INFRA); + nm_platform_wifi_set_mode(nm_device_get_platform(device), ifindex, _NM_802_11_MODE_INFRA); nm_device_bring_up(NM_DEVICE(self), TRUE, NULL); } - if (priv->mode != NM_802_11_MODE_INFRA) { - priv->mode = NM_802_11_MODE_INFRA; + if (priv->mode != _NM_802_11_MODE_INFRA) { + priv->mode = _NM_802_11_MODE_INFRA; _notify(self, PROP_MODE); } @@ -1010,14 +1011,14 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * /* Early exit if supplicant or device doesn't support requested mode */ mode = nm_setting_wireless_get_mode(s_wireless); if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) { - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) { + if (!(priv->capabilities & _NM_WIFI_DEVICE_CAP_ADHOC)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "the device does not support Ad-Hoc networks"); return FALSE; } } else if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_AP) == 0) { - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) { + if (!(priv->capabilities & _NM_WIFI_DEVICE_CAP_AP)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "the device does not support Access Point mode"); @@ -1034,7 +1035,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } } } else if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_MESH) == 0) { - if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_MESH)) { + if (!(priv->capabilities & _NM_WIFI_DEVICE_CAP_MESH)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "the device does not support Mesh mode"); @@ -1381,8 +1382,8 @@ _hw_addr_set_scanning(NMDeviceWifi *self, gboolean do_reset) now = nm_utils_get_monotonic_timestamp_sec(); if (now >= priv->hw_addr_scan_expire) { - gs_free char *generate_mac_address_mask = NULL; - gs_free char *hw_addr_scan = NULL; + gs_free char *hw_addr_scan = NULL; + const char * generate_mac_address_mask; /* the random MAC address for scanning expires after a while. * @@ -1433,7 +1434,7 @@ ssids_options_to_ptrarray(GVariant *value, GError **error) v = g_variant_get_child_value(value, i); bytes = g_variant_get_fixed_array(v, &len, sizeof(guint8)); - if (len > 32) { + if (len > NM_IW_ESSID_MAX_SIZE) { g_set_error(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_ARGUMENT, @@ -1822,7 +1823,7 @@ _scan_kickoff(NMDeviceWifi *self) strv = g_new(char *, ssids->len + 1u); for (i = 0; i < ssids->len; i++) - strv[i] = _nm_utils_ssid_to_string(ssids->pdata[i]); + strv[i] = _nm_utils_ssid_to_string_gbytes(ssids->pdata[i]); strv[i] = NULL; nm_assert(ssids->len > 0); @@ -1884,13 +1885,13 @@ ap_list_dump(gpointer user_data) _LOGD(LOGD_WIFI_SCAN, "APs: [now:%u.%03u, last:%s]", - (guint)(now_msec / NM_UTILS_MSEC_PER_SEC), - (guint)(now_msec % NM_UTILS_MSEC_PER_SEC), + (guint) (now_msec / NM_UTILS_MSEC_PER_SEC), + (guint) (now_msec % NM_UTILS_MSEC_PER_SEC), priv->scan_last_complete_msec > 0 ? nm_sprintf_buf(str_buf, "%u.%03u", - (guint)(priv->scan_last_complete_msec / NM_UTILS_MSEC_PER_SEC), - (guint)(priv->scan_last_complete_msec % NM_UTILS_MSEC_PER_SEC)) + (guint) (priv->scan_last_complete_msec / NM_UTILS_MSEC_PER_SEC), + (guint) (priv->scan_last_complete_msec % NM_UTILS_MSEC_PER_SEC)) : "-1"); c_list_for_each_entry (ap, &priv->aps_lst_head, aps_lst) _ap_dump(self, LOGL_DEBUG, ap, "dump", now_msec); @@ -1986,19 +1987,19 @@ supplicant_iface_bss_changed_cb(NMSupplicantInterface *iface, /* Let the manager try to fill in the SSID from seen-bssids lists */ ssid = nm_wifi_ap_get_ssid(ap); - if (!ssid || _nm_utils_is_empty_ssid(ssid)) { + if (!ssid || _nm_utils_is_empty_ssid_gbytes(ssid)) { /* Try to fill the SSID from the AP database */ try_fill_ssid_for_hidden_ap(self, ap); ssid = nm_wifi_ap_get_ssid(ap); - if (ssid && !_nm_utils_is_empty_ssid(ssid)) { + if (ssid && !_nm_utils_is_empty_ssid_gbytes(ssid)) { gs_free char *s = NULL; /* Yay, matched it, no longer treat as hidden */ _LOGD(LOGD_WIFI, "matched hidden AP %s => %s", nm_wifi_ap_get_address(ap), - (s = _nm_utils_ssid_to_string(ssid))); + (s = _nm_utils_ssid_to_string_gbytes(ssid))); } else { /* Didn't have an entry for this AP in the database */ _LOGD(LOGD_WIFI, "failed to match hidden AP %s", nm_wifi_ap_get_address(ap)); @@ -2481,9 +2482,9 @@ supplicant_iface_state(NMDeviceWifi * self, _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Stage 2 of 5 (Device Configure) successful. %s %s", - priv->mode == NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" - : "Connected to wireless network", - (ssid_str = _nm_utils_ssid_to_string(ssid))); + priv->mode == _NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" + : "Connected to wireless network", + (ssid_str = _nm_utils_ssid_to_string_gbytes(ssid))); nm_device_activate_schedule_stage3_ip_config_start(device); } else if (devstate == NM_DEVICE_STATE_ACTIVATED) periodic_update(self); @@ -2599,9 +2600,9 @@ supplicant_iface_notify_current_bss(NMSupplicantInterface *iface, _LOGD(LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)", old_bssid ?: "(none)", - (old_ssid_s = _nm_utils_ssid_to_string(old_ssid)), + (old_ssid_s = _nm_utils_ssid_to_string_gbytes(old_ssid)), new_bssid ?: "(none)", - (new_ssid_s = _nm_utils_ssid_to_string(new_ssid))); + (new_ssid_s = _nm_utils_ssid_to_string_gbytes(new_ssid))); if (new_bssid) { /* The new AP could be in a different layer 3 network @@ -2790,21 +2791,21 @@ supplicant_connection_timeout_cb(gpointer user_data) connection = nm_act_request_get_applied_connection(req); g_assert(connection); - if (NM_IN_SET(priv->mode, NM_802_11_MODE_ADHOC, NM_802_11_MODE_MESH, NM_802_11_MODE_AP)) { + if (NM_IN_SET(priv->mode, _NM_802_11_MODE_ADHOC, _NM_802_11_MODE_MESH, _NM_802_11_MODE_AP)) { /* In Ad-Hoc and AP modes there's nothing to check the encryption key * (if any), so supplicant timeouts here are almost certainly the wifi * driver being really stupid. */ _LOGW(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) %s network creation took too long, failing activation", - priv->mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc" : "Hotspot"); + priv->mode == _NM_802_11_MODE_ADHOC ? "Ad-Hoc" : "Hotspot"); nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); return FALSE; } - g_assert(priv->mode == NM_802_11_MODE_INFRA); + g_assert(priv->mode == _NM_802_11_MODE_INFRA); if (priv->ssid_found && nm_connection_get_setting_wireless_security(connection)) { guint64 timestamp = 0; @@ -2956,9 +2957,10 @@ error: static gboolean wake_on_wlan_enable(NMDeviceWifi *self) { - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSettingWirelessWakeOnWLan wowl; - NMSettingWireless * s_wireless; + NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMSettingWirelessWakeOnWLan wowl; + _NMSettingWirelessWakeOnWLan wowl2; + NMSettingWireless * s_wireless; s_wireless = nm_device_get_applied_setting(NM_DEVICE(self), NM_TYPE_SETTING_WIRELESS); if (s_wireless) { @@ -2990,9 +2992,11 @@ wake_on_wlan_enable(NMDeviceWifi *self) goto found; wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; + found: - if (wowl == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) { - priv->wowlan_restore = wowl; + wowl2 = _NM_SETTING_WIRELESS_WAKE_ON_WLAN_CAST(wowl); + if (wowl2 == _NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) { + priv->wowlan_restore = wowl2; return TRUE; } @@ -3001,7 +3005,7 @@ found: return nm_platform_wifi_set_wake_on_wlan(NM_PLATFORM_GET, nm_device_get_ifindex(NM_DEVICE(self)), - wowl); + wowl2); } static NMActStageReturn @@ -3030,16 +3034,16 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) mode = nm_setting_wireless_get_mode(s_wireless); if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) - priv->mode = NM_802_11_MODE_INFRA; + priv->mode = _NM_802_11_MODE_INFRA; else if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) - priv->mode = NM_802_11_MODE_ADHOC; + priv->mode = _NM_802_11_MODE_ADHOC; else if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_AP) == 0) { - priv->mode = NM_802_11_MODE_AP; + priv->mode = _NM_802_11_MODE_AP; /* Scanning not done in AP mode; clear the scan list */ remove_all_aps(self); } else if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_MESH) == 0) - priv->mode = NM_802_11_MODE_MESH; + priv->mode = _NM_802_11_MODE_MESH; _notify(self, PROP_MODE); /* expire the temporary MAC address used during scanning */ @@ -3052,7 +3056,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) } /* AP and Mesh modes never use a specific object or existing scanned AP */ - if (!NM_IN_SET(priv->mode, NM_802_11_MODE_AP, NM_802_11_MODE_MESH)) { + if (!NM_IN_SET(priv->mode, _NM_802_11_MODE_AP, _NM_802_11_MODE_MESH)) { ap_path = nm_active_connection_get_specific_object(NM_ACTIVE_CONNECTION(req)); ap = ap_path ? nm_wifi_ap_lookup_for_device(NM_DEVICE(self), ap_path) : NULL; } @@ -3154,7 +3158,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) NMDeviceWifi * self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); gs_unref_object NMSupplicantConfig *config = NULL; - NM80211Mode ap_mode; + _NM80211Mode ap_mode; NMActRequest * req; NMWifiAP * ap; NMConnection * connection; @@ -3221,10 +3225,11 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) * if the user didn't specify one and we didn't find an AP that matched * the connection, just pick a frequency the device supports. */ - if (NM_IN_SET(ap_mode, NM_802_11_MODE_ADHOC, NM_802_11_MODE_MESH) || nm_wifi_ap_is_hotspot(ap)) + if (NM_IN_SET(ap_mode, _NM_802_11_MODE_ADHOC, _NM_802_11_MODE_MESH) + || nm_wifi_ap_is_hotspot(ap)) ensure_hotspot_frequency(self, s_wireless, ap); - if (ap_mode == NM_802_11_MODE_INFRA) + if (ap_mode == _NM_802_11_MODE_INFRA) set_powersave(device); /* Build up the supplicant configuration */ @@ -3341,7 +3346,7 @@ act_stage4_ip_config_timeout(NMDevice * device, s_ip = nm_connection_get_setting_ip_config(connection, addr_family); may_fail = nm_setting_ip_config_get_may_fail(s_ip); - if (priv->mode == NM_802_11_MODE_AP) + if (priv->mode == _NM_802_11_MODE_AP) goto call_parent; if (may_fail || !is_static_wep(connection)) { @@ -3694,8 +3699,8 @@ nm_device_wifi_init(NMDeviceWifi *self) priv->scan_last_request_started_at_msec = G_MININT64; priv->hidden_probe_scan_warn = TRUE; - priv->mode = NM_802_11_MODE_INFRA; - priv->wowlan_restore = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; + priv->mode = _NM_802_11_MODE_INFRA; + priv->wowlan_restore = _NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; } static void @@ -3706,7 +3711,7 @@ constructed(GObject *object) G_OBJECT_CLASS(nm_device_wifi_parent_class)->constructed(object); - if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP) + if (priv->capabilities & _NM_WIFI_DEVICE_CAP_AP) _LOGI(LOGD_PLATFORM | LOGD_WIFI, "driver supports Access Point (AP) mode"); /* Connect to the supplicant manager */ @@ -3714,7 +3719,7 @@ constructed(GObject *object) } NMDevice * -nm_device_wifi_new(const char *iface, NMDeviceWifiCapabilities capabilities) +nm_device_wifi_new(const char *iface, _NMDeviceWifiCapabilities capabilities) { return g_object_new(NM_TYPE_DEVICE_WIFI, NM_DEVICE_IFACE, @@ -3822,9 +3827,9 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass) obj_properties[PROP_MODE] = g_param_spec_uint(NM_DEVICE_WIFI_MODE, "", "", - NM_802_11_MODE_UNKNOWN, - NM_802_11_MODE_AP, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_UNKNOWN, + _NM_802_11_MODE_AP, + _NM_802_11_MODE_INFRA, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_BITRATE] = g_param_spec_uint(NM_DEVICE_WIFI_BITRATE, @@ -3855,7 +3860,7 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass) "", 0, G_MAXUINT32, - NM_WIFI_DEVICE_CAP_NONE, + _NM_WIFI_DEVICE_CAP_NONE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); obj_properties[PROP_SCANNING] = g_param_spec_boolean(NM_DEVICE_WIFI_SCANNING, diff --git a/src/core/devices/wifi/nm-device-wifi.h b/src/core/devices/wifi/nm-device-wifi.h index d9e9038c..c7ff1a14 100644 --- a/src/core/devices/wifi/nm-device-wifi.h +++ b/src/core/devices/wifi/nm-device-wifi.h @@ -33,7 +33,7 @@ typedef struct _NMDeviceWifiClass NMDeviceWifiClass; GType nm_device_wifi_get_type(void); -NMDevice *nm_device_wifi_new(const char *iface, NMDeviceWifiCapabilities capabilities); +NMDevice *nm_device_wifi_new(const char *iface, _NMDeviceWifiCapabilities capabilities); const CList *_nm_device_wifi_get_aps(NMDeviceWifi *self); diff --git a/src/core/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index 68a74438..56386c57 100644 --- a/src/core/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -8,14 +8,20 @@ #include "nm-iwd-manager.h" #include +#include +#include +#include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-manager.h" #include "nm-device-iwd.h" #include "nm-wifi-utils.h" -#include "nm-glib-aux/nm-random-utils.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-random-utils.h" +#include "libnm-glib-aux/nm-io-utils.h" #include "settings/nm-settings.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/nm-dbus-compat.h" +#include "nm-config.h" /*****************************************************************************/ @@ -28,6 +34,7 @@ typedef struct { typedef struct { GDBusProxy * known_network; NMSettingsConnection *mirror_connection; + const KnownNetworkId *id; } KnownNetworkData; typedef struct { @@ -40,6 +47,8 @@ typedef struct { char * agent_path; GHashTable * known_networks; NMDeviceIwd * last_agent_call_device; + char * last_state_dir; + char * warned_state_dir; } NMIwdManagerPrivate; struct _NMIwdManager { @@ -419,25 +428,94 @@ known_network_update_cb(GObject *source, GAsyncResult *res, gpointer user_data) variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant) { nm_log_warn(LOGD_WIFI, - "Updating %s on IWD known network %s failed: %s", + "iwd: updating %s on IWD known network %s failed: %s", (const char *) user_data, g_dbus_proxy_get_object_path(G_DBUS_PROXY(source)), error->message); } } +static gboolean +iwd_config_write(GKeyFile * config, + const char * filepath, + const struct timespec *mtime, + GError ** error) +{ + gsize length; + gs_free char * data = g_key_file_to_data(config, &length, NULL); + struct timespec times[2] = {{.tv_nsec = UTIME_OMIT}, *mtime}; + + /* Atomically write or replace the file with the right permission bits + * and timestamps set. We rely on the temporary file created by + * nm_utils_file_set_contents having only upper-case letters and digits + * in the last few filename characters -- it cannot end in .open, .psk + * or .8021x. + */ + return nm_utils_file_set_contents(filepath, data, length, 0600, times, NULL, error); +} + +static const char * +get_config_path(NMIwdManager *self) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char * path; + + path = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA); + if (path && path[0] == '\0') { + nm_clear_g_free(&priv->warned_state_dir); + return NULL; + } + + if (!path || nm_streq(path, "auto")) { + path = priv->last_state_dir; + if (!path) { + nm_clear_g_free(&priv->warned_state_dir); + return NULL; + } + } + + if (priv->warned_state_dir && !nm_streq(priv->warned_state_dir, path)) + nm_clear_g_free(&priv->warned_state_dir); + + if (path && (path[0] != '/' || !g_file_test(path, G_FILE_TEST_IS_DIR))) { + if (!priv->warned_state_dir) { + priv->warned_state_dir = g_strdup(path); + _LOGW("IWD StateDirectory '%s' not accessible", priv->warned_state_dir); + } + return NULL; + } + + return path; +} + static void -sett_conn_changed(NMSettingsConnection *sett_conn, guint update_reason, KnownNetworkData *data) +sett_conn_changed(NMSettingsConnection * sett_conn, + guint update_reason, + const KnownNetworkData *data) { NMSettingsConnectionIntFlags flags; - NMConnection * conn = nm_settings_connection_get_connection(sett_conn); - NMSettingConnection * s_conn = nm_connection_get_setting_connection(conn); - gboolean nm_autoconnectable = nm_setting_connection_get_autoconnect(s_conn); - gboolean iwd_autoconnectable = get_property_bool(data->known_network, "AutoConnect", TRUE); + NMConnection * conn = nm_settings_connection_get_connection(sett_conn); + NMSettingConnection * s_conn = nm_connection_get_setting_connection(conn); + NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(conn); + nm_auto_unref_keyfile GKeyFile *iwd_config = NULL; + const char * iwd_dir; + gs_free char * filename = NULL; + gs_free char * full_path = NULL; + gs_free_error GError *error = NULL; + NMIwdNetworkSecurity security; + GBytes * ssid; + const guint8 * ssid_data; + gsize ssid_len; + gboolean removed; + GStatBuf statbuf; + gboolean have_mtime; nm_assert(sett_conn == data->mirror_connection); - if (iwd_autoconnectable == nm_autoconnectable) + if (!NM_FLAGS_ANY(update_reason, + NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET + | NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_SYSTEM_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS)) return; /* If this is a generated connection it may be ourselves updating it */ @@ -445,21 +523,131 @@ sett_conn_changed(NMSettingsConnection *sett_conn, guint update_reason, KnownNet if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) return; + iwd_dir = get_config_path(nm_iwd_manager_get()); + if (!iwd_dir) { + gboolean nm_autoconnectable = nm_setting_connection_get_autoconnect(s_conn); + gboolean iwd_autoconnectable = get_property_bool(data->known_network, "AutoConnect", TRUE); + + if (iwd_autoconnectable != nm_autoconnectable) { + nm_log_dbg(LOGD_WIFI, + "iwd: updating AutoConnect on known network at %s based on connection %s", + g_dbus_proxy_get_object_path(data->known_network), + nm_settings_connection_get_id(data->mirror_connection)); + g_dbus_proxy_call(data->known_network, + DBUS_INTERFACE_PROPERTIES ".Set", + g_variant_new("(ssv)", + NM_IWD_KNOWN_NETWORK_INTERFACE, + "AutoConnect", + g_variant_new_boolean(nm_autoconnectable)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + known_network_update_cb, + "AutoConnect"); + } + + return; + } + + /* If the SSID and the security type in the NMSettingsConnection haven't + * changed, we just need to overwrite the original IWD config file. + * Otherwise we need to call Forget on the original KnownNetwork or + * remove its file. IWD will have to delete one D-Bus object and + * create another anyway because the SSID and security type are in the + * D-Bus object path, so no point renaming the file. + */ + ssid = nm_setting_wireless_get_ssid(s_wifi); + ssid_data = ssid ? g_bytes_get_data(ssid, &ssid_len) : NULL; + removed = FALSE; + have_mtime = FALSE; + + if (!nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &security) + || security != data->id->security || !ssid_data || ssid_len != strlen(data->id->name) + || memcmp(ssid_data, data->id->name, ssid_len)) { + gs_free char *orig_filename = + nm_wifi_utils_get_iwd_config_filename(data->id->name, -1, data->id->security); + gs_free char *orig_full_path = g_strdup_printf("%s/%s", iwd_dir, orig_filename); + + if (g_stat(orig_full_path, &statbuf) == 0) + have_mtime = TRUE; + + if (g_remove(orig_full_path) == 0) + nm_log_dbg(LOGD_WIFI, "iwd: profile at %s removed", orig_full_path); + else if (errno != ENOENT) + nm_log_dbg(LOGD_WIFI, + "iwd: profile at %s not removed: %s (%i)", + orig_full_path, + strerror(errno), + errno); + + removed = TRUE; + } + + if (!nm_streq(nm_settings_connection_get_connection_type(sett_conn), "802-11-wireless") + || !s_wifi) + return; + + /* If the connection has any permissions other than the default we don't + * want to save it as an IWD profile. IWD will make it available for + * everybody to attempt a connection, remove, or toggle "autoconnectable". + */ + if (s_conn && nm_setting_connection_get_num_permissions(s_conn)) { + nm_log_dbg( + LOGD_WIFI, + "iwd: changed Wi-Fi connection %s not mirrored as IWD profile because of non-default " + "permissions", + nm_settings_connection_get_id(sett_conn)); + return; + } + + iwd_config = nm_wifi_utils_connection_to_iwd_config(conn, &filename, &error); + if (!iwd_config) { + /* The error message here is not translated and it only goes in + * the logs. + */ + nm_log_dbg(LOGD_WIFI, + "iwd: changed Wi-Fi connection %s not mirrored as IWD profile: %s", + nm_settings_connection_get_id(sett_conn), + error->message); + return; + } + + full_path = g_strdup_printf("%s/%s", iwd_dir, filename); + if (removed && g_file_test(full_path, G_FILE_TEST_EXISTS)) { + nm_log_dbg(LOGD_WIFI, + "iwd: changed Wi-Fi connection %s not mirrored as IWD profile because %s " + "already exists", + nm_settings_connection_get_id(sett_conn), + full_path); + return; + } + + if (!removed && g_stat(full_path, &statbuf) == 0) + have_mtime = TRUE; + + /* If modifying an existing network try to preserve the file mtime, + * otherwise use a small non-zero timespec value to signal that the + * network is autoconnectable (according to its AutoConnect value) + * but hasn't recently been connected to and thus shouldn't be + * prioritized by autoconnect. + */ + if (!have_mtime) { + statbuf.st_mtim.tv_sec = 1; + statbuf.st_mtim.tv_nsec = 0; + } + + if (!iwd_config_write(iwd_config, full_path, &statbuf.st_mtim, &error)) { + nm_log_dbg(LOGD_WIFI, + "iwd: changed Wi-Fi connection %s not mirrored as IWD profile: save error: %s", + nm_settings_connection_get_id(sett_conn), + error->message); + return; + } + nm_log_dbg(LOGD_WIFI, - "Updating AutoConnect on known network at %s based on connection %s", - g_dbus_proxy_get_object_path(data->known_network), - nm_settings_connection_get_id(data->mirror_connection)); - g_dbus_proxy_call(data->known_network, - DBUS_INTERFACE_PROPERTIES ".Set", - g_variant_new("(ssv)", - NM_IWD_KNOWN_NETWORK_INTERFACE, - "AutoConnect", - g_variant_new_boolean(nm_autoconnectable)), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - known_network_update_cb, - "AutoConnect"); + "iwd: changed Wi-Fi connection %s mirrored as IWD profile %s", + nm_settings_connection_get_id(sett_conn), + full_path); } /* Look up an existing NMSettingsConnection for a network that has been @@ -590,8 +778,10 @@ mirror_connection(NMIwdManager * self, NULL); g_object_set(G_OBJECT(s_wifi), NM_SETTING_WIRELESS_HIDDEN, hidden, NULL); } else { - KnownNetworkData data = {known_network, settings_connection}; - sett_conn_changed(settings_connection, 0, &data); + KnownNetworkData data = {known_network, settings_connection, id}; + sett_conn_changed(settings_connection, + NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET, + &data); } } @@ -621,7 +811,7 @@ mirror_connection(NMIwdManager * self, NM_SETTING_CONNECTION_ID, id->name, NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_buf(uuid), + nm_uuid_generate_random_str_arr(uuid), NM_SETTING_CONNECTION_AUTOCONNECT, autoconnectable, NULL); @@ -779,6 +969,7 @@ interface_added(GDBusObjectManager *object_manager, } else { data = g_slice_new0(KnownNetworkData); data->known_network = g_object_ref(proxy); + data->id = id; g_hash_table_insert(priv->known_networks, id, data); } @@ -907,6 +1098,9 @@ connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpoint const guint8 * ssid_bytes; gsize ssid_len; NMSettingsConnection *new_mirror_conn; + const char * iwd_dir; + gs_free char * filename = NULL; + gs_free char * full_path = NULL; if (!nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &id.security)) return; @@ -923,8 +1117,12 @@ connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpoint ssid_buf[ssid_len] = '\0'; id.name = ssid_buf; data = g_hash_table_lookup(priv->known_networks, &id); - if (!data) - return; + if (!data) { + if (!g_utf8_validate((const char *) ssid_bytes, ssid_len, NULL)) + return; + + goto try_delete_file; + } if (data->mirror_connection != sett_conn) return; @@ -941,7 +1139,7 @@ connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpoint } if (!priv->running) - return; + goto try_delete_file; g_dbus_proxy_call(data->known_network, "Forget", @@ -951,6 +1149,91 @@ connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpoint NULL, NULL, NULL); + return; + +try_delete_file: + if (mirror_connection(self, &id, FALSE, NULL)) + return; + + iwd_dir = get_config_path(self); + if (!iwd_dir) + return; + + filename = nm_wifi_utils_get_iwd_config_filename(id.name, ssid_len, id.security); + full_path = g_strdup_printf("%s/%s", iwd_dir, filename); + if (g_remove(full_path) == 0) + _LOGD("IWD profile at %s removed", full_path); + else if (errno != ENOENT) + _LOGD("IWD profile at %s not removed: %s (%i)", full_path, strerror(errno), errno); +} + +static void +connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer user_data) +{ + NMIwdManager * self = user_data; + NMConnection * conn = nm_settings_connection_get_connection(sett_conn); + NMSettingConnection *s_conn = nm_connection_get_setting_connection(conn); + const char * iwd_dir; + gs_free char * filename = NULL; + gs_free char * full_path = NULL; + gs_free_error GError *error = NULL; + nm_auto_unref_keyfile GKeyFile *iwd_config = NULL; + NMSettingsConnectionIntFlags flags; + + if (!nm_streq(nm_settings_connection_get_connection_type(sett_conn), "802-11-wireless")) + return; + + iwd_dir = get_config_path(self); + if (!iwd_dir) + return; + + /* If this is a generated connection it may be ourselves creating it and + * directly assigning it to a KnownNetwork's .mirror_connection. + */ + flags = nm_settings_connection_get_flags(sett_conn); + if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) + return; + + /* If the connection has any permissions other than the default we don't + * want to save it as an IWD profile. IWD will make it available for + * everybody to attempt a connection, remove, or toggle "autoconnectable". + */ + if (s_conn && nm_setting_connection_get_num_permissions(s_conn)) { + _LOGD("New Wi-Fi connection %s not mirrored as IWD profile because of non-default " + "permissions", + nm_settings_connection_get_id(sett_conn)); + return; + } + + iwd_config = nm_wifi_utils_connection_to_iwd_config(conn, &filename, &error); + if (!iwd_config) { + /* The error message here is not translated and it only goes in + * the logs. + */ + _LOGD("New Wi-Fi connection %s not mirrored as IWD profile: %s", + nm_settings_connection_get_id(sett_conn), + error->message); + return; + } + + full_path = g_strdup_printf("%s/%s", iwd_dir, filename); + if (g_file_test(full_path, G_FILE_TEST_EXISTS)) { + _LOGD("New Wi-Fi connection %s not mirrored as IWD profile because %s already exists", + nm_settings_connection_get_id(sett_conn), + full_path); + return; + } + + if (!g_key_file_save_to_file(iwd_config, full_path, &error)) { + _LOGD("New Wi-Fi connection %s not mirrored as IWD profile: save error: %s", + nm_settings_connection_get_id(sett_conn), + error->message); + return; + } + + _LOGD("New Wi-Fi connection %s mirrored as IWD profile %s", + nm_settings_connection_get_id(sett_conn), + full_path); } static gboolean @@ -1115,7 +1398,7 @@ device_removed(NMManager *manager, NMDevice *device, gpointer user_data) static int object_compare_interfaces(gconstpointer a, gconstpointer b) { - static const char *interface_order[] = { + static const char *const interface_order[] = { NM_IWD_KNOWN_NETWORK_INTERFACE, NM_IWD_NETWORK_INTERFACE, NM_IWD_DEVICE_INTERFACE, @@ -1145,6 +1428,56 @@ object_compare_interfaces(gconstpointer a, gconstpointer b) return rank_a - rank_b; } +static void +get_daemon_info_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMIwdManager * self = user_data; + NMIwdManagerPrivate *priv; + gs_unref_variant GVariant *properties = NULL; + gs_free_error GError *error = NULL; + GVariantIter * properties_iter; + const char * key; + GVariant * value; + + properties = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!properties) { + if (nm_utils_error_is_cancelled(error)) + return; + + nm_log_warn(LOGD_WIFI, "iwd: Daemon.GetInfo() failed: %s", error->message); + return; + } + + priv = NM_IWD_MANAGER_GET_PRIVATE(self); + + if (!g_variant_is_of_type(properties, G_VARIANT_TYPE("(a{sv})"))) { + _LOGE("Daemon.GetInfo returned type %s instead of (a{sv})", + g_variant_get_type_string(properties)); + return; + } + + g_variant_get(properties, "(a{sv})", &properties_iter); + + while (g_variant_iter_next(properties_iter, "{&sv}", &key, &value)) { + if (nm_streq(key, "StateDirectory")) { + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + _LOGE("Daemon.GetInfo property %s is typed '%s' instead of 's'", + key, + g_variant_get_type_string(value)); + goto next; + } + + nm_clear_g_free(&priv->last_state_dir); + priv->last_state_dir = g_variant_dup_string(value, NULL); + } + +next: + g_variant_unref(value); + } + + g_variant_iter_free(properties_iter); +} + static void got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) { @@ -1182,7 +1515,8 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) } if (_om_has_name_owner(object_manager)) { - GList *objects, *iter; + GList * objects, *iter; + gs_unref_object GDBusInterface *daemon = NULL; priv->running = true; @@ -1208,6 +1542,19 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) if (priv->agent_id) register_agent(self); + + daemon = g_dbus_object_manager_get_interface(object_manager, + "/net/connman/iwd", /* IWD 1.15+ */ + NM_IWD_DAEMON_INTERFACE); + if (daemon) + g_dbus_proxy_call(G_DBUS_PROXY(daemon), + "GetInfo", + g_variant_new("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->cancellable, + get_daemon_info_cb, + self); } } @@ -1305,11 +1652,31 @@ nm_iwd_manager_init(NMIwdManager *self) g_signal_connect(priv->manager, NM_MANAGER_DEVICE_ADDED, G_CALLBACK(device_added), self); g_signal_connect(priv->manager, NM_MANAGER_DEVICE_REMOVED, G_CALLBACK(device_removed), self); + /* The current logic is that we track all creations and removals but + * for modifications we only listen to those connections that are + * currently a KnownNetwork's mirror_connection. There may be multiple + * NMSettingsConnections referring to the same SSID+Security type tuple + * so to the same KnownNetwork. So to make connection profile editing + * work at least for the simple cases, we track one NMSettingsConnection + * out of those, and we map its changes to the IWD KnownNetwork. + * + * When an NMSettingsConnection is created by a user for a completely + * new network and the settings are compatible with IWD, we create an + * IWD KnownNetwork config file for it. IWD will notice that and a + * KnownNetwork objects pops up on D-Bus. We look up a suitable + * mirror_connection for it and only then subscribe to modification + * signals. There are various different ways that this could be done, + * it's not clear which one's the best. + */ priv->settings = g_object_ref(NM_SETTINGS_GET); g_signal_connect(priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, G_CALLBACK(connection_removed), self); + g_signal_connect(priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_ADDED, + G_CALLBACK(connection_added), + self); priv->cancellable = g_cancellable_new(); @@ -1348,6 +1715,9 @@ dispose(GObject *object) priv->last_agent_call_device = NULL; + nm_clear_g_free(&priv->last_state_dir); + nm_clear_g_free(&priv->warned_state_dir); + G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object); } diff --git a/src/core/devices/wifi/nm-iwd-manager.h b/src/core/devices/wifi/nm-iwd-manager.h index 466f67c7..e794e661 100644 --- a/src/core/devices/wifi/nm-iwd-manager.h +++ b/src/core/devices/wifi/nm-iwd-manager.h @@ -13,6 +13,7 @@ #define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM #define NM_IWD_SERVICE "net.connman.iwd" +#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon" #define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager" #define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter" #define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device" diff --git a/src/core/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index 08fa10ec..20ed6833 100644 --- a/src/core/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -13,13 +13,13 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" -#include "nm-glib-aux/nm-ref-string.h" +#include "libnm-glib-aux/nm-ref-string.h" #include "nm-setting-wireless.h" #include "nm-utils.h" #include "nm-wifi-utils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "supplicant/nm-supplicant-interface.h" #define PROTO_WPA "wpa" @@ -41,12 +41,12 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMWifiAP, struct _NMWifiAPPrivate { /* Scanned or cached values */ - GBytes * ssid; - char * address; - NM80211Mode mode; - guint8 strength; - guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ - guint32 max_bitrate; /* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ + GBytes * ssid; + char * address; + _NM80211Mode mode; + guint8 strength; + guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ + guint32 max_bitrate; /* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ gint64 last_seen_msec; /* Timestamp when the AP was seen lastly (in nm_utils_get_monotonic_timestamp_*() scale). @@ -98,7 +98,7 @@ nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid) } l = g_bytes_get_size(ssid); - if (l == 0 || l > 32) + if (l == 0 || l > NM_IW_ESSID_MAX_SIZE) g_return_val_if_reached(FALSE); priv = NM_WIFI_AP_GET_PRIVATE(ap); @@ -191,24 +191,24 @@ nm_wifi_ap_set_address(NMWifiAP *ap, const char *addr) return nm_wifi_ap_set_address_bin(ap, &addr_buf); } -NM80211Mode +_NM80211Mode nm_wifi_ap_get_mode(NMWifiAP *ap) { - g_return_val_if_fail(NM_IS_WIFI_AP(ap), NM_802_11_MODE_UNKNOWN); + g_return_val_if_fail(NM_IS_WIFI_AP(ap), _NM_802_11_MODE_UNKNOWN); return NM_WIFI_AP_GET_PRIVATE(ap)->mode; } static gboolean -nm_wifi_ap_set_mode(NMWifiAP *ap, NM80211Mode mode) +nm_wifi_ap_set_mode(NMWifiAP *ap, _NM80211Mode mode) { NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(ap); nm_assert(NM_IN_SET(mode, - NM_802_11_MODE_UNKNOWN, - NM_802_11_MODE_ADHOC, - NM_802_11_MODE_INFRA, - NM_802_11_MODE_MESH)); + _NM_802_11_MODE_UNKNOWN, + _NM_802_11_MODE_ADHOC, + _NM_802_11_MODE_INFRA, + _NM_802_11_MODE_MESH)); if (priv->mode != mode) { priv->mode = mode; @@ -513,34 +513,35 @@ nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64 nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - g_snprintf(str_buf, - buf_len, - "%17s %-35s [ %c %3u %3u%% %c%c %c%c W:%04X R:%04X ] %s sup:%s [nm:%s]", - priv->address ?: "(none)", - (ssid_to_free = _nm_utils_ssid_to_string(priv->ssid)), - (priv->mode == NM_802_11_MODE_ADHOC - ? '*' - : (priv->hotspot - ? '#' - : (priv->fake ? 'f' : (priv->mode == NM_802_11_MODE_MESH ? 'm' : 'a')))), - chan, - priv->strength, - priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : '_', - priv->metered ? 'M' : '_', - priv->flags & NM_802_11_AP_FLAGS_WPS ? 'W' : '_', - priv->flags & NM_802_11_AP_FLAGS_WPS_PIN - ? 'p' - : (priv->flags & NM_802_11_AP_FLAGS_WPS_PBC ? '#' : '_'), - priv->wpa_flags & 0xFFFF, - priv->rsn_flags & 0xFFFF, - priv->last_seen_msec != G_MININT64 - ? nm_sprintf_buf(str_buf_ts, - "%3u.%03us", - (guint)((now_msec - priv->last_seen_msec) / 1000), - (guint)((now_msec - priv->last_seen_msec) % 1000)) - : " ", - supplicant_id, - export_path); + g_snprintf( + str_buf, + buf_len, + "%17s %-35s [ %c %3u %3u%% %c%c %c%c W:%04X R:%04X ] %s sup:%s [nm:%s]", + priv->address ?: "(none)", + (ssid_to_free = _nm_utils_ssid_to_string_gbytes(priv->ssid)), + (priv->mode == _NM_802_11_MODE_ADHOC + ? '*' + : (priv->hotspot + ? '#' + : (priv->fake ? 'f' : (priv->mode == _NM_802_11_MODE_MESH ? 'm' : 'a')))), + chan, + priv->strength, + priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : '_', + priv->metered ? 'M' : '_', + priv->flags & NM_802_11_AP_FLAGS_WPS ? 'W' : '_', + priv->flags & NM_802_11_AP_FLAGS_WPS_PIN + ? 'p' + : (priv->flags & NM_802_11_AP_FLAGS_WPS_PBC ? '#' : '_'), + priv->wpa_flags & 0xFFFF, + priv->rsn_flags & 0xFFFF, + priv->last_seen_msec != G_MININT64 + ? nm_sprintf_buf(str_buf_ts, + "%3u.%03us", + (guint) ((now_msec - priv->last_seen_msec) / 1000), + (guint) ((now_msec - priv->last_seen_msec) % 1000)) + : " ", + supplicant_id, + export_path); return str_buf; } @@ -589,13 +590,13 @@ nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection) mode = nm_setting_wireless_get_mode(s_wireless); if (mode) { - if (!strcmp(mode, "infrastructure") && (priv->mode != NM_802_11_MODE_INFRA)) + if (!strcmp(mode, "infrastructure") && (priv->mode != _NM_802_11_MODE_INFRA)) return FALSE; - if (!strcmp(mode, "adhoc") && (priv->mode != NM_802_11_MODE_ADHOC)) + if (!strcmp(mode, "adhoc") && (priv->mode != _NM_802_11_MODE_ADHOC)) return FALSE; - if (!strcmp(mode, "ap") && (priv->mode != NM_802_11_MODE_INFRA || priv->hotspot != TRUE)) + if (!strcmp(mode, "ap") && (priv->mode != _NM_802_11_MODE_INFRA || priv->hotspot != TRUE)) return FALSE; - if (!strcmp(mode, "mesh") && (priv->mode != NM_802_11_MODE_MESH)) + if (!strcmp(mode, "mesh") && (priv->mode != _NM_802_11_MODE_MESH)) return FALSE; } @@ -624,7 +625,7 @@ nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection) priv->flags, priv->wpa_flags, priv->rsn_flags, - priv->mode); + NM_802_11_MODE_CAST(priv->mode)); } gboolean @@ -713,7 +714,7 @@ nm_wifi_ap_init(NMWifiAP *self) c_list_init(&self->aps_lst); - priv->mode = NM_802_11_MODE_INFRA; + priv->mode = _NM_802_11_MODE_INFRA; priv->flags = NM_802_11_AP_FLAGS_NONE; priv->wpa_flags = NM_802_11_AP_SEC_NONE; priv->rsn_flags = NM_802_11_AP_SEC_NONE; @@ -758,19 +759,19 @@ nm_wifi_ap_new_fake_from_connection(NMConnection *connection) mode = nm_setting_wireless_get_mode(s_wireless); if (mode) { if (!strcmp(mode, "infrastructure")) - nm_wifi_ap_set_mode(ap, NM_802_11_MODE_INFRA); + nm_wifi_ap_set_mode(ap, _NM_802_11_MODE_INFRA); else if (!strcmp(mode, "adhoc")) { - nm_wifi_ap_set_mode(ap, NM_802_11_MODE_ADHOC); + nm_wifi_ap_set_mode(ap, _NM_802_11_MODE_ADHOC); adhoc = TRUE; } else if (!strcmp(mode, "mesh")) - nm_wifi_ap_set_mode(ap, NM_802_11_MODE_MESH); + nm_wifi_ap_set_mode(ap, _NM_802_11_MODE_MESH); else if (!strcmp(mode, "ap")) { - nm_wifi_ap_set_mode(ap, NM_802_11_MODE_INFRA); + nm_wifi_ap_set_mode(ap, _NM_802_11_MODE_INFRA); NM_WIFI_AP_GET_PRIVATE(ap)->hotspot = TRUE; } else goto error; } else { - nm_wifi_ap_set_mode(ap, NM_802_11_MODE_INFRA); + nm_wifi_ap_set_mode(ap, _NM_802_11_MODE_INFRA); } band = nm_setting_wireless_get_band(s_wireless); @@ -861,27 +862,21 @@ finalize(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_access_point = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_ACCESS_POINT, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Flags", "u", NM_WIFI_AP_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WpaFlags", "u", NM_WIFI_AP_WPA_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("RsnFlags", "u", NM_WIFI_AP_RSN_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ssid", "ay", NM_WIFI_AP_SSID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Frequency", - "u", - NM_WIFI_AP_FREQUENCY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_WIFI_AP_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "u", NM_WIFI_AP_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("MaxBitrate", - "u", - NM_WIFI_AP_MAX_BITRATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Strength", "y", NM_WIFI_AP_STRENGTH), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("LastSeen", - "i", - NM_WIFI_AP_LAST_SEEN), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Flags", "u", NM_WIFI_AP_FLAGS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WpaFlags", "u", NM_WIFI_AP_WPA_FLAGS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RsnFlags", "u", NM_WIFI_AP_RSN_FLAGS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ssid", "ay", NM_WIFI_AP_SSID), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Frequency", "u", NM_WIFI_AP_FREQUENCY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_WIFI_AP_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "u", NM_WIFI_AP_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("MaxBitrate", + "u", + NM_WIFI_AP_MAX_BITRATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Strength", "y", NM_WIFI_AP_STRENGTH), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LastSeen", + "i", + NM_WIFI_AP_LAST_SEEN), ), ), }; static void @@ -955,9 +950,9 @@ nm_wifi_ap_class_init(NMWifiAPClass *ap_class) obj_properties[PROP_MODE] = g_param_spec_uint(NM_WIFI_AP_MODE, "", "", - NM_802_11_MODE_ADHOC, - NM_802_11_MODE_INFRA, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_ADHOC, + _NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_MAX_BITRATE] = g_param_spec_uint(NM_WIFI_AP_MAX_BITRATE, diff --git a/src/core/devices/wifi/nm-wifi-ap.h b/src/core/devices/wifi/nm-wifi-ap.h index bdd72415..bffd28a8 100644 --- a/src/core/devices/wifi/nm-wifi-ap.h +++ b/src/core/devices/wifi/nm-wifi-ap.h @@ -10,6 +10,7 @@ #include "nm-dbus-object.h" #include "nm-dbus-interface.h" #include "nm-connection.h" +#include "libnm-base/nm-base.h" #define NM_TYPE_WIFI_AP (nm_wifi_ap_get_type()) #define NM_WIFI_AP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_AP, NMWifiAP)) @@ -69,7 +70,7 @@ gboolean nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid); const char * nm_wifi_ap_get_address(const NMWifiAP *ap); gboolean nm_wifi_ap_set_address(NMWifiAP *ap, const char *addr); gboolean nm_wifi_ap_set_address_bin(NMWifiAP *ap, const NMEtherAddr *addr); -NM80211Mode nm_wifi_ap_get_mode(NMWifiAP *ap); +_NM80211Mode nm_wifi_ap_get_mode(NMWifiAP *ap); gboolean nm_wifi_ap_is_hotspot(NMWifiAP *ap); gint8 nm_wifi_ap_get_strength(NMWifiAP *ap); gboolean nm_wifi_ap_set_strength(NMWifiAP *ap, gint8 strength); diff --git a/src/core/devices/wifi/nm-wifi-common.c b/src/core/devices/wifi/nm-wifi-common.c index c715c07c..b98ef222 100644 --- a/src/core/devices/wifi/nm-wifi-common.c +++ b/src/core/devices/wifi/nm-wifi-common.c @@ -146,31 +146,25 @@ const NMDBusInterfaceInfoExtended nm_interface_info_device_wireless = { .in_args = NM_DEFINE_GDBUS_ARG_INFOS( NM_DEFINE_GDBUS_ARG_INFO("options", "a{sv}"), ), ), .handle = impl_device_wifi_request_scan, ), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &nm_signal_info_wireless_access_point_added, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_wireless_access_point_added, &nm_signal_info_wireless_access_point_removed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PermHwAddress", - "s", - NM_DEVICE_PERM_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "u", NM_DEVICE_WIFI_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Bitrate", - "u", - NM_DEVICE_WIFI_BITRATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AccessPoints", - "ao", - NM_DEVICE_WIFI_ACCESS_POINTS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActiveAccessPoint", - "o", - NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WirelessCapabilities", - "u", - NM_DEVICE_WIFI_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PermHwAddress", + "s", + NM_DEVICE_PERM_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "u", NM_DEVICE_WIFI_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Bitrate", "u", NM_DEVICE_WIFI_BITRATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AccessPoints", + "ao", + NM_DEVICE_WIFI_ACCESS_POINTS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ActiveAccessPoint", + "o", + NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WirelessCapabilities", + "u", + NM_DEVICE_WIFI_CAPABILITIES), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LastScan", "x", NM_DEVICE_WIFI_LAST_SCAN), ), ), - .legacy_property_changed = TRUE, }; diff --git a/src/core/devices/wifi/nm-wifi-factory.c b/src/core/devices/wifi/nm-wifi-factory.c index 40375e1c..d2269c74 100644 --- a/src/core/devices/wifi/nm-wifi-factory.c +++ b/src/core/devices/wifi/nm-wifi-factory.c @@ -15,7 +15,7 @@ #include "nm-device-olpc-mesh.h" #include "nm-device-iwd.h" #include "settings/nm-settings-connection.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-config.h" /*****************************************************************************/ @@ -74,7 +74,8 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - gs_free char *backend = NULL; + gs_free char *backend_free = NULL; + const char * backend; g_return_val_if_fail(iface != NULL, NULL); g_return_val_if_fail(plink != NULL, NULL); @@ -89,7 +90,7 @@ create_device(NMDeviceFactory * factory, plink, "wifi", NULL); - nm_strstrip(backend); + backend = nm_strstrip_avoid_copy_a(300, backend, &backend_free); nm_log_dbg(LOGD_PLATFORM | LOGD_WIFI, "(%s) config: backend is %s%s%s%s", @@ -97,9 +98,9 @@ create_device(NMDeviceFactory * factory, NM_PRINT_FMT_QUOTE_STRING(backend), WITH_IWD ? " (iwd support enabled)" : ""); if (!backend || !g_ascii_strcasecmp(backend, "wpa_supplicant")) { - NMDevice * device; - NMDeviceWifiCapabilities capabilities; - NM80211Mode mode; + NMDevice * device; + _NMDeviceWifiCapabilities capabilities; + _NM80211Mode mode; if (!nm_platform_wifi_get_capabilities(NM_PLATFORM_GET, plink->ifindex, &capabilities)) { nm_log_warn(LOGD_PLATFORM | LOGD_WIFI, @@ -114,7 +115,7 @@ create_device(NMDeviceFactory * factory, * them if/when they change to a handled type. */ mode = nm_platform_wifi_get_mode(NM_PLATFORM_GET, plink->ifindex); - if (mode == NM_802_11_MODE_UNKNOWN) { + if (mode == _NM_802_11_MODE_UNKNOWN) { *out_ignore = TRUE; return NULL; } diff --git a/src/core/devices/wifi/nm-wifi-p2p-peer.c b/src/core/devices/wifi/nm-wifi-p2p-peer.c index 8488f32d..433c2833 100644 --- a/src/core/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.c @@ -12,13 +12,13 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" -#include "nm-glib-aux/nm-ref-string.h" +#include "libnm-glib-aux/nm-ref-string.h" #include "nm-setting-wireless.h" #include "nm-utils.h" #include "nm-wifi-utils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "supplicant/nm-supplicant-types.h" /*****************************************************************************/ @@ -608,7 +608,6 @@ static const NMDBusInterfaceInfoExtended interface_info_p2p_peer = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("LastSeen", "i", NM_WIFI_P2P_PEER_LAST_SEEN), ), ), - .legacy_property_changed = FALSE, }; static void diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index aed236cc..15ced990 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -7,10 +7,14 @@ #include "nm-wifi-utils.h" +#include +#include #include #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-base/nm-config-base.h" static gboolean verify_no_wep(NMSettingWirelessSecurity *s_wsec, const char *tag, GError **error) @@ -526,7 +530,7 @@ verify_adhoc(NMSettingWirelessSecurity *s_wsec, gboolean nm_wifi_utils_complete_connection(GBytes * ap_ssid, const char * bssid, - NM80211Mode ap_mode, + _NM80211Mode ap_mode, guint32 ap_freq, guint32 ap_flags, guint32 ap_wpa_flags, @@ -575,14 +579,14 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, /* Make sure the supplied mode matches the AP's */ if (!strcmp(mode, NM_SETTING_WIRELESS_MODE_INFRA) || !strcmp(mode, NM_SETTING_WIRELESS_MODE_AP)) { - if (ap_mode == NM_802_11_MODE_INFRA) + if (ap_mode == _NM_802_11_MODE_INFRA) valid = TRUE; } else if (!strcmp(mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { - if (ap_mode == NM_802_11_MODE_ADHOC) + if (ap_mode == _NM_802_11_MODE_ADHOC) valid = TRUE; adhoc = TRUE; } else if (!strcmp(mode, NM_SETTING_WIRELESS_MODE_MESH)) { - if (ap_mode == NM_802_11_MODE_MESH) + if (ap_mode == _NM_802_11_MODE_MESH) valid = TRUE; mesh = TRUE; } @@ -600,10 +604,10 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, } } else { mode = NM_SETTING_WIRELESS_MODE_INFRA; - if (ap_mode == NM_802_11_MODE_ADHOC) { + if (ap_mode == _NM_802_11_MODE_ADHOC) { mode = NM_SETTING_WIRELESS_MODE_ADHOC; adhoc = TRUE; - } else if (ap_mode == NM_802_11_MODE_MESH) { + } else if (ap_mode == _NM_802_11_MODE_MESH) { mode = NM_SETTING_WIRELESS_MODE_MESH; mesh = TRUE; } @@ -810,15 +814,24 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, * setting. Since there's so much configuration required for it, there's * no way it can be automatically completed. */ - } else if ((key_mgmt && !strcmp(key_mgmt, "sae")) - || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) { + } else if (nm_streq0(key_mgmt, "wpa-psk") + || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE + && (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK + || ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK))) { + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + "open", + NULL); + } else if (nm_streq0(key_mgmt, "sae") || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) { g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", NULL); - } else if ((key_mgmt && !strcmp(key_mgmt, "owe")) + } else if (nm_streq0(key_mgmt, "owe") || NM_FLAGS_ANY(ap_rsn_flags, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { g_object_set(s_wsec, @@ -827,9 +840,8 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", NULL); - } else if ((key_mgmt && !strcmp(key_mgmt, "wpa-psk")) - || (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { + } else if (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK + || ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) { g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", @@ -839,7 +851,7 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, /* Leave proto/pairwise/group as client set them; if they are unset the * supplicant will figure out the best combination at connect time. */ - } else if ((key_mgmt && !strcmp(key_mgmt, "wpa-eap-suite-b-192")) + } else if (nm_streq0(key_mgmt, "wpa-eap-suite-b-192") || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)) { g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, @@ -943,3 +955,865 @@ nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, return TRUE; } + +/*****************************************************************************/ + +/* Builds the IWD network configuration file name for a given SSID + * and security type pair. The SSID should be valid UTF-8 and in + * any case must contain no NUL-bytes. If @ssid is NUL-terminated, + * @ssid_len can be -1 instead of actual SSID length. + */ +char * +nm_wifi_utils_get_iwd_config_filename(const char * ssid, + gssize ssid_len, + NMIwdNetworkSecurity security) +{ + const char *security_suffix; + const char *ptr; + gboolean alnum_ssid = TRUE; + + for (ptr = ssid; ssid_len != 0 && *ptr != '\0'; ptr++, ssid_len--) + if (!g_ascii_isalnum(*ptr) && !strchr("-_ ", *ptr)) + alnum_ssid = FALSE; + + g_return_val_if_fail(ptr != ssid && ptr - ssid <= NM_IW_ESSID_MAX_SIZE, NULL); + + switch (security) { + case NM_IWD_NETWORK_SECURITY_OPEN: + security_suffix = "open"; + break; + case NM_IWD_NETWORK_SECURITY_PSK: + security_suffix = "psk"; + break; + case NM_IWD_NETWORK_SECURITY_8021X: + security_suffix = "8021x"; + break; + default: + return NULL; + } + + if (alnum_ssid) { + return g_strdup_printf("%.*s.%s", (int) (ptr - ssid), ssid, security_suffix); + } else { + char ssid_buf[NM_IW_ESSID_MAX_SIZE * 2 + 1]; + + return g_strdup_printf("=%s.%s", + nm_utils_bin2hexstr_full(ssid, ptr - ssid, '\0', FALSE, ssid_buf), + security_suffix); + } +} + +/*****************************************************************************/ + +#define SECRETS_DONT_STORE_FLAGS \ + (NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED) + +static gboolean +psk_setting_to_iwd_config(GKeyFile *file, NMSettingWirelessSecurity *s_wsec, GError **error) +{ + NMSettingSecretFlags psk_flags = nm_setting_wireless_security_get_psk_flags(s_wsec); + const char * psk = nm_setting_wireless_security_get_psk(s_wsec); + gsize psk_len; + guint8 buffer[32]; + const char * key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec); + + if (!psk || NM_FLAGS_ANY(psk_flags, SECRETS_DONT_STORE_FLAGS)) { + if (NM_FLAGS_ANY(psk_flags, SECRETS_DONT_STORE_FLAGS)) { + nm_log_info( + LOGD_WIFI, + "IWD network config is being created wihout the PSK but IWD will save the PSK on " + "successful activation not honoring the psk-flags property"); + } + return TRUE; + } + + psk_len = strlen(psk); + if (nm_streq0(key_mgmt, "sae")) { + g_key_file_set_string(file, "Security", "Passphrase", psk); + } else if (psk_len >= 8 && psk_len <= 63) { + g_key_file_set_string(file, "Security", "Passphrase", psk); + } else if (psk_len == 64 && nm_utils_hexstr2bin_buf(psk, FALSE, FALSE, NULL, buffer)) { + g_key_file_set_string(file, "Security", "PreSharedKey", psk); + } else { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Unknown PSK format"); + return FALSE; + } + + return TRUE; +} + +static gboolean +eap_certs_to_iwd_config(GKeyFile * file, + NMSetting8021x *s_8021x, + bool phase2, + char * iwd_prefix, + GError ** error) +{ + NMSetting8021xCKScheme ca_cert_scheme = + phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme(s_8021x) + : nm_setting_802_1x_get_ca_cert_scheme(s_8021x); + NMSetting8021xCKScheme client_cert_scheme = + phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme(s_8021x) + : nm_setting_802_1x_get_client_cert_scheme(s_8021x); + NMSetting8021xCKScheme key_scheme; + NMSettingSecretFlags key_password_flags; + const char * ca_path = phase2 ? nm_setting_802_1x_get_phase2_ca_path(s_8021x) + : nm_setting_802_1x_get_ca_path(s_8021x); + const char * cert_path; + const char * key_path = NULL; + const char * key_password; + const char * domain_suffix_match; + const char * domain_match; + char setting_buf[128]; + + /* TODO: should check that all certificates and the key are RSA */ + /* Note: up to IWD 1.9 only the PEM encoding was supported for certificates + * and only PKCS#8 PEM for keys but we don't know the IWD version here. + * From IWD 1.10 raw (DER) X.509 certificates and PKCS#12 are also supported + * for certificates but a certificate list or chain still has to be PEM + * (i.e. if it contains more than one certificate.) Raw PKCS#12 and + * old-style OpenSSL PEM formats are also supported for keys. Hopefully + * this is in practice the same set of file:// formats as supported by + * nm_crypto_* / wpa_supplicant so we need no conversions here. + */ + + if (nm_setting_802_1x_get_system_ca_certs(s_8021x)) { + /* Either overrides or is added to the certificates in (phase2-)ca-cert + * and ca-path depending on whether it points to a file or a directory. + * We can't ignore this property so it's an error if it is set. + * Fortunately not used by nm-connection-editor. + */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "The system-ca-certs property is not supported"); + return FALSE; + } + + if (ca_path) { + /* To support this (and this could be applied to system-ca-certs as + * well) we'd have to scan the directory, parse the certificates and + * write a new certificate-list file to point to in the IWD config. + * This is going to create issues of where to store these files, for + * how long and with what permission bits. Fortunately this doesn't + * seem to be used by nm-connection-editor either. + * + * That file would also have to contain whatever the (phase2-)ca-cert + * propterty points to because IWD has only one CACert setting per + * phase. + */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "The (phase2-)ca-path property is not supported"); + return FALSE; + } + + if (ca_cert_scheme != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { + if (ca_cert_scheme != NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* To support the blob scheme we'd have to either convert the + * certificate data into a PEM payload and embed the PEM file in + * the IWD config file, which is not supported by GKeyFile, or write + * it into a new file to point to in the IWD config. This is again + * is going to create issues of where to store these files, for how + * long and with what permission bits. Fortunately this scheme isn't + * used in nm-connection-editor either. + * + * PKCS#11 is not supported by IWD in any way so we don't need to + * support the PKCS#11 URI scheme. + * + * If scheme is unknown, assume no value is set. + */ + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "(phase2-)ca-cert property schemes other than file:// not supported"); + return FALSE; + } + + cert_path = phase2 ? nm_setting_802_1x_get_phase2_ca_cert_path(s_8021x) + : nm_setting_802_1x_get_ca_cert_path(s_8021x); + if (cert_path) + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "CACert"), + cert_path); + } + + if (client_cert_scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) + goto private_key_done; + + if (client_cert_scheme != NM_SETTING_802_1X_CK_SCHEME_PATH) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "(phase2-)client-cert property schemes other than file:// not supported"); + return FALSE; + } + + cert_path = phase2 ? nm_setting_802_1x_get_phase2_client_cert_path(s_8021x) + : nm_setting_802_1x_get_client_cert_path(s_8021x); + if (!cert_path) + goto private_key_done; + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "ClientCert"), + cert_path); + + key_scheme = phase2 ? nm_setting_802_1x_get_phase2_private_key_scheme(s_8021x) + : nm_setting_802_1x_get_private_key_scheme(s_8021x); + if (key_scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) + key_path = phase2 ? nm_setting_802_1x_get_phase2_private_key_path(s_8021x) + : nm_setting_802_1x_get_private_key_path(s_8021x); + if (key_scheme != NM_SETTING_802_1X_CK_SCHEME_PATH || !key_path) { + /* The same comments apply to writing the key into a temporary file + * as for the certificates (above), except this is even more + * sensitive. + */ + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "(phase2-)private-key property schemes other than file:// not supported"); + return FALSE; + } + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "ClientKey"), + key_path); + + key_password = phase2 ? nm_setting_802_1x_get_phase2_private_key_password(s_8021x) + : nm_setting_802_1x_get_private_key_password(s_8021x); + key_password_flags = phase2 ? nm_setting_802_1x_get_phase2_private_key_password_flags(s_8021x) + : nm_setting_802_1x_get_private_key_password_flags(s_8021x); + if (!key_password || NM_FLAGS_ANY(key_password_flags, SECRETS_DONT_STORE_FLAGS)) { + g_key_file_set_comment( + file, + "Security", + setting_buf, + "ClientKeyPassphrase not to be saved, will be queried through the agent if needed", + NULL); + goto private_key_done; + } + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "ClientKeyPassphrase"), + key_password); + +private_key_done: + if (phase2 ? nm_setting_802_1x_get_phase2_subject_match(s_8021x) + : nm_setting_802_1x_get_subject_match(s_8021x)) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "(phase2-)subject-match not supported, use domain-match or domain-suffix-match"); + return FALSE; + } + + if (phase2 ? nm_setting_802_1x_get_num_phase2_altsubject_matches(s_8021x) + : nm_setting_802_1x_get_num_altsubject_matches(s_8021x)) { + /* We could convert the "DNS:" entries into a ServerDomainMask but we'd + * have to leave out the "EMAIL:" and "URI:" types or report error. + * The interpretation still wouldn't be exactly the same as in + * wpa_supplicant. + */ + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "(phase2-)altsubject-matches not supported, use domain-match or domain-suffix-match"); + return FALSE; + } + + domain_suffix_match = phase2 ? nm_setting_802_1x_get_phase2_domain_suffix_match(s_8021x) + : nm_setting_802_1x_get_domain_suffix_match(s_8021x); + domain_match = phase2 ? nm_setting_802_1x_get_phase2_domain_match(s_8021x) + : nm_setting_802_1x_get_domain_match(s_8021x); + + if (domain_suffix_match || domain_match) { + GString * s = g_string_sized_new(128); + const char *ptr; + const char *end; + + for (ptr = domain_suffix_match; ptr; ptr = *end == ';' ? end + 1 : NULL) { + if (s->len) + g_string_append_c(s, ';'); + end = strchrnul(ptr, ';'); + /* Use *. to get the suffix match effect */ + g_string_append(s, "*."); + g_string_append_len(s, ptr, end - ptr); + } + + /* domain-match can be appended as-is */ + if (domain_match) { + if (s->len) + g_string_append_c(s, ';'); + g_string_append(s, domain_match); + } + + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "ServerDomainMask"), + s->str); + g_string_free(s, TRUE); + } + + return TRUE; +} + +static void +eap_method_name_to_iwd_config(GKeyFile *file, const char *iwd_prefix, const char *method) +{ + char setting_buf[128]; + + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "Method"), + method); +} + +static void +eap_optional_identity_to_iwd_config(GKeyFile *file, const char *iwd_prefix, const char *identity) +{ + char setting_buf[128]; + + /* The identity is optional for some methods where an authenticator may + * in theory not ask for it. For our usage here we treat it as always + * optional because it can be omitted in the config file if the user + * wants IWD to query for it on every connection. + */ + if (identity) { + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "Identity"), + identity); + } else { + g_key_file_set_comment( + file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "Method"), + "Identity not to be saved, will be queried through the agent if needed", + NULL); + } +} + +static gboolean +eap_optional_password_to_iwd_config(GKeyFile * file, + const char * iwd_prefix, + NMSetting8021x *s_8021x, + GError ** error) +{ + char setting_buf[128]; + const char * password = nm_setting_802_1x_get_password(s_8021x); + NMSettingSecretFlags flags = nm_setting_802_1x_get_password_flags(s_8021x); + + if (!password && nm_setting_802_1x_get_password_raw(s_8021x)) { + /* IWD doesn't support passwords that can't be encoded in the config + * file, i.e. containing NUL characters. Those that don't have NULs + * could in theory be written to the config file but GKeyFile may not + * like that if they're no UTF-8, and the password-raw property is + * not written by nm-connection-editor anyway. + */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Non-UTF-8 passwords are not supported, if the password is UTF-8 set " + "the \"password\" property"); + return FALSE; + } + if (!password || NM_FLAGS_ANY(flags, SECRETS_DONT_STORE_FLAGS)) { + return g_key_file_set_comment(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "Method"), + "Password not to be saved, will be queried through the agent", + error); + } else { + g_key_file_set_string(file, + "Security", + nm_sprintf_buf(setting_buf, "%s%s", iwd_prefix, "Password"), + password); + return TRUE; + } +} + +static void +eap_phase1_identity_to_iwd_config(GKeyFile *file, const char *iwd_prefix, NMSetting8021x *s_8021x) +{ + const char *phase1_identity = nm_setting_802_1x_get_anonymous_identity(s_8021x); + + if (!phase1_identity) { + phase1_identity = nm_setting_802_1x_get_identity(s_8021x); + + if (phase1_identity) { + nm_log_info(LOGD_WIFI, + "IWD network config will send the same EAP Identity string in " + "plaintext in phase 1 as in phase 2 (encrypted) to mimic legacy " + "behavior, set [%s].%s=anonymous to prevent exposing the value", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY); + } + } + + eap_optional_identity_to_iwd_config(file, iwd_prefix, phase1_identity); +} + +static gboolean +eap_method_config_to_iwd_config(GKeyFile * file, + NMSetting8021x *s_8021x, + gboolean phase2, + const char * method, + const char * iwd_prefix, + GError ** error) +{ + char prefix_buf[128]; + + if (nm_streq0(method, "tls")) { + eap_method_name_to_iwd_config(file, iwd_prefix, "TLS"); + eap_optional_identity_to_iwd_config(file, + iwd_prefix, + nm_setting_802_1x_get_identity(s_8021x)); + + return eap_certs_to_iwd_config(file, + s_8021x, + phase2, + nm_sprintf_buf(prefix_buf, "%s%s", iwd_prefix, "TLS-"), + error); + } else if (nm_streq0(method, "ttls") && !phase2) { + const char *noneap_method = nm_setting_802_1x_get_phase2_auth(s_8021x); + + eap_method_name_to_iwd_config(file, iwd_prefix, "TTLS"); + eap_phase1_identity_to_iwd_config(file, iwd_prefix, s_8021x); + + if (!eap_certs_to_iwd_config(file, + s_8021x, + phase2, + nm_sprintf_buf(prefix_buf, "%s%s", iwd_prefix, "TTLS-"), + error)) + return FALSE; + + nm_sprintf_buf(prefix_buf, "%s%s", iwd_prefix, "TTLS-Phase2-"); + + if (nm_setting_802_1x_get_phase2_autheap(s_8021x)) { + if (noneap_method) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Only one TTLS phase 2 method can be set"); + return FALSE; + } + return eap_method_config_to_iwd_config(file, + s_8021x, + TRUE, + nm_setting_802_1x_get_phase2_autheap(s_8021x), + prefix_buf, + error); + } + + if (NM_IN_STRSET(noneap_method, "chap", "mschap", "mschapv2", "pap")) { + const char *iwd_method; + + if (nm_streq0(noneap_method, "chap")) { + iwd_method = "Tunneled-CHAP"; + } else if (nm_streq0(noneap_method, "mschap")) { + iwd_method = "Tunneled-MSCHAP"; + } else if (nm_streq0(noneap_method, "mschapv2")) { + iwd_method = "Tunneled-MSCHAPv2"; + } else { + iwd_method = "Tunneled-PAP"; + } + + eap_method_name_to_iwd_config(file, prefix_buf, iwd_method); + eap_optional_identity_to_iwd_config(file, + prefix_buf, + nm_setting_802_1x_get_identity(s_8021x)); + return eap_optional_password_to_iwd_config(file, prefix_buf, s_8021x, error); + } + + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Unsupported TTLS non-EAP inner method"); + return FALSE; + } else if (nm_streq0(method, "peap") && !phase2) { + eap_method_name_to_iwd_config(file, iwd_prefix, "PEAP"); + eap_phase1_identity_to_iwd_config(file, iwd_prefix, s_8021x); + + if (!eap_certs_to_iwd_config(file, + s_8021x, + phase2, + nm_sprintf_buf(prefix_buf, "%s%s", iwd_prefix, "PEAP-"), + error)) + return FALSE; + + if (nm_setting_802_1x_get_phase1_peapver(s_8021x) + || nm_setting_802_1x_get_phase1_peaplabel(s_8021x)) + nm_log_info(LOGD_WIFI, + "IWD network config will not honour the PEAP version and label properties " + "in the 802.1x setting (unsupported)"); + + if (!nm_setting_802_1x_get_phase2_auth(s_8021x)) { + /* Apparently PEAP can be used without a phase 2 but this is not + * supported by either NM or IWD. + */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "PEAP without an inner method is unsupported"); + return FALSE; + } + + return eap_method_config_to_iwd_config( + file, + s_8021x, + TRUE, + nm_setting_802_1x_get_phase2_auth(s_8021x), + nm_sprintf_buf(prefix_buf, "%s%s", iwd_prefix, "PEAP-Phase2-"), + error); + } else if (nm_streq0(method, "md5") && phase2) { + eap_method_name_to_iwd_config(file, iwd_prefix, "MD5"); + eap_optional_identity_to_iwd_config(file, + iwd_prefix, + nm_setting_802_1x_get_identity(s_8021x)); + return eap_optional_password_to_iwd_config(file, iwd_prefix, s_8021x, error); + } else if (nm_streq0(method, "gtc") && phase2) { + eap_method_name_to_iwd_config(file, iwd_prefix, "GTC"); + eap_optional_identity_to_iwd_config(file, + iwd_prefix, + nm_setting_802_1x_get_identity(s_8021x)); + return eap_optional_password_to_iwd_config(file, iwd_prefix, s_8021x, error); + } else if (nm_streq0(method, "pwd")) { + eap_method_name_to_iwd_config(file, iwd_prefix, "PWD"); + eap_optional_identity_to_iwd_config(file, + iwd_prefix, + nm_setting_802_1x_get_identity(s_8021x)); + return eap_optional_password_to_iwd_config(file, iwd_prefix, s_8021x, error); + } else if (nm_streq0(method, "mschapv2")) { + eap_method_name_to_iwd_config(file, iwd_prefix, "MSCHAPV2"); + eap_optional_identity_to_iwd_config(file, + iwd_prefix, + nm_setting_802_1x_get_identity(s_8021x)); + /* In this case we can support password-raw but would have to + * MD4-hash it and set as Password-Hash + */ + return eap_optional_password_to_iwd_config(file, iwd_prefix, s_8021x, error); + } else if (nm_streq0(method, "external")) { + /* This may be a connection created by NMIwdManager in whch case there + * may be no need to be convert it back to the IWD format. Ideally we + * would still rewrite the other sections/groups in the IWD settings + * file and preserve the [Security] group -- TODO. Possibly this should + * also not be reported as an error. + */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Connection contains no EAP method configuration"); + return FALSE; + } else { + /* Some methods are only allowed in phase 1 or only phase 2. + * OTP, LEAP and FAST are not supported by IWD at all. + */ + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + phase2 ? "Unsupported phase 2 EAP method" + : "Unsupported phase 1 EAP method"); + return FALSE; + } + + return TRUE; +} + +static gboolean +eap_setting_to_iwd_config(GKeyFile *file, NMSetting8021x *s_8021x, GError **error) +{ + const char *method; + + if (!s_8021x || nm_setting_802_1x_get_num_eap_methods(s_8021x) == 0) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "The 802.1x setting is missing or no EAP method set"); + return FALSE; + } + + if (!nm_setting_verify(NM_SETTING(s_8021x), NULL, error)) + return FALSE; + + method = nm_setting_802_1x_get_eap_method(s_8021x, 0); + + if (nm_setting_802_1x_get_num_eap_methods(s_8021x) > 1) + nm_log_info(LOGD_WIFI, + "IWD network config will only contain the first EAP method: %s", + method); + + if (nm_setting_802_1x_get_phase1_auth_flags(s_8021x)) + nm_log_info(LOGD_WIFI, + "IWD network config will not honour the TLSv1.x-disable flags in the 802.1x " + "setting (unsupported)"); + + if (nm_setting_802_1x_get_auth_timeout(s_8021x)) + nm_log_info(LOGD_WIFI, + "IWD network config will not honour the auth-timeout property in the 802.1x " + "setting (unsupported)"); + + return eap_method_config_to_iwd_config(file, s_8021x, FALSE, method, "EAP-", error); +} + +static gboolean +ip4_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error) +{ + guint num; + struct in_addr ip; + + /* These settings are not acutally used unless global + * [General].EnableNetworkConfiguration is true, which we don't support. + * We add them for sake of completness, although many NMSettingIPConfig + * configurations can't be mapped to IWD configs and we simply ignore + * them. If they were to be used we'd need to add a few warnings. + */ + + if (!s_ip) + return TRUE; + + num = nm_setting_ip_config_get_num_dns(s_ip); + if (num) { + nm_auto_free_gstring GString *s = g_string_sized_new(128); + guint i; + + for (i = 0; i < num; i++) { + if (s->len) + g_string_append_c(s, ' '); + g_string_append(s, nm_setting_ip_config_get_dns(s_ip, i)); + } + /* It doesn't matter whether we add the DNS under [IPv4] or [IPv6] + * except that with method=auto the list will override the + * DNS addresses received over the DHCP version corresponing to + * v4 or v6. + * Note ignore-auto-dns=false isn't supported, this list always + * overrides the DHCP DNSes. + */ + g_key_file_set_string(file, "IPv4", "DNS", s->str); + } + + if (!nm_streq0(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) + return TRUE; + + num = nm_setting_ip_config_get_num_addresses(s_ip); + if (num) { + NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, 0); + guint prefix = nm_ip_address_get_prefix(addr); + in_addr_t netmask = _nm_utils_ip4_prefix_to_netmask(prefix); + char buf[INET_ADDRSTRLEN]; + + nm_ip_address_get_address_binary(addr, &ip); + g_key_file_set_string(file, "IPv4", "Address", nm_ip_address_get_address(addr)); + g_key_file_set_string(file, "IPv4", "Netmask", _nm_utils_inet4_ntop(netmask, buf)); + } else { + inet_pton(AF_INET, "10.42.0.100", &ip); + g_key_file_set_string(file, "IPv4", "Address", "10.42.0.100"); + } + + if (nm_setting_ip_config_get_gateway(s_ip)) { + g_key_file_set_string(file, "IPv4", "Gateway", nm_setting_ip_config_get_gateway(s_ip)); + } else { + uint32_t val; + char buf[INET_ADDRSTRLEN]; + + /* IWD won't enable static IP unless both Address and Gateway are + * set so generate a gateway address if not known. + */ + val = (ntohl(ip.s_addr) & 0xfffffff0) + 1; + if (val == ntohl(ip.s_addr)) + val += 1; + g_key_file_set_string(file, "IPv4", "Gateway", _nm_utils_inet4_ntop(htonl(val), buf)); + } + + return TRUE; +} + +static gboolean +ip6_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error) +{ + guint num; + NMIPAddress *addr; + char buf[INET6_ADDRSTRLEN + 10]; + + if (!s_ip) + return TRUE; + + num = nm_setting_ip_config_get_num_dns(s_ip); + if (num) { + nm_auto_free_gstring GString *s = g_string_sized_new(128); + guint i; + + for (i = 0; i < num; i++) { + if (s->len) + g_string_append_c(s, ' '); + g_string_append(s, nm_setting_ip_config_get_dns(s_ip, i)); + } + g_key_file_set_string(file, "IPv6", "DNS", s->str); + } + + if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip), + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) + return TRUE; + + g_key_file_set_boolean(file, "IPv6", "Enabled", TRUE); + + if (!nm_streq0(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) + return TRUE; + + if (!nm_setting_ip_config_get_num_addresses(s_ip)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "IP address required for IPv6 manual config"); + return FALSE; + } + + addr = nm_setting_ip_config_get_address(s_ip, 0); + g_key_file_set_string(file, + "IPv6", + "Address", + nm_sprintf_buf(buf, + "%s/%u", + nm_ip_address_get_address(addr), + nm_ip_address_get_prefix(addr))); + if (nm_setting_ip_config_get_gateway(s_ip)) + g_key_file_set_string(file, "IPv6", "Gateway", nm_setting_ip_config_get_gateway(s_ip)); + return TRUE; +} + +GKeyFile * +nm_wifi_utils_connection_to_iwd_config(NMConnection *connection, + char ** out_filename, + GError ** error) +{ + NMSettingConnection * s_conn = nm_connection_get_setting_connection(connection); + NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(connection); + GBytes * ssid; + const guint8 * ssid_data; + gsize ssid_len; + NMIwdNetworkSecurity security; + const char * cloned_mac_addr; + gs_free char * comment = NULL; + nm_auto_unref_keyfile GKeyFile *file = NULL; + + if (!s_conn || !s_wifi + || !nm_streq(nm_setting_connection_get_connection_type(s_conn), + NM_SETTING_WIRELESS_SETTING_NAME)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Connection and/or wireless settings are missing"); + return NULL; + } + + if (!NM_IN_STRSET(nm_setting_wireless_get_mode(s_wifi), NULL, NM_SETTING_WIRELESS_MODE_INFRA)) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Non-infrastructure-mode connections don't have IWD profiles (or aren't supported)"); + return NULL; + } + + ssid = nm_setting_wireless_get_ssid(s_wifi); + ssid_data = ssid ? g_bytes_get_data(ssid, &ssid_len) : NULL; + if (!ssid_data || ssid_len <= 0 || ssid_len > NM_IW_ESSID_MAX_SIZE + || !g_utf8_validate((const char *) ssid_data, ssid_len, NULL)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Empty or non-UTF-8 SSIDs not supported by IWD"); + return NULL; + } + + if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Connection's security type unrecognised"); + return NULL; + } + + file = g_key_file_new(); + + comment = g_strdup_printf(" Auto-generated from NetworkManager connection \"%s\"\n" + " Changes to that connection overwrite this file when " + "enabled by NM's [%s].%s value", + nm_setting_connection_get_id(s_conn), + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_IWD_CONFIG_PATH); + g_key_file_set_comment(file, NULL, NULL, comment, NULL); + + if (!nm_setting_connection_get_autoconnect(s_conn)) + g_key_file_set_boolean(file, "Settings", "AutoConnect", FALSE); + + if (nm_setting_wireless_get_hidden(s_wifi)) + g_key_file_set_boolean(file, "Settings", "Hidden", TRUE); + + /* Only effective if IWD's global [General].AddressRandomization is set + * to "network". "random" maps to [Settings].AlwaysRandomizeAddress=true, + * "stable" is the default, specific address maps to + * [Settings].AddressOverride set to that address. "permanent" is not + * supported and "preserve" can only be achieved using the global + * [General].AddressRandomization=disabled setting. We don't print + * warnings when we can't map the value here because we don't know what + * IWD's [General].AddressRandomization is set to. + */ + cloned_mac_addr = nm_setting_wireless_get_cloned_mac_address(s_wifi); + if (nm_streq0(cloned_mac_addr, NM_CLONED_MAC_RANDOM)) + g_key_file_set_boolean(file, "Settings", "AlwaysRandomizeAddress", TRUE); + else if (cloned_mac_addr && nm_utils_hwaddr_valid(cloned_mac_addr, ETH_ALEN)) + g_key_file_set_string(file, "Settings", "AddressOverride", cloned_mac_addr); + + if (!ip4_config_to_iwd_config( + file, + NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip4_config(connection)), + error)) + return NULL; + + if (!ip6_config_to_iwd_config( + file, + NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip6_config(connection)), + error)) + return NULL; + + switch (security) { + case NM_IWD_NETWORK_SECURITY_OPEN: + break; + case NM_IWD_NETWORK_SECURITY_PSK: + if (!psk_setting_to_iwd_config(file, + nm_connection_get_setting_wireless_security(connection), + error)) + return NULL; + + break; + case NM_IWD_NETWORK_SECURITY_8021X: + if (!eap_setting_to_iwd_config(file, nm_connection_get_setting_802_1x(connection), error)) + return NULL; + + break; + default: + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "Connection security type is not supported"); + return NULL; + } + + if (out_filename) + *out_filename = + nm_wifi_utils_get_iwd_config_filename((const char *) ssid_data, ssid_len, security); + + return g_steal_pointer(&file); +} diff --git a/src/core/devices/wifi/nm-wifi-utils.h b/src/core/devices/wifi/nm-wifi-utils.h index 474bea41..2664c03e 100644 --- a/src/core/devices/wifi/nm-wifi-utils.h +++ b/src/core/devices/wifi/nm-wifi-utils.h @@ -11,6 +11,7 @@ #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" #include "nm-setting-8021x.h" +#include "libnm-base/nm-base.h" typedef enum { NM_IWD_NETWORK_SECURITY_OPEN, @@ -21,7 +22,7 @@ typedef enum { gboolean nm_wifi_utils_complete_connection(GBytes * ssid, const char * bssid, - NM80211Mode mode, + _NM80211Mode mode, guint32 ap_freq, guint32 flags, guint32 wpa_flags, @@ -35,5 +36,11 @@ gboolean nm_wifi_utils_is_manf_default_ssid(GBytes *ssid); gboolean nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, char ** ssid, NMIwdNetworkSecurity *security); +char * nm_wifi_utils_get_iwd_config_filename(const char * ssid, + gssize ssid_len, + NMIwdNetworkSecurity security); + +GKeyFile * +nm_wifi_utils_connection_to_iwd_config(NMConnection *conn, char **out_filename, GError **error); #endif /* __NM_WIFI_UTILS_H__ */ diff --git a/src/core/devices/wifi/tests/test-devices-wifi.c b/src/core/devices/wifi/tests/test-devices-wifi.c index bc0ba126..dc278c94 100644 --- a/src/core/devices/wifi/tests/test-devices-wifi.c +++ b/src/core/devices/wifi/tests/test-devices-wifi.c @@ -7,7 +7,7 @@ #include "devices/wifi/nm-wifi-utils.h" #include "devices/wifi/nm-device-wifi.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-test-utils-core.h" @@ -49,7 +49,7 @@ static gboolean complete_connection(const char * ssid, const char * bssid, - NM80211Mode mode, + _NM80211Mode mode, guint32 flags, guint32 wpa_flags, guint32 rsn_flags, @@ -197,7 +197,7 @@ fill_8021x(NMConnection *connection, const KeyData items[]) } static NMConnection * -create_basic(const char *ssid, const char *bssid, NM80211Mode mode) +create_basic(const char *ssid, const char *bssid, _NM80211Mode mode) { NMConnection * connection; NMSettingWireless *s_wifi = NULL; @@ -217,9 +217,9 @@ create_basic(const char *ssid, const char *bssid, NM80211Mode mode) if (bssid) g_object_set(G_OBJECT(s_wifi), NM_SETTING_WIRELESS_BSSID, bssid, NULL); - if (mode == NM_802_11_MODE_INFRA) + if (mode == _NM_802_11_MODE_INFRA) g_object_set(G_OBJECT(s_wifi), NM_SETTING_WIRELESS_MODE, "infrastructure", NULL); - else if (mode == NM_802_11_MODE_ADHOC) + else if (mode == _NM_802_11_MODE_ADHOC) g_object_set(G_OBJECT(s_wifi), NM_SETTING_WIRELESS_MODE, "adhoc", NULL); else g_assert_not_reached(); @@ -241,14 +241,14 @@ test_lock_bssid(void) src = nm_simple_connection_new(); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, TRUE, src, &error); - expected = create_basic(ssid, bssid, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, bssid, _NM_802_11_MODE_INFRA); COMPARE(src, expected, success, error, 0, 0); g_object_unref(src); @@ -273,14 +273,14 @@ test_open_ap_empty_connection(void) src = nm_simple_connection_new(); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, FALSE, src, &error); - expected = create_basic(ssid, NULL, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, NULL, _NM_802_11_MODE_INFRA); COMPARE(src, expected, success, error, 0, 0); g_object_unref(src); @@ -311,7 +311,7 @@ test_open_ap_leap_connection_1(gconstpointer add_wifi) success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -345,7 +345,7 @@ test_open_ap_leap_connection_2(void) success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -383,7 +383,7 @@ test_open_ap_wep_connection(gconstpointer add_wifi) fill_wsec(src, src_wsec); success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_NONE, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -427,7 +427,7 @@ test_ap_wpa_psk_connection_base(const char * key_mgmt, fill_wsec(src, both_wsec); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, flags, wpa_flags, rsn_flags, @@ -553,7 +553,7 @@ test_ap_wpa_eap_connection_base(const char *key_mgmt, fill_8021x(src, src_empty); success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, flags, wpa_flags, rsn_flags, @@ -751,7 +751,7 @@ test_priv_ap_empty_connection(void) src = nm_simple_connection_new(); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -760,7 +760,7 @@ test_priv_ap_empty_connection(void) &error); /* Static WEP connection expected */ - expected = create_basic(ssid, NULL, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, NULL, _NM_802_11_MODE_INFRA); fill_wsec(expected, exp_wsec); COMPARE(src, expected, success, error, 0, 0); @@ -798,7 +798,7 @@ test_priv_ap_leap_connection_1(gconstpointer add_wifi) fill_wsec(src, src_wsec); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -809,7 +809,7 @@ test_priv_ap_leap_connection_1(gconstpointer add_wifi) * there's no way to determine from the AP's beacon whether it's static WEP, * dynamic WEP, or LEAP. */ - expected = create_basic(ssid, NULL, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, NULL, _NM_802_11_MODE_INFRA); fill_wsec(expected, exp_wsec); COMPARE(src, expected, success, error, 0, 0); @@ -840,7 +840,7 @@ test_priv_ap_leap_connection_2(void) fill_wsec(src, src_wsec); success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -885,7 +885,7 @@ test_priv_ap_dynamic_wep_1(void) fill_8021x(src, both_8021x); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -894,7 +894,7 @@ test_priv_ap_dynamic_wep_1(void) &error); /* We expect a completed Dynamic WEP connection */ - expected = create_basic(ssid, NULL, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, NULL, _NM_802_11_MODE_INFRA); fill_wsec(expected, exp_wsec); fill_8021x(expected, both_8021x); COMPARE(src, expected, success, error, 0, 0); @@ -933,7 +933,7 @@ test_priv_ap_dynamic_wep_2(void) fill_8021x(src, both_8021x); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -942,7 +942,7 @@ test_priv_ap_dynamic_wep_2(void) &error); /* We expect a completed Dynamic WEP connection */ - expected = create_basic(ssid, NULL, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, NULL, _NM_802_11_MODE_INFRA); fill_wsec(expected, exp_wsec); fill_8021x(expected, both_8021x); COMPARE(src, expected, success, error, 0, 0); @@ -976,7 +976,7 @@ test_priv_ap_dynamic_wep_3(void) fill_8021x(src, src_8021x); success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_SEC_NONE, NM_802_11_AP_SEC_NONE, @@ -1102,7 +1102,7 @@ test_wpa_ap_empty_connection(gconstpointer data) src = nm_simple_connection_new(); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, wpa_flags_for_idx(idx), rsn_flags_for_idx(idx), @@ -1111,7 +1111,7 @@ test_wpa_ap_empty_connection(gconstpointer data) &error); /* WPA connection expected */ - expected = create_basic(ssid, NULL, NM_802_11_MODE_INFRA); + expected = create_basic(ssid, NULL, _NM_802_11_MODE_INFRA); fill_wsec(expected, exp_wsec); COMPARE(src, expected, success, error, 0, 0); @@ -1144,7 +1144,7 @@ test_wpa_ap_leap_connection_1(gconstpointer data) fill_wsec(src, src_wsec); success = complete_connection(ssid, bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, wpa_flags_for_idx(idx), rsn_flags_for_idx(idx), @@ -1180,7 +1180,7 @@ test_wpa_ap_leap_connection_2(gconstpointer data) fill_wsec(src, src_wsec); success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, wpa_flags_for_idx(idx), rsn_flags_for_idx(idx), @@ -1214,7 +1214,7 @@ test_wpa_ap_dynamic_wep_connection(gconstpointer data) fill_wsec(src, src_wsec); success = complete_connection("blahblah", bssid, - NM_802_11_MODE_INFRA, + _NM_802_11_MODE_INFRA, NM_802_11_AP_FLAGS_PRIVACY, wpa_flags_for_idx(idx), rsn_flags_for_idx(idx), diff --git a/src/core/devices/wwan/meson.build b/src/core/devices/wwan/meson.build index 87af0429..37ef738c 100644 --- a/src/core/devices/wwan/meson.build +++ b/src/core/devices/wwan/meson.build @@ -17,7 +17,6 @@ libnm_wwan = shared_module( libsystemd_dep, mm_glib_dep, ], - c_args: daemon_c_flags, link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, install: true, @@ -51,7 +50,6 @@ libnm_device_plugin_wwan = shared_module( libsystemd_dep, mm_glib_dep, ], - c_args: daemon_c_flags, link_with: libnm_wwan, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index 3ea89d2c..4d892e6f 100644 --- a/src/core/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -14,7 +14,7 @@ #include "settings/nm-settings-connection.h" #include "nm-modem-broadband.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceModem #include "devices/nm-device-logging.h" @@ -193,15 +193,20 @@ modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpoi NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDevice * device = NM_DEVICE(self); - g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE); + if (!nm_device_activate_ip4_state_in_conf(device)) { + _LOGD(LOGD_MB | LOGD_IP4, + "retrieving IPv4 configuration while no longer in state IPv4 conf"); + return; + } if (error) { _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message); nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else { - nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config)); - nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL); + return; } + + nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config)); + nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL); } static void @@ -218,7 +223,11 @@ modem_ip6_config_result(NMModem * modem, gs_unref_object NMIP6Config *ignored = NULL; gboolean got_config = !!config; - g_return_if_fail(nm_device_activate_ip6_state_in_conf(device) == TRUE); + if (!nm_device_activate_ip6_state_in_conf(device)) { + _LOGD(LOGD_MB | LOGD_IP6, + "retrieving IPv6 configuration while no longer in state IPv6 conf"); + return; + } if (error) { _LOGW(LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); @@ -357,7 +366,6 @@ modem_state_cb(NMModem *modem, int new_state_i, int old_state_i, gpointer user_d nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); - return; } if (new_state > NM_MODEM_STATE_LOCKED && old_state == NM_MODEM_STATE_LOCKED) { @@ -856,14 +864,13 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_device_modem = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DEVICE_MODEM, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ModemCapabilities", - "u", - NM_DEVICE_MODEM_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("CurrentCapabilities", - "u", - NM_DEVICE_MODEM_CURRENT_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ModemCapabilities", + "u", + NM_DEVICE_MODEM_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("CurrentCapabilities", + "u", + NM_DEVICE_MODEM_CURRENT_CAPABILITIES), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DeviceId", "s", NM_DEVICE_MODEM_DEVICE_ID), @@ -871,7 +878,6 @@ static const NMDBusInterfaceInfoExtended interface_info_device_modem = { "s", NM_DEVICE_MODEM_OPERATOR_CODE), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Apn", "s", NM_DEVICE_MODEM_APN), ), ), - .legacy_property_changed = TRUE, }; static void diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index 1297d964..0872a8a1 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -11,10 +11,10 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" diff --git a/src/core/devices/wwan/nm-modem-manager.c b/src/core/devices/wwan/nm-modem-manager.c index 598c6898..4fb9a378 100644 --- a/src/core/devices/wwan/nm-modem-manager.c +++ b/src/core/devices/wwan/nm-modem-manager.c @@ -17,7 +17,7 @@ #define sd_booted() FALSE #endif -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-modem.h" #include "nm-modem-broadband.h" diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 21734cee..78ad7b68 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -7,10 +7,10 @@ #include "nm-modem-ofono.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "devices/nm-device-private.h" #include "nm-modem.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-ip4-config.h" #define VARIANT_IS_OF_TYPE_BOOLEAN(v) \ @@ -316,10 +316,9 @@ handle_sim_property(GDBusProxy *proxy, const char *property, GVariant *v, gpoint static void sim_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - GVariant *v_child = g_variant_get_child_value(v, 0); + gs_unref_variant GVariant *v_child = g_variant_get_child_value(v, 0); handle_sim_property(proxy, property, v_child, user_data); - g_variant_unref(v_child); } static void @@ -330,7 +329,7 @@ sim_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_dat gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; - GVariant * v; + gs_unref_variant GVariant *v = NULL; GVariantIter i; const char * property; @@ -370,9 +369,8 @@ sim_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_dat */ g_variant_iter_init(&i, v_dict); - while (g_variant_iter_next(&i, "{&sv}", &property, &v)) { + while (g_variant_iter_loop(&i, "{&sv}", &property, &v)) { handle_sim_property(NULL, property, v, self); - g_variant_unref(v); } } @@ -477,10 +475,9 @@ handle_connman_property(GDBusProxy *proxy, const char *property, GVariant *v, gp static void connman_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - GVariant *v_child = g_variant_get_child_value(v, 0); + gs_unref_variant GVariant *v_child = g_variant_get_child_value(v, 0); handle_connman_property(proxy, property, v_child, user_data); - g_variant_unref(v_child); } static void @@ -491,7 +488,7 @@ connman_get_properties_done(GObject *source, GAsyncResult *result, gpointer user gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; - GVariant * v; + gs_unref_variant GVariant *v = NULL; GVariantIter i; const char * property; @@ -523,9 +520,8 @@ connman_get_properties_done(GObject *source, GAsyncResult *result, gpointer user */ g_variant_iter_init(&i, v_dict); - while (g_variant_iter_next(&i, "{&sv}", &property, &v)) { + while (g_variant_iter_loop(&i, "{&sv}", &property, &v)) { handle_connman_property(NULL, property, v, self); - g_variant_unref(v); } } @@ -700,9 +696,8 @@ modem_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_d */ g_variant_iter_init(&i, v_dict); - while (g_variant_iter_next(&i, "{&sv}", &property, &v)) { + while (g_variant_iter_loop(&i, "{&sv}", &property, &v)) { handle_modem_property(NULL, property, v, self); - g_variant_unref(v); } } @@ -726,35 +721,30 @@ stage1_prepare_done(GObject *source, GAsyncResult *result, gpointer user_data) nm_clear_pointer(&priv->connect_properties, g_hash_table_destroy); if (error) { - _LOGW("connection failed: %s", error->message); - - nm_modem_emit_prepare_result(NM_MODEM(self), FALSE, NM_DEVICE_STATE_REASON_MODEM_BUSY); - /* - * FIXME: add code to check for InProgress so that the - * connection doesn't continue to try and activate, - * leading to the connection being disabled, and a 5m - * timeout... - */ + if (!g_strstr_len(error->message, + NM_STRLEN(OFONO_ERROR_IN_PROGRESS), + OFONO_ERROR_IN_PROGRESS)) { + nm_modem_emit_prepare_result(NM_MODEM(self), FALSE, NM_DEVICE_STATE_REASON_MODEM_BUSY); + } } } static void -context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) +handle_settings(GVariant *v_dict, gpointer user_data) { NMModemOfono * self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); NMPlatformIP4Address addr; - gboolean ret = FALSE; - gs_unref_variant GVariant *v_dict = NULL; - const char * interface; - const char * s; - const char ** array, **iter; - guint32 address_network, gateway_network; - guint32 ip4_route_table, ip4_route_metric; - int ifindex; - GError * error = NULL; + gboolean ret = FALSE; + const char * interface; + const char * s; + const char ** array, **iter; + guint32 address_network, gateway_network; + guint32 ip4_route_table, ip4_route_metric; + int ifindex; + GError * error = NULL; - _LOGD("PropertyChanged: %s", property); + //_LOGD("PropertyChanged: %s", property); /* * TODO: might be a good idea and re-factor this to mimic bluez-device, @@ -762,15 +752,6 @@ context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, g * handle the action. */ - if (g_strcmp0(property, "Settings") != 0) - return; - - v_dict = g_variant_get_child_value(v, 0); - if (!v_dict) { - _LOGW("error getting IPv4 Settings: no v_dict"); - goto out; - } - _LOGI("IPv4 static Settings:"); if (!g_variant_lookup(v_dict, "Interface", "&s", &interface)) { @@ -909,6 +890,28 @@ out: } } +static void +context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) +{ + NMModemOfono * self = NM_MODEM_OFONO(user_data); + gs_unref_variant GVariant *v_dict = NULL; + + _LOGD("PropertyChanged: %s", property); + + if (g_strcmp0(property, "Settings") != 0) + return; + + v_dict = g_variant_get_child_value(v, 0); + if (!v_dict) { + _LOGW("ofono: (%s): error getting IPv4 Settings", nm_modem_get_uid(NM_MODEM(self))); + return; + } + + g_assert(g_variant_is_of_type(v_dict, G_VARIANT_TYPE_VARDICT)); + + handle_settings(v_dict, user_data); +} + static NMActStageReturn static_stage3_ip4_config_start(NMModem * modem, NMActRequest * req, @@ -935,6 +938,72 @@ static_stage3_ip4_config_start(NMModem * modem, return NM_ACT_STAGE_RETURN_POSTPONE; } +static void +context_properties_cb(GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + NMModemOfono * self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *properties = NULL; + gs_unref_variant GVariant *settings = NULL; + gs_unref_variant GVariant *v_dict = NULL; + gboolean active; + + self = NM_MODEM_OFONO(user_data); + priv = NM_MODEM_OFONO_GET_PRIVATE(self); + + properties = g_dbus_proxy_call_finish(proxy, result, &error); + + if (!properties) { + _LOGW("ofono: connection failed: no context properties returned %s", error->message); + g_clear_error(&error); + goto error; + } + + v_dict = g_variant_get_child_value(properties, 0); + if (!v_dict || !g_variant_is_of_type(v_dict, G_VARIANT_TYPE_VARDICT)) { + _LOGW("ofono: connection failed; could not read connection properties"); + goto error; + } + + if (!g_variant_lookup(v_dict, "Active", "b", &active)) { + _LOGW("ofono: connection failed; can not read 'Active' property"); + goto error; + } + + /* Watch for custom ofono PropertyChanged signals */ + _nm_dbus_signal_connect(priv->context_proxy, + "PropertyChanged", + G_VARIANT_TYPE("(sv)"), + G_CALLBACK(context_property_changed), + self); + + if (active) { + _LOGD("ofono: connection is already Active"); + + settings = g_variant_lookup_value(v_dict, "Settings", G_VARIANT_TYPE_VARDICT); + if (settings == NULL) { + _LOGW("ofono: connection failed; can not read 'Settings' property"); + goto error; + } + + handle_settings(settings, user_data); + } else { + g_dbus_proxy_call(priv->context_proxy, + "SetProperty", + g_variant_new("(sv)", "Active", g_variant_new("b", TRUE)), + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) stage1_prepare_done, + self); + } + return; + +error: + nm_modem_emit_prepare_result(NM_MODEM(self), FALSE, NM_DEVICE_STATE_REASON_MODEM_BUSY); +} + static void context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { @@ -973,19 +1042,15 @@ context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) */ g_clear_object(&priv->ip4_config); - _nm_dbus_signal_connect(priv->context_proxy, - "PropertyChanged", - G_VARIANT_TYPE("(sv)"), - G_CALLBACK(context_property_changed), - self); - + /* We need to directly query ConnectionContextinteface to get the current + * property values */ g_dbus_proxy_call(priv->context_proxy, - "SetProperty", - g_variant_new("(sv)", "Active", g_variant_new("b", TRUE)), + "GetProperties", + NULL, G_DBUS_CALL_FLAGS_NONE, 20000, - priv->context_proxy_cancellable, - stage1_prepare_done, + NULL, + (GAsyncReadyCallback) context_properties_cb, self); } @@ -1069,6 +1134,7 @@ modem_act_stage1_prepare(NMModem * modem, _LOGI("activating context %s", priv->context_path); + update_modem_state(self); if (nm_modem_get_state(modem) == NM_MODEM_STATE_REGISTERED) { do_context_activate(self); } else { diff --git a/src/core/devices/wwan/nm-modem-ofono.h b/src/core/devices/wwan/nm-modem-ofono.h index 260e3954..ebe21023 100644 --- a/src/core/devices/wwan/nm-modem-ofono.h +++ b/src/core/devices/wwan/nm-modem-ofono.h @@ -25,6 +25,8 @@ #define OFONO_DBUS_INTERFACE_CONNECTION_CONTEXT "org.ofono.ConnectionContext" #define OFONO_DBUS_INTERFACE_SIM_MANAGER "org.ofono.SimManager" +#define OFONO_ERROR_IN_PROGRESS "org.ofono.Error.InProgress" + typedef struct _NMModemOfono NMModemOfono; typedef struct _NMModemOfonoClass NMModemOfonoClass; diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index 0d334fa4..15baa677 100644 --- a/src/core/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -10,10 +10,11 @@ #include #include +#include #include -#include "nm-core-internal.h" -#include "platform/nm-platform.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nm-platform.h" #include "nm-setting-connection.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" @@ -799,8 +800,10 @@ nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config) g_assert(address); if (address->plen == 32) - nm_platform_link_set_noarp(nm_device_get_platform(device), - nm_device_get_ip_ifindex(device)); + nm_platform_link_change_flags(nm_device_get_platform(device), + nm_device_get_ip_ifindex(device), + IFF_NOARP, + TRUE); } } @@ -1199,7 +1202,7 @@ deactivate_cleanup(NMModem *self, NMDevice *device, gboolean stop_ppp_manager) nm_platform_ip_route_flush(platform, AF_UNSPEC, ifindex); nm_platform_ip_address_flush(platform, AF_UNSPEC, ifindex); - nm_platform_link_set_down(platform, ifindex); + nm_platform_link_change_flags(platform, ifindex, IFF_UP, FALSE); } } } diff --git a/src/core/devices/wwan/nm-wwan-factory.c b/src/core/devices/wwan/nm-wwan-factory.c index 5d2ce2b3..0d802ae1 100644 --- a/src/core/devices/wwan/nm-wwan-factory.c +++ b/src/core/devices/wwan/nm-wwan-factory.c @@ -12,7 +12,7 @@ #include "nm-setting-cdma.h" #include "nm-modem-manager.h" #include "nm-device-modem.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" /*****************************************************************************/ diff --git a/src/core/dhcp/meson.build b/src/core/dhcp/meson.build index 1bb004cd..ddaa32fb 100644 --- a/src/core/dhcp/meson.build +++ b/src/core/dhcp/meson.build @@ -3,10 +3,11 @@ executable( 'nm-dhcp-helper', 'nm-dhcp-helper.c', - dependencies: glib_nm_default_dep, - c_args: [ - '-DG_LOG_DOMAIN="nm-dhcp-helper"', + include_directories: [ + src_inc, + top_inc, ], + dependencies: glib_dep, link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, install: true, diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index 3b0343fd..ab8243d0 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -13,15 +13,16 @@ #include #include #include +#include -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-glib-aux/nm-random-utils.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-random-utils.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-options.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-dhcp-client-logging.h" @@ -33,6 +34,7 @@ static guint signals[LAST_SIGNAL] = {0}; NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient, PROP_ADDR_FAMILY, + PROP_ANYCAST_ADDRESS, PROP_FLAGS, PROP_HWADDR, PROP_BROADCAST_HWADDR, @@ -61,6 +63,7 @@ typedef struct _NMDhcpClientPrivate { char * hostname; const char ** reject_servers; char * mud_url; + char * anycast_address; GBytes * vendor_class_identifier; pid_t pid; guint timeout_id; @@ -73,8 +76,7 @@ typedef struct _NMDhcpClientPrivate { guint32 iaid; NMDhcpState state; NMDhcpHostnameFlags hostname_flags; - bool info_only : 1; - bool use_fqdn : 1; + NMDhcpClientFlags client_flags; bool iaid_explicit : 1; } NMDhcpClientPrivate; @@ -281,6 +283,14 @@ nm_dhcp_client_set_client_id_bin(NMDhcpClient *self, _set_client_id(self, b, TRUE); } +const char * +nm_dhcp_client_get_anycast_address(NMDhcpClient *self) +{ + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); + + return NM_DHCP_CLIENT_GET_PRIVATE(self)->anycast_address; +} + const char * nm_dhcp_client_get_hostname(NMDhcpClient *self) { @@ -297,20 +307,12 @@ nm_dhcp_client_get_hostname_flags(NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname_flags; } -gboolean -nm_dhcp_client_get_info_only(NMDhcpClient *self) +NMDhcpClientFlags +nm_dhcp_client_get_client_flags(NMDhcpClient *self) { - g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_CLIENT_FLAGS_NONE); - return NM_DHCP_CLIENT_GET_PRIVATE(self)->info_only; -} - -gboolean -nm_dhcp_client_get_use_fqdn(NMDhcpClient *self) -{ - g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); - - return NM_DHCP_CLIENT_GET_PRIVATE(self)->use_fqdn; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_flags; } const char * @@ -339,29 +341,25 @@ nm_dhcp_client_get_reject_servers(NMDhcpClient *self) /*****************************************************************************/ -static const char *state_table[NM_DHCP_STATE_MAX + 1] = { - [NM_DHCP_STATE_UNKNOWN] = "unknown", - [NM_DHCP_STATE_BOUND] = "bound", - [NM_DHCP_STATE_EXTENDED] = "extended", - [NM_DHCP_STATE_TIMEOUT] = "timeout", - [NM_DHCP_STATE_EXPIRE] = "expire", - [NM_DHCP_STATE_DONE] = "done", - [NM_DHCP_STATE_FAIL] = "fail", - [NM_DHCP_STATE_TERMINATED] = "terminated", -}; - -static const char * -state_to_string(NMDhcpState state) -{ - if ((gsize) state < G_N_ELEMENTS(state_table)) - return state_table[state]; - return NULL; -} +NM_UTILS_LOOKUP_STR_DEFINE(nm_dhcp_state_to_string, + NMDhcpState, + NM_UTILS_LOOKUP_DEFAULT(NULL), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_BOUND, "bound"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_DONE, "done"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_EXPIRE, "expire"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_EXTENDED, "extended"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_FAIL, "fail"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_NOOP, "noop"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_TERMINATED, "terminated"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_TIMEOUT, "timeout"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_ITEM_IGNORE(__NM_DHCP_STATE_MAX), ); static NMDhcpState reason_to_state(NMDhcpClient *self, const char *iface, const char *reason) { - if (g_ascii_strcasecmp(reason, "bound") == 0 || g_ascii_strcasecmp(reason, "bound6") == 0) + if (g_ascii_strcasecmp(reason, "bound") == 0 || g_ascii_strcasecmp(reason, "bound6") == 0 + || g_ascii_strcasecmp(reason, "static") == 0) return NM_DHCP_STATE_BOUND; else if (g_ascii_strcasecmp(reason, "renew") == 0 || g_ascii_strcasecmp(reason, "renew6") == 0 || g_ascii_strcasecmp(reason, "reboot") == 0 @@ -493,8 +491,8 @@ nm_dhcp_client_set_state(NMDhcpClient *self, const char *addr = nm_g_hash_table_lookup(options, req_str); _LOGI("state changed %s -> %s%s%s%s", - state_to_string(priv->state), - state_to_string(new_state), + nm_dhcp_state_to_string(priv->state), + nm_dhcp_state_to_string(new_state), NM_PRINT_FMT_QUOTED(addr, ", address=", addr, "", "")); } @@ -519,20 +517,12 @@ daemon_watch_cb(GPid pid, int status, gpointer user_data) { NMDhcpClient * self = NM_DHCP_CLIENT(user_data); NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + gs_free char * desc = NULL; g_return_if_fail(priv->watch_id); priv->watch_id = 0; - if (WIFEXITED(status)) - _LOGI("client pid %d exited with status %d", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - _LOGI("client pid %d killed by signal %d", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - _LOGI("client pid %d stopped by signal %d", pid, WSTOPSIG(status)); - else if (WIFCONTINUED(status)) - _LOGI("client pid %d resumed (by SIGCONT)", pid); - else - _LOGW("client died abnormally"); + _LOGI("client pid %d %s", pid, (desc = nm_utils_get_process_exit_status_desc(status))); priv->pid = -1; @@ -583,7 +573,6 @@ nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid) gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, GBytes * client_id, - const char * dhcp_anycast_addr, const char * last_ip4_address, GError ** error) { @@ -603,10 +592,7 @@ nm_dhcp_client_start_ip4(NMDhcpClient *self, nm_dhcp_client_set_client_id(self, client_id); - return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, - dhcp_anycast_addr, - last_ip4_address, - error); + return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, last_ip4_address, error); } gboolean @@ -643,7 +629,6 @@ gboolean nm_dhcp_client_start_ip6(NMDhcpClient * self, GBytes * client_id, gboolean enforce_duid, - const char * dhcp_anycast_addr, const struct in6_addr * ll_addr, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, @@ -672,8 +657,11 @@ nm_dhcp_client_start_ip6(NMDhcpClient * self, else _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); - return NM_DHCP_CLIENT_GET_CLASS(self) - ->ip6_start(self, dhcp_anycast_addr, ll_addr, privacy, needed_prefixes, error); + return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self, + ll_addr, + privacy, + needed_prefixes, + error); } void @@ -903,8 +891,8 @@ nm_dhcp_client_handle_event(gpointer unused, old_state = priv->state; new_state = reason_to_state(self, priv->iface, reason); _LOGD("DHCP state '%s' -> '%s' (reason: '%s')", - state_to_string(old_state), - state_to_string(new_state), + nm_dhcp_state_to_string(old_state), + nm_dhcp_state_to_string(new_state), reason); if (new_state == NM_DHCP_STATE_NOOP) @@ -935,12 +923,12 @@ nm_dhcp_client_handle_event(gpointer unused, priv->route_metric)); } else { prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options); - ip_config = NM_IP_CONFIG_CAST( - nm_dhcp_utils_ip6_config_from_options(nm_dhcp_client_get_multi_idx(self), - priv->ifindex, - priv->iface, - str_options, - priv->info_only)); + ip_config = NM_IP_CONFIG_CAST(nm_dhcp_utils_ip6_config_from_options( + nm_dhcp_client_get_multi_idx(self), + priv->ifindex, + priv->iface, + str_options, + NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY))); } } else g_warn_if_reached(); @@ -1057,11 +1045,8 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps case PROP_FLAGS: /* construct-only */ flags = g_value_get_uint(value); - nm_assert( - (flags & ~((guint)(NM_DHCP_CLIENT_FLAGS_INFO_ONLY | NM_DHCP_CLIENT_FLAGS_USE_FQDN))) - == 0); - priv->info_only = NM_FLAGS_HAS(flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY); - priv->use_fqdn = NM_FLAGS_HAS(flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN); + nm_assert(!NM_FLAGS_ANY(flags, ~((guint) NM_DHCP_CLIENT_FLAGS_ALL))); + priv->client_flags = flags; break; case PROP_MULTI_IDX: /* construct-only */ @@ -1085,6 +1070,10 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps /* construct-only */ priv->hwaddr = g_value_dup_boxed(value); break; + case PROP_ANYCAST_ADDRESS: + /* construct-only */ + priv->anycast_address = g_value_dup_string(value); + break; case PROP_BROADCAST_HWADDR: /* construct-only */ priv->bcast_hwaddr = g_value_dup_boxed(value); @@ -1158,6 +1147,28 @@ nm_dhcp_client_init(NMDhcpClient *self) priv->pid = -1; } +#if NM_MORE_ASSERTS +static void +constructed(GObject *object) +{ + NMDhcpClient * self = NM_DHCP_CLIENT(object); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + + /* certain flags only make sense with certain address family. Assert + * for that. */ + if (NM_IS_IPv4(priv->addr_family)) + nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY)); + else { + nm_assert(NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN)); + nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)); + } + + nm_assert(!priv->anycast_address || nm_utils_hwaddr_valid(priv->anycast_address, ETH_ALEN)); + + G_OBJECT_CLASS(nm_dhcp_client_parent_class)->constructed(object); +} +#endif + static void dispose(GObject *object) { @@ -1177,6 +1188,7 @@ dispose(GObject *object) nm_clear_g_free(&priv->iface); nm_clear_g_free(&priv->hostname); nm_clear_g_free(&priv->uuid); + nm_clear_g_free(&priv->anycast_address); nm_clear_g_free(&priv->mud_url); nm_clear_g_free(&priv->reject_servers); nm_clear_pointer(&priv->client_id, g_bytes_unref); @@ -1196,6 +1208,9 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class) g_type_class_add_private(client_class, sizeof(NMDhcpClientPrivate)); +#if NM_MORE_ASSERTS + object_class->constructed = constructed; +#endif object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; @@ -1248,6 +1263,13 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class) AF_UNSPEC, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ANYCAST_ADDRESS] = + g_param_spec_string(NM_DHCP_CLIENT_ANYCAST_ADDRESS, + "", + "", + NULL, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_UUID] = g_param_spec_string(NM_DHCP_CLIENT_UUID, "", diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index af3406cc..3fe1b34e 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -25,6 +25,7 @@ (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass)) #define NM_DHCP_CLIENT_ADDR_FAMILY "addr-family" +#define NM_DHCP_CLIENT_ANYCAST_ADDRESS "anycast-address" #define NM_DHCP_CLIENT_FLAGS "flags" #define NM_DHCP_CLIENT_HWADDR "hwaddr" #define NM_DHCP_CLIENT_BROADCAST_HWADDR "broadcast-hwaddr" @@ -60,6 +61,8 @@ typedef enum { NM_DHCP_STATE_MAX = __NM_DHCP_STATE_MAX - 1, } NMDhcpState; +const char *nm_dhcp_state_to_string(NMDhcpState state); + struct _NMDhcpClientPrivate; typedef struct { @@ -68,25 +71,27 @@ typedef struct { CList dhcp_client_lst; } NMDhcpClient; -typedef enum { - NM_DHCP_CLIENT_FLAGS_INFO_ONLY = (1LL << 0), - NM_DHCP_CLIENT_FLAGS_USE_FQDN = (1LL << 1), +typedef enum _nm_packed { + NM_DHCP_CLIENT_FLAGS_NONE = 0, + + NM_DHCP_CLIENT_FLAGS_INFO_ONLY = (1LL << 0), + NM_DHCP_CLIENT_FLAGS_USE_FQDN = (1LL << 1), + NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST = (1LL << 2), + + _NM_DHCP_CLIENT_FLAGS_LAST, + NM_DHCP_CLIENT_FLAGS_ALL = ((_NM_DHCP_CLIENT_FLAGS_LAST - 1) << 1) - 1, } NMDhcpClientFlags; typedef struct { GObjectClass parent; - gboolean (*ip4_start)(NMDhcpClient *self, - const char * anycast_addr, - const char * last_ip4_address, - GError ** error); + gboolean (*ip4_start)(NMDhcpClient *self, const char *last_ip4_address, GError **error); gboolean (*accept)(NMDhcpClient *self, GError **error); gboolean (*decline)(NMDhcpClient *self, const char *error_message, GError **error); gboolean (*ip6_start)(NMDhcpClient * self, - const char * anycast_addr, const struct in6_addr * ll_addr, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, @@ -126,6 +131,8 @@ GBytes *nm_dhcp_client_get_hw_addr(NMDhcpClient *self); GBytes *nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self); +const char *nm_dhcp_client_get_anycast_address(NMDhcpClient *self); + guint32 nm_dhcp_client_get_route_table(NMDhcpClient *self); void nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table); @@ -148,22 +155,18 @@ const char *const *nm_dhcp_client_get_reject_servers(NMDhcpClient *self); NMDhcpHostnameFlags nm_dhcp_client_get_hostname_flags(NMDhcpClient *self); -gboolean nm_dhcp_client_get_info_only(NMDhcpClient *self); - -gboolean nm_dhcp_client_get_use_fqdn(NMDhcpClient *self); +NMDhcpClientFlags nm_dhcp_client_get_client_flags(NMDhcpClient *self); GBytes *nm_dhcp_client_get_vendor_class_identifier(NMDhcpClient *self); gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, GBytes * client_id, - const char * dhcp_anycast_addr, const char * last_ip4_address, GError ** error); gboolean nm_dhcp_client_start_ip6(NMDhcpClient * self, GBytes * client_id, gboolean enforce_duid, - const char * dhcp_anycast_addr, const struct in6_addr * ll_addr, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c index ad1e097f..4284a852 100644 --- a/src/core/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c @@ -12,12 +12,12 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-dhcp-utils.h" #include "nm-ip4-config.h" #include "nm-utils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "NetworkManagerUtils.h" #define TIMEOUT_TAG "timeout " @@ -291,7 +291,7 @@ char * nm_dhcp_dhclient_create_config(const char * interface, int addr_family, GBytes * client_id, - const char * anycast_addr, + const char * anycast_address, const char * hostname, guint32 timeout, gboolean use_fqdn, @@ -308,7 +308,8 @@ nm_dhcp_dhclient_create_config(const char * interface, gboolean reset_reqlist = FALSE; int i; - g_return_val_if_fail(!anycast_addr || nm_utils_hwaddr_valid(anycast_addr, ETH_ALEN), NULL); + g_return_val_if_fail(!anycast_address || nm_utils_hwaddr_valid(anycast_address, ETH_ALEN), + NULL); g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NULL); g_return_val_if_fail(!reject_servers || addr_family == AF_INET, NULL); nm_assert(!out_new_client_id || !*out_new_client_id); @@ -508,14 +509,14 @@ nm_dhcp_dhclient_create_config(const char * interface, g_string_append_c(new_contents, '\n'); - if (anycast_addr) { + if (anycast_address) { g_string_append_printf(new_contents, "interface \"%s\" {\n" " initial-interval 1; \n" " anycast-mac ethernet %s;\n" "}\n", interface, - anycast_addr); + anycast_address); } return g_string_free(g_steal_pointer(&new_contents), FALSE); diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c index c42a0ba5..4a11250f 100644 --- a/src/core/dhcp/nm-dhcp-dhclient.c +++ b/src/core/dhcp/nm-dhcp-dhclient.c @@ -21,7 +21,7 @@ #include #include - #include "nm-glib-aux/nm-dedup-multi.h" + #include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-utils.h" #include "nm-dhcp-dhclient-utils.h" @@ -151,7 +151,7 @@ merge_dhclient_config(NMDhcpDhclient * self, const char * iface, const char * conf_file, GBytes * client_id, - const char * anycast_addr, + const char * anycast_address, const char * hostname, guint32 timeout, gboolean use_fqdn, @@ -180,7 +180,7 @@ merge_dhclient_config(NMDhcpDhclient * self, new = nm_dhcp_dhclient_create_config(iface, addr_family, client_id, - anycast_addr, + anycast_address, hostname, timeout, use_fqdn, @@ -280,7 +280,7 @@ create_dhclient_config(NMDhcpDhclient * self, const char * iface, const char * uuid, GBytes * client_id, - const char * dhcp_anycast_addr, + const char * anycast_address, const char * hostname, guint32 timeout, gboolean use_fqdn, @@ -312,7 +312,7 @@ create_dhclient_config(NMDhcpDhclient * self, iface, new, client_id, - dhcp_anycast_addr, + anycast_address, hostname, timeout, use_fqdn, @@ -435,6 +435,12 @@ dhclient_start(NMDhcpClient *client, if (release) g_ptr_array_add(argv, (gpointer) "-r"); + if (!release + && NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)), + NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)) { + g_ptr_array_add(argv, (gpointer) "-B"); + } + if (addr_family == AF_INET6) { g_ptr_array_add(argv, (gpointer) "-6"); @@ -508,10 +514,7 @@ dhclient_start(NMDhcpClient *client, } static gboolean -ip4_start(NMDhcpClient *client, - const char * dhcp_anycast_addr, - const char * last_ip4_address, - GError ** error) +ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) { NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client); NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); @@ -520,19 +523,20 @@ ip4_start(NMDhcpClient *client, client_id = nm_dhcp_client_get_client_id(client); - priv->conf_file = create_dhclient_config(self, - AF_INET, - nm_dhcp_client_get_iface(client), - nm_dhcp_client_get_uuid(client), - client_id, - dhcp_anycast_addr, - nm_dhcp_client_get_hostname(client), - nm_dhcp_client_get_timeout(client), - nm_dhcp_client_get_use_fqdn(client), - nm_dhcp_client_get_hostname_flags(client), - nm_dhcp_client_get_mud_url(client), - nm_dhcp_client_get_reject_servers(client), - &new_client_id); + priv->conf_file = create_dhclient_config( + self, + AF_INET, + nm_dhcp_client_get_iface(client), + nm_dhcp_client_get_uuid(client), + client_id, + nm_dhcp_client_get_anycast_address(client), + nm_dhcp_client_get_hostname(client), + nm_dhcp_client_get_timeout(client), + NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN), + nm_dhcp_client_get_hostname_flags(client), + nm_dhcp_client_get_mud_url(client), + nm_dhcp_client_get_reject_servers(client), + &new_client_id); if (!priv->conf_file) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, @@ -549,7 +553,6 @@ ip4_start(NMDhcpClient *client, static gboolean ip6_start(NMDhcpClient * client, - const char * dhcp_anycast_addr, const struct in6_addr * ll_addr, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, @@ -566,7 +569,7 @@ ip6_start(NMDhcpClient * client, nm_dhcp_client_get_iface(client), nm_dhcp_client_get_uuid(client), NULL, - dhcp_anycast_addr, + nm_dhcp_client_get_anycast_address(client), nm_dhcp_client_get_hostname(client), nm_dhcp_client_get_timeout(client), TRUE, @@ -582,7 +585,10 @@ ip6_start(NMDhcpClient * client, } return dhclient_start(client, - nm_dhcp_client_get_info_only(NM_DHCP_CLIENT(self)) ? "-S" : "-N", + NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)), + NM_DHCP_CLIENT_FLAGS_INFO_ONLY) + ? "-S" + : "-N", FALSE, NULL, needed_prefixes, diff --git a/src/core/dhcp/nm-dhcp-dhcpcanon.c b/src/core/dhcp/nm-dhcp-dhcpcanon.c index 3504a048..f3a52ea9 100644 --- a/src/core/dhcp/nm-dhcp-dhcpcanon.c +++ b/src/core/dhcp/nm-dhcp-dhcpcanon.c @@ -161,10 +161,7 @@ dhcpcanon_start(NMDhcpClient *client, } static gboolean -ip4_start(NMDhcpClient *client, - const char * dhcp_anycast_addr, - const char * last_ip4_address, - GError ** error) +ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) { return dhcpcanon_start(client, NULL, NULL, FALSE, NULL, 0, error); } diff --git a/src/core/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c index cdb266ed..605fb84d 100644 --- a/src/core/dhcp/nm-dhcp-dhcpcd.c +++ b/src/core/dhcp/nm-dhcp-dhcpcd.c @@ -65,10 +65,7 @@ nm_dhcp_dhcpcd_get_path(void) } static gboolean -ip4_start(NMDhcpClient *client, - const char * dhcp_anycast_addr, - const char * last_ip4_address, - GError ** error) +ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) { NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client); gs_unref_ptrarray GPtrArray *argv = NULL; @@ -122,7 +119,7 @@ ip4_start(NMDhcpClient *client, hostname = nm_dhcp_client_get_hostname(client); if (hostname) { - if (nm_dhcp_client_get_use_fqdn(client)) { + if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) { g_ptr_array_add(argv, (gpointer) "-h"); g_ptr_array_add(argv, (gpointer) hostname); g_ptr_array_add(argv, (gpointer) "-F"); diff --git a/src/core/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c index 0f98add1..56d20101 100644 --- a/src/core/dhcp/nm-dhcp-helper.c +++ b/src/core/dhcp/nm-dhcp-helper.c @@ -3,13 +3,13 @@ * Copyright (C) 2007 - 2013 Red Hat, Inc. */ -#include "nm-glib-aux/nm-default-glib.h" +#include "libnm-glib-aux/nm-default-glib.h" #include #include #include -#include "nm-utils/nm-vpn-plugin-macros.h" +#include "libnm-glib-aux/nm-logging-syslog.h" #include "nm-dhcp-helper-api.h" @@ -92,7 +92,7 @@ build_signal_parameters(void) g_variant_builder_add(&builder, "{sv}", name, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, val, strlen(val), 1)); + nm_g_variant_new_ay((const guint8 *) val, strlen(val))); next:; } @@ -154,7 +154,7 @@ do_connect: error->message, try_count, (long long) (time_end - time_remaining - time_start) / 1000); - interval = NM_CLAMP((gint64)(100L * (1L << NM_MIN(try_count, 31))), 5000, 100000); + interval = NM_CLAMP((gint64) (100L * (1L << NM_MIN(try_count, 31))), 5000, 100000); g_usleep(NM_MIN(interval, time_remaining)); g_clear_error(&error); goto do_connect; @@ -199,7 +199,7 @@ do_notify: * do some retry. */ if (remaining_time > 0) { _LOGi("failure to call notify: %s (retry %u)", error->message, try_count); - interval = NM_CLAMP((gint64)(100L * (1L << NM_MIN(try_count, 31))), 5000, 25000); + interval = NM_CLAMP((gint64) (100L * (1L << NM_MIN(try_count, 31))), 5000, 25000); g_usleep(NM_MIN(interval, remaining_time)); g_clear_error(&error); goto do_notify; diff --git a/src/core/dhcp/nm-dhcp-listener.c b/src/core/dhcp/nm-dhcp-listener.c index 1673bbb7..b8bb3c33 100644 --- a/src/core/dhcp/nm-dhcp-listener.c +++ b/src/core/dhcp/nm-dhcp-listener.c @@ -16,7 +16,7 @@ #include "nm-dhcp-helper-api.h" #include "nm-dhcp-client.h" #include "nm-dhcp-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" diff --git a/src/core/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c index bc114ad8..44b8ede2 100644 --- a/src/core/dhcp/nm-dhcp-manager.c +++ b/src/core/dhcp/nm-dhcp-manager.c @@ -16,8 +16,8 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" -#include "systemd/nm-sd-utils-shared.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" #include "nm-config.h" #include "NetworkManagerUtils.h" @@ -213,12 +213,11 @@ client_start(NMDhcpManager * self, guint32 iaid, gboolean iaid_explicit, guint32 timeout, - const char * dhcp_anycast_addr, + NMDhcpClientFlags client_flags, + const char * anycast_address, const char * hostname, - gboolean hostname_use_fqdn, NMDhcpHostnameFlags hostname_flags, const char * mud_url, - gboolean info_only, NMSettingIP6ConfigPrivacy privacy, const char * last_ip4_address, guint needed_prefixes, @@ -241,6 +240,7 @@ client_start(NMDhcpManager * self, || g_bytes_get_size(vendor_class_identifier) <= 255, NULL); g_return_val_if_fail(!error || !*error, NULL); + nm_assert(!NM_FLAGS_ANY(client_flags, ~NM_DHCP_CLIENT_FLAGS_ALL)); if (addr_family == AF_INET) { if (!hwaddr || !bcast_hwaddr) { @@ -252,7 +252,7 @@ client_start(NMDhcpManager * self, } hwaddr_len = g_bytes_get_size(hwaddr); - if (hwaddr_len == 0 || hwaddr_len > NM_UTILS_HWADDR_LEN_MAX) { + if (hwaddr_len == 0 || hwaddr_len > _NM_UTILS_HWADDR_LEN_MAX) { nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address"); g_return_val_if_reached(NULL); } @@ -263,12 +263,14 @@ client_start(NMDhcpManager * self, } if (hostname) { - if ((hostname_use_fqdn && !nm_sd_dns_name_is_valid(hostname)) - || (!hostname_use_fqdn && !nm_sd_hostname_is_valid(hostname, FALSE))) { + gboolean use_fqdn = NM_FLAGS_HAS(client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN); + + if ((use_fqdn && !nm_sd_dns_name_is_valid(hostname)) + || (!use_fqdn && !nm_sd_hostname_is_valid(hostname, FALSE))) { nm_log_warn(LOGD_DHCP, "dhcp%c: %s '%s' is invalid, will be ignored", nm_utils_addr_family_to_char(addr_family), - hostname_use_fqdn ? "FQDN" : "hostname", + use_fqdn ? "FQDN" : "hostname", hostname); hostname = NULL; } @@ -334,8 +336,9 @@ client_start(NMDhcpManager * self, NM_DHCP_CLIENT_REJECT_SERVERS, reject_servers, NM_DHCP_CLIENT_FLAGS, - (guint)(0 | (hostname_use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : 0) - | (info_only ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY : 0)), + (guint) client_flags, + NM_DHCP_CLIENT_ANYCAST_ADDRESS, + anycast_address, NULL); nm_assert(client && c_list_is_empty(&client->dhcp_client_lst)); c_list_link_tail(&priv->dhcp_client_lst_head, &client->dhcp_client_lst); @@ -371,16 +374,11 @@ client_start(NMDhcpManager * self, */ if (addr_family == AF_INET) { - success = nm_dhcp_client_start_ip4(client, - dhcp_client_id, - dhcp_anycast_addr, - last_ip4_address, - error); + success = nm_dhcp_client_start_ip4(client, dhcp_client_id, last_ip4_address, error); } else { success = nm_dhcp_client_start_ip6(client, dhcp_client_id, enforce_duid, - dhcp_anycast_addr, ipv6_ll_addr, privacy, needed_prefixes, @@ -406,6 +404,7 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self, const char * uuid, guint32 route_table, guint32 route_metric, + NMDhcpClientFlags client_flags, gboolean send_hostname, const char * dhcp_hostname, const char * dhcp_fqdn, @@ -413,7 +412,7 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self, const char * mud_url, GBytes * dhcp_client_id, guint32 timeout, - const char * dhcp_anycast_addr, + const char * anycast_address, const char * last_ip_address, GBytes * vendor_class_identifier, const char *const * reject_servers, @@ -425,6 +424,10 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self, gboolean use_fqdn = FALSE; char * dot; + /* these flags are set automatically/prohibited, and not free to set to the caller. */ + nm_assert(!NM_FLAGS_ANY(client_flags, + NM_DHCP_CLIENT_FLAGS_USE_FQDN | NM_DHCP_CLIENT_FLAGS_INFO_ONLY)); + g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL); priv = NM_DHCP_MANAGER_GET_PRIVATE(self); @@ -451,34 +454,34 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self, } } - return client_start(self, - AF_INET, - multi_idx, - iface, - ifindex, - hwaddr, - bcast_hwaddr, - uuid, - route_table, - route_metric, - NULL, - dhcp_client_id, - FALSE, - 0, - FALSE, - timeout, - dhcp_anycast_addr, - hostname, - use_fqdn, - hostname_flags, - mud_url, - FALSE, - 0, - last_ip_address, - 0, - vendor_class_identifier, - reject_servers, - error); + return client_start( + self, + AF_INET, + multi_idx, + iface, + ifindex, + hwaddr, + bcast_hwaddr, + uuid, + route_table, + route_metric, + NULL, + dhcp_client_id, + FALSE, + 0, + FALSE, + timeout, + client_flags | (use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : NM_DHCP_CLIENT_FLAGS_NONE), + anycast_address, + hostname, + hostname_flags, + mud_url, + 0, + last_ip_address, + 0, + vendor_class_identifier, + reject_servers, + error); } /* Caller owns a reference to the NMDhcpClient on return */ @@ -491,6 +494,7 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self, const char * uuid, guint32 route_table, guint32 route_metric, + NMDhcpClientFlags client_flags, gboolean send_hostname, const char * dhcp_hostname, NMDhcpHostnameFlags hostname_flags, @@ -500,8 +504,7 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self, guint32 iaid, gboolean iaid_explicit, guint32 timeout, - const char * dhcp_anycast_addr, - gboolean info_only, + const char * anycast_address, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, GError ** error) @@ -509,6 +512,9 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self, NMDhcpManagerPrivate *priv; const char * hostname = NULL; + /* this flag is set automatically, and not free to set to the caller. */ + nm_assert(!NM_FLAGS_ANY(client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN)); + g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL); priv = NM_DHCP_MANAGER_GET_PRIVATE(self); @@ -532,12 +538,11 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self, iaid, iaid_explicit, timeout, - dhcp_anycast_addr, + client_flags | NM_DHCP_CLIENT_FLAGS_USE_FQDN, + anycast_address, hostname, - TRUE, hostname_flags, mud_url, - info_only, privacy, NULL, needed_prefixes, diff --git a/src/core/dhcp/nm-dhcp-manager.h b/src/core/dhcp/nm-dhcp-manager.h index f7aba8a0..ce160437 100644 --- a/src/core/dhcp/nm-dhcp-manager.h +++ b/src/core/dhcp/nm-dhcp-manager.h @@ -41,6 +41,7 @@ NMDhcpClient *nm_dhcp_manager_start_ip4(NMDhcpManager * manager, const char * uuid, guint32 route_table, guint32 route_metric, + NMDhcpClientFlags client_flags, gboolean send_hostname, const char * dhcp_hostname, const char * dhcp_fqdn, @@ -48,7 +49,7 @@ NMDhcpClient *nm_dhcp_manager_start_ip4(NMDhcpManager * manager, const char * mud_url, GBytes * dhcp_client_id, guint32 timeout, - const char * dhcp_anycast_addr, + const char * anycast_address, const char * last_ip_address, GBytes * vendor_class_identifier, const char *const * reject_servers, @@ -62,6 +63,7 @@ NMDhcpClient *nm_dhcp_manager_start_ip6(NMDhcpManager * manager, const char * uuid, guint32 route_table, guint32 route_metric, + NMDhcpClientFlags client_flags, gboolean send_hostname, const char * dhcp_hostname, NMDhcpHostnameFlags hostname_flags, @@ -71,8 +73,7 @@ NMDhcpClient *nm_dhcp_manager_start_ip6(NMDhcpManager * manager, guint32 iaid, gboolean iaid_explicit, guint32 timeout, - const char * dhcp_anycast_addr, - gboolean info_only, + const char * anycast_address, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, GError ** error); diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index c8b80ea6..4bb6c833 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -13,9 +13,9 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-std-aux/unaligned.h" -#include "nm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-std-aux/unaligned.h" +#include "libnm-glib-aux/nm-str-buf.h" #include "nm-utils.h" #include "nm-config.h" @@ -23,11 +23,11 @@ #include "nm-dhcp-options.h" #include "nm-core-utils.h" #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-dhcp-client-logging.h" #include "n-dhcp4/src/n-dhcp4.h" -#include "systemd/nm-sd-utils-shared.h" -#include "systemd/nm-sd-utils-dhcp.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" +#include "libnm-systemd-core/nm-sd-utils-dhcp.h" /*****************************************************************************/ @@ -694,12 +694,40 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, /* https://tools.ietf.org/html/rfc2132#section-8.1 */ - v_str = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free); + v_str = nm_utils_buf_utf8safe_escape((char *) l_data, + l_data_len, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &to_free); nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str ?: ""); nm_ip4_config_set_nis_domain(ip4_config, v_str ?: ""); } + r = n_dhcp4_client_lease_get_file(lease, &v_str); + if (r == 0) { + gs_free char *to_free = NULL; + + v_str = nm_utils_buf_utf8safe_escape(v_str, + -1, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &to_free); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_FILENAME, v_str ?: ""); + } + + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, &l_data, &l_data_len); + if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) { + gs_free char *to_free = NULL; + + v_str = nm_utils_buf_utf8safe_escape((char *) l_data, + l_data_len, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &to_free); + nm_dhcp_option_add_option(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, + v_str ?: ""); + } + lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf); lease_parse_address_list(lease, @@ -874,7 +902,7 @@ dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data) } static gboolean -nettools_create(NMDhcpNettools *self, const char *dhcp_anycast_addr, GError **error) +nettools_create(NMDhcpNettools *self, GError **error) { NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); nm_auto(n_dhcp4_client_config_freep) NDhcp4ClientConfig *config = NULL; @@ -893,6 +921,8 @@ nettools_create(NMDhcpNettools *self, const char *dhcp_anycast_addr, GError **er g_return_val_if_fail(!priv->client, FALSE); + /* TODO: honor nm_dhcp_client_get_anycast_address() */ + hwaddr = nm_dhcp_client_get_hw_addr(NM_DHCP_CLIENT(self)); if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len)) || (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) { @@ -941,9 +971,13 @@ nettools_create(NMDhcpNettools *self, const char *dhcp_anycast_addr, GError **er n_dhcp4_client_config_set_transport(config, transport); n_dhcp4_client_config_set_mac(config, hwaddr_arr, hwaddr_len); n_dhcp4_client_config_set_broadcast_mac(config, bcast_hwaddr_arr, bcast_hwaddr_len); + n_dhcp4_client_config_set_request_broadcast( + config, + NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)), + NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)); r = n_dhcp4_client_config_set_client_id(config, client_id_arr, - NM_MIN(client_id_len, 1 + _NM_SD_MAX_CLIENT_ID_LEN)); + NM_MIN(client_id_len, 1 + _NM_MAX_CLIENT_ID_LEN)); if (r) { set_error_nettools(error, r, "failed to set client-id"); return FALSE; @@ -1031,10 +1065,7 @@ fqdn_flags_to_wire(NMDhcpHostnameFlags flags) } static gboolean -ip4_start(NMDhcpClient *client, - const char * dhcp_anycast_addr, - const char * last_ip4_address, - GError ** error) +ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) { nm_auto(n_dhcp4_client_probe_config_freep) NDhcp4ClientProbeConfig *config = NULL; NMDhcpNettools * self = NM_DHCP_NETTOOLS(client); @@ -1048,7 +1079,7 @@ ip4_start(NMDhcpClient *client, g_return_val_if_fail(!priv->probe, FALSE); - if (!nettools_create(self, dhcp_anycast_addr, error)) + if (!nettools_create(self, error)) return FALSE; r = n_dhcp4_client_probe_config_new(&config); @@ -1113,7 +1144,7 @@ ip4_start(NMDhcpClient *client, } hostname = nm_dhcp_client_get_hostname(client); if (hostname) { - if (nm_dhcp_client_get_use_fqdn(client)) { + if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) { uint8_t buffer[255]; NMDhcpHostnameFlags flags; size_t fqdn_len; diff --git a/src/core/dhcp/nm-dhcp-options.c b/src/core/dhcp/nm-dhcp-options.c index 3537cd14..011f23e4 100644 --- a/src/core/dhcp/nm-dhcp-options.c +++ b/src/core/dhcp/nm-dhcp-options.c @@ -7,7 +7,7 @@ #include "nm-dhcp-options.h" -#include "nm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-str-buf.h" /*****************************************************************************/ @@ -169,6 +169,7 @@ const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { REQ(NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NM_FILENAME, "filename", FALSE), }; static const NMDhcpOption *const _sorted_options_4[G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options)] = { @@ -184,7 +185,7 @@ static const NMDhcpOption *const _sorted_options_4[G_N_ELEMENTS(_nm_dhcp_option_ A(98), A(99), A(100), A(101), A(102), A(103), A(104), A(105), A(106), A(107), A(108), A(109), A(110), A(111), A(112), A(113), A(114), A(115), A(116), A(117), A(118), A(119), A(120), A(121), A(122), A(123), A(124), A(125), A(126), A(127), A(128), A(129), A(130), A(131), A(132), A(133), - A(134), A(15), A(135), A(136), A(16), A(137), A(138), A(139), A(140), A(141), + A(134), A(15), A(135), A(136), A(16), A(137), A(138), A(139), A(140), A(141), A(142), #undef A }; @@ -404,7 +405,10 @@ nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options, gs_free char *to_free = NULL; const char * escaped; - escaped = nm_utils_buf_utf8safe_escape((char *) data, n_data, 0, &to_free); + escaped = nm_utils_buf_utf8safe_escape((char *) data, + n_data, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &to_free); nm_dhcp_option_add_option(options, addr_family, option, escaped ?: ""); } diff --git a/src/core/dhcp/nm-dhcp-options.h b/src/core/dhcp/nm-dhcp-options.h index 585f1187..8ed2039d 100644 --- a/src/core/dhcp/nm-dhcp-options.h +++ b/src/core/dhcp/nm-dhcp-options.h @@ -153,6 +153,7 @@ typedef enum { NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS = 1024, NM_DHCP_OPTION_DHCP4_NM_EXPIRY = 1025, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER = 1026, + NM_DHCP_OPTION_DHCP4_NM_FILENAME = 1027, /* 'file' DHCP header */ } NMDhcpOptionDhcp4Options; typedef enum { @@ -185,7 +186,7 @@ typedef struct { bool include; } NMDhcpOption; -extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[142]; +extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[143]; extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[16]; static inline const char * diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index 100807aa..c789aaee 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -13,18 +13,18 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-std-aux/unaligned.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-std-aux/unaligned.h" #include "nm-utils.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-options.h" #include "nm-core-utils.h" #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-dhcp-client-logging.h" -#include "systemd/nm-sd.h" -#include "systemd/nm-sd-utils-dhcp.h" +#include "libnm-systemd-core/nm-sd.h" +#include "libnm-systemd-core/nm-sd-utils-dhcp.h" /*****************************************************************************/ @@ -153,7 +153,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_EXPIRY, - (guint64)(ts_time + a_lifetime)); + (guint64) (ts_time + a_lifetime)); if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) { _nm_utils_inet4_ntop(a_next_server.s_addr, addr_str); @@ -429,18 +429,33 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, num = nm_sd_dhcp_lease_get_private_options(lease, &private_options); if (num > 0) { for (i = 0; i < num; i++) { - char *option_string; - - option_string = nm_utils_bin2hexstr_full(private_options[i].data, - private_options[i].data_len, - ':', - FALSE, - NULL); - if (!options) { - g_free(option_string); + guint8 code = private_options[i].code; + const guint8 *l_data = private_options[i].data; + gsize l_data_len = private_options[i].data_len; + char * option_string; + + if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) { + if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) { + nm_dhcp_option_add_option_utf8safe_escape( + options, + AF_INET, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, + l_data, + l_data_len); + } continue; } - nm_dhcp_option_take_option(options, AF_INET, private_options[i].code, option_string); + if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE) { + /* nettools and dhclient parse option 249 (Microsoft Classless Static Route) + * as fallback for routes and ignores them from private options. + * + * The systemd plugin does not, and for consistency with nettools we + * also don't expose it as private option either. */ + continue; + } + + option_string = nm_utils_bin2hexstr_full(l_data, l_data_len, ':', FALSE, NULL); + nm_dhcp_option_take_option(options, AF_INET, code, option_string); } } NM_SET_OUT(out_options, g_steal_pointer(&options)); @@ -543,10 +558,7 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data) } static gboolean -ip4_start(NMDhcpClient *client, - const char * dhcp_anycast_addr, - const char * last_ip4_address, - GError ** error) +ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) { nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL; NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client); @@ -572,6 +584,8 @@ ip4_start(NMDhcpClient *client, g_return_val_if_fail(!priv->client4, FALSE); g_return_val_if_fail(!priv->client6, FALSE); + /* TODO: honor nm_dhcp_client_get_anycast_address() */ + r = sd_dhcp_client_new(&sd_client, FALSE); if (r < 0) { nm_utils_error_set_errno(error, r, "failed to create dhcp-client: %s"); @@ -632,6 +646,11 @@ ip4_start(NMDhcpClient *client, sd_dhcp_lease_get_address(lease, &last_addr); } + r = sd_dhcp_client_set_request_broadcast(sd_client, + NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), + NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)); + nm_assert(r >= 0); + if (last_addr.s_addr) { r = sd_dhcp_client_set_request_address(sd_client, &last_addr); if (r < 0) { @@ -659,7 +678,7 @@ ip4_start(NMDhcpClient *client, r = sd_dhcp_client_set_client_id(sd_client, client_id_arr[0], client_id_arr + 1, - NM_MIN(client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN)); + NM_MIN(client_id_len - 1, _NM_MAX_CLIENT_ID_LEN)); if (r < 0) { nm_utils_error_set_errno(error, r, "failed to set IPv4 client-id: %s"); return FALSE; @@ -844,14 +863,16 @@ bound6_handle(NMDhcpSystemd *self) _LOGD("lease available"); - ip6_config = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)), - iface, - nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)), - lease, - nm_dhcp_client_get_info_only(NM_DHCP_CLIENT(self)), - &options, - ts, - &error); + ip6_config = + lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)), + iface, + nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)), + lease, + NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)), + NM_DHCP_CLIENT_FLAGS_INFO_ONLY), + &options, + ts, + &error); if (!ip6_config) { _LOGW("%s", error->message); @@ -905,7 +926,6 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data) static gboolean ip6_start(NMDhcpClient * client, - const char * dhcp_anycast_addr, const struct in6_addr * ll_addr, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes, @@ -924,6 +944,8 @@ ip6_start(NMDhcpClient * client, g_return_val_if_fail(!priv->client4, FALSE); g_return_val_if_fail(!priv->client6, FALSE); + /* TODO: honor nm_dhcp_client_get_anycast_address() */ + if (!(duid = nm_dhcp_client_get_client_id(client)) || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing DUID"); @@ -938,7 +960,7 @@ ip6_start(NMDhcpClient * client, _LOGT("dhcp-client6: set %p", sd_client); - if (nm_dhcp_client_get_info_only(client)) { + if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_INFO_ONLY)) { sd_dhcp6_client_set_address_request(sd_client, 0); if (needed_prefixes == 0) sd_dhcp6_client_set_information_request(sd_client, 1); diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 63d90641..7fd18b0a 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -8,18 +8,18 @@ #include #include -#include "nm-std-aux/unaligned.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-glib-aux/nm-str-buf.h" -#include "systemd/nm-sd-utils-shared.h" +#include "libnm-std-aux/unaligned.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" #include "nm-dhcp-utils.h" #include "nm-utils.h" #include "nm-config.h" #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-dhcp-client-logging.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ @@ -989,7 +989,7 @@ lease_option_print_label(NMStrBuf *sbuf, size_t n_label, const uint8_t **datap, break; case '.': case '\\': - nm_str_buf_append_c2(sbuf, '\\', c); + nm_str_buf_append_c(sbuf, '\\', c); break; default: nm_str_buf_append_printf(sbuf, "\\%3d", c); diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c index 77626f69..e9a62096 100644 --- a/src/core/dhcp/tests/test-dhcp-dhclient.c +++ b/src/core/dhcp/tests/test-dhcp-dhclient.c @@ -9,14 +9,14 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "NetworkManagerUtils.h" #include "dhcp/nm-dhcp-dhclient-utils.h" #include "dhcp/nm-dhcp-utils.h" #include "nm-utils.h" #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-test-utils-core.h" diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c index 9b54e2cd..4d47e7e2 100644 --- a/src/core/dhcp/tests/test-dhcp-utils.c +++ b/src/core/dhcp/tests/test-dhcp-utils.c @@ -9,12 +9,12 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-utils.h" #include "dhcp/nm-dhcp-utils.h" #include "dhcp/nm-dhcp-options.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-test-utils-core.h" diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c index dcff98e9..126e0a21 100644 --- a/src/core/dns/nm-dns-dnsmasq.c +++ b/src/core/dns/nm-dns-dnsmasq.c @@ -15,9 +15,9 @@ #include #include -#include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-core-internal.h" -#include "platform/nm-platform.h" +#include "libnm-glib-aux/nm-dbus-aux.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nm-platform.h" #include "nm-utils.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" diff --git a/src/core/dns/nm-dns-dnsmasq.h b/src/core/dns/nm-dns-dnsmasq.h index bd6d4c60..575b0b26 100644 --- a/src/core/dns/nm-dns-dnsmasq.h +++ b/src/core/dns/nm-dns-dnsmasq.h @@ -7,6 +7,7 @@ #define __NETWORKMANAGER_DNS_DNSMASQ_H__ #include "nm-dns-plugin.h" +#include "nm-dns-manager.h" #define NM_TYPE_DNS_DNSMASQ (nm_dns_dnsmasq_get_type()) #define NM_DNS_DNSMASQ(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasq)) diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 59c8898a..4c498c82 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -22,8 +22,9 @@ #include #endif +#include "libnm-glib-aux/nm-str-buf.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dns-manager.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -83,13 +84,10 @@ typedef struct { GHashTable *configs_dict; CList configs_lst_head; - CList ip_configs_lst_head; + CList ip_config_lst_head; GVariant *config_variant; - NMDnsConfigIPData *best_ip_config_4; - NMDnsConfigIPData *best_ip_config_6; - - bool ip_configs_lst_need_sort : 1; + bool ip_config_lst_need_sort : 1; bool configs_lst_need_sort : 1; @@ -266,9 +264,11 @@ _dns_config_ip_data_new(NMDnsConfigData * data, .ip_config_type = ip_config_type, }; c_list_link_tail(&data->data_lst_head, &ip_data->data_lst); - c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_configs_lst_head, + c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_config_lst_head, &ip_data->ip_config_lst); + /* We also need to set priv->ip_config_lst_need_sort, but the caller will do that! */ + g_signal_connect(ip_config, NM_IS_IP4_CONFIG(ip_config) ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY : "notify::" NM_IP6_CONFIG_DNS_PRIORITY, @@ -325,7 +325,7 @@ _dns_config_data_free(NMDnsConfigData *data) } static int -_mgr_get_ip_configs_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) +_mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) { const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_config_lst); const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_config_lst); @@ -341,16 +341,16 @@ _mgr_get_ip_configs_lst_cmp(const CList *a_lst, const CList *b_lst, const void * } static CList * -_mgr_get_ip_configs_lst_head(NMDnsManager *self) +_mgr_get_ip_config_lst_head(NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); - if (G_UNLIKELY(priv->ip_configs_lst_need_sort)) { - priv->ip_configs_lst_need_sort = FALSE; - c_list_sort(&priv->ip_configs_lst_head, _mgr_get_ip_configs_lst_cmp, NULL); + if (G_UNLIKELY(priv->ip_config_lst_need_sort)) { + priv->ip_config_lst_need_sort = FALSE; + c_list_sort(&priv->ip_config_lst_head, _mgr_get_ip_config_lst_cmp, NULL); } - return &priv->ip_configs_lst_head; + return &priv->ip_config_lst_head; } static int @@ -378,11 +378,11 @@ _mgr_get_configs_lst_head(NMDnsManager *self) /*****************************************************************************/ -gboolean -nm_dns_manager_has_systemd_resolved(NMDnsManager *self) +NMDnsPlugin * +nm_dns_manager_get_systemd_resolved(NMDnsManager *self) { - NMDnsManagerPrivate * priv; - NMDnsSystemdResolved *plugin = NULL; + NMDnsManagerPrivate *priv; + NMDnsPlugin * plugin = NULL; g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE); @@ -390,11 +390,14 @@ nm_dns_manager_has_systemd_resolved(NMDnsManager *self) if (priv->sd_resolve_plugin) { nm_assert(!NM_IS_DNS_SYSTEMD_RESOLVED(priv->plugin)); - plugin = NM_DNS_SYSTEMD_RESOLVED(priv->sd_resolve_plugin); + plugin = priv->sd_resolve_plugin; } else if (NM_IS_DNS_SYSTEMD_RESOLVED(priv->plugin)) - plugin = NM_DNS_SYSTEMD_RESOLVED(priv->plugin); + plugin = priv->plugin; - return plugin && nm_dns_systemd_resolved_is_running(plugin); + if (plugin && nm_dns_systemd_resolved_is_running(NM_DNS_SYSTEMD_RESOLVED(plugin))) + return plugin; + + return NULL; } /*****************************************************************************/ @@ -1104,7 +1107,7 @@ update_resolv_conf(NMDnsManager * self, } static void -compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[HASH_LEN]) +compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[static HASH_LEN]) { nm_auto_free_checksum GChecksum *sum = NULL; NMDnsConfigIPData * ip_data; @@ -1119,7 +1122,7 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[ /* FIXME(ip-config-checksum): this relies on the fact that an IP * configuration without DNS parameters gives a zero checksum. */ - head = _mgr_get_ip_configs_lst_head(self); + head = _mgr_get_ip_config_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) nm_ip_config_hash(ip_data->ip_config, sum, TRUE); } @@ -1169,27 +1172,26 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) } static const char * -get_nameserver_list(const NMIPConfig *config, GString **str) +get_nameserver_list(const NMIPConfig *config, NMStrBuf *tmp_strbuf) { - guint num, i; char buf[NM_UTILS_INET_ADDRSTRLEN]; int addr_family; + guint num; + guint i; - if (*str) - g_string_truncate(*str, 0); - else - *str = g_string_sized_new(64); + nm_str_buf_reset(tmp_strbuf); addr_family = nm_ip_config_get_addr_family(config); num = nm_ip_config_get_num_nameservers(config); for (i = 0; i < num; i++) { nm_utils_inet_ntop(addr_family, nm_ip_config_get_nameserver(config, i), buf); if (i > 0) - g_string_append_c(*str, ' '); - g_string_append(*str, buf); + nm_str_buf_append_c(tmp_strbuf, ' '); + nm_str_buf_append(tmp_strbuf, buf); } - return (*str)->str; + nm_str_buf_maybe_expand(tmp_strbuf, 1, FALSE); + return nm_str_buf_get_str(tmp_strbuf); } static char ** @@ -1224,13 +1226,14 @@ _collect_resolv_conf_data(NMDnsManager * self, if (global_config) merge_global_dns_config(&rc, global_config); else { - nm_auto_free_gstring GString *tmp_gstring = NULL; - int prio, first_prio = 0; - const NMDnsConfigIPData * ip_data; - const CList * head; - gboolean is_first = TRUE; - - head = _mgr_get_ip_configs_lst_head(self); + nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE); + int prio; + int first_prio = 0; + const NMDnsConfigIPData *ip_data; + const CList * head; + gboolean is_first = TRUE; + + head = _mgr_get_ip_config_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) { gboolean skip = FALSE; @@ -1244,16 +1247,13 @@ _collect_resolv_conf_data(NMDnsManager * self, } else if (first_prio < 0 && first_prio != prio) skip = TRUE; - if (nm_ip_config_get_num_nameservers(ip_data->ip_config)) { - _LOGT( - "config: %8d %-7s v%c %-5d %s: %s", - prio, - _config_type_to_string(ip_data->ip_config_type), - nm_utils_addr_family_to_char(nm_ip_config_get_addr_family(ip_data->ip_config)), - ip_data->data->ifindex, - skip ? "" : "", - get_nameserver_list(ip_data->ip_config, &tmp_gstring)); - } + _LOGT("config: %8d %-7s v%c %-5d %s: %s", + prio, + _config_type_to_string(ip_data->ip_config_type), + nm_utils_addr_family_to_char(nm_ip_config_get_addr_family(ip_data->ip_config)), + ip_data->data->ifindex, + skip ? "" : "", + get_nameserver_list(ip_data->ip_config, &tmp_strbuf)); if (!skip) merge_one_ip_config(&rc, ip_data->data->ifindex, ip_data->ip_config); @@ -1394,7 +1394,7 @@ _mgr_configs_data_construct(NMDnsManager *self) CList * head; int prev_priority = G_MININT; - head = _mgr_get_ip_configs_lst_head(self); + head = _mgr_get_ip_config_lst_head(self); #if NM_MORE_ASSERTS /* we call _mgr_configs_data_clear() at the end of update. We @@ -1611,7 +1611,7 @@ _mgr_configs_data_clear(NMDnsManager *self) NMDnsConfigIPData *ip_data; CList * head; - head = _mgr_get_ip_configs_lst_head(self); + head = _mgr_get_ip_config_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) { nm_clear_g_free(&ip_data->domains.search); nm_clear_pointer(&ip_data->domains.reverse, g_strfreev); @@ -1680,7 +1680,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError if (priv->sd_resolve_plugin) { nm_dns_plugin_update(priv->sd_resolve_plugin, global_config, - _mgr_get_ip_configs_lst_head(self), + _mgr_get_ip_config_lst_head(self), priv->hostname, NULL); } @@ -1702,7 +1702,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError _LOGD("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update(plugin, global_config, - _mgr_get_ip_configs_lst_head(self), + _mgr_get_ip_config_lst_head(self), priv->hostname, &plugin_error)) { _LOGW("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message); @@ -1839,7 +1839,7 @@ _ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigI { _ASSERT_dns_config_ip_data(ip_data); - NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_configs_lst_need_sort = TRUE; + NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_config_lst_need_sort = TRUE; } gboolean @@ -1851,7 +1851,6 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, NMDnsConfigIPData * ip_data; NMDnsConfigData * data; int ifindex; - NMDnsConfigIPData ** p_best; g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE); g_return_val_if_fail(NM_IS_IP_CONFIG(ip_config), FALSE); @@ -1870,10 +1869,6 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) { if (!ip_data) return FALSE; - if (priv->best_ip_config_4 == ip_data) - priv->best_ip_config_4 = NULL; - if (priv->best_ip_config_6 == ip_data) - priv->best_ip_config_6 = NULL; /* deleting a config doesn't invalidate the configs' sort order. */ _dns_config_ip_data_free(ip_data); if (c_list_is_empty(&data->data_lst_head)) @@ -1904,21 +1899,7 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, else ip_data->ip_config_type = ip_config_type; - priv->ip_configs_lst_need_sort = TRUE; - - p_best = NM_IS_IP4_CONFIG(ip_config) ? &priv->best_ip_config_4 : &priv->best_ip_config_6; - - if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { - /* Only one best-device per IP version is allowed */ - if (*p_best != ip_data) { - if (*p_best) - (*p_best)->ip_config_type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; - *p_best = ip_data; - } - } else { - if (*p_best == ip_data) - *p_best = NULL; - } + priv->ip_config_lst_need_sort = TRUE; changed: if (!priv->updates_queue) { @@ -2440,7 +2421,7 @@ _get_config_variant(NMDnsManager *self) g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - head = _mgr_get_ip_configs_lst_head(self); + head = _mgr_get_ip_config_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) { const NMIPConfig *ip_config = ip_data->ip_config; GVariantBuilder entry_builder; @@ -2546,13 +2527,13 @@ nm_dns_manager_init(NMDnsManager *self) _LOGT("creating..."); c_list_init(&priv->configs_lst_head); - c_list_init(&priv->ip_configs_lst_head); + c_list_init(&priv->ip_config_lst_head); priv->config = g_object_ref(nm_config_get()); G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDnsConfigData, ifindex) == 0); priv->configs_dict = g_hash_table_new_full(nm_pint_hash, - nm_pint_equals, + nm_pint_equal, (GDestroyNotify) _dns_config_data_free, NULL); @@ -2584,10 +2565,7 @@ dispose(GObject *object) g_clear_object(&priv->sd_resolve_plugin); _clear_plugin(self); - priv->best_ip_config_4 = NULL; - priv->best_ip_config_6 = NULL; - - c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_configs_lst_head, ip_config_lst) + c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst) _dns_config_ip_data_free(ip_data); nm_clear_pointer(&priv->configs_dict, g_hash_table_destroy); @@ -2618,13 +2596,13 @@ static const NMDBusInterfaceInfoExtended interface_info_dns_manager = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DNS_MANAGER, .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "s", NM_DNS_MANAGER_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("RcManager", - "s", - NM_DNS_MANAGER_RC_MANAGER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Configuration", - "aa{sv}", - NM_DNS_MANAGER_CONFIGURATION), ), ), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "s", NM_DNS_MANAGER_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RcManager", + "s", + NM_DNS_MANAGER_RC_MANAGER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Configuration", + "aa{sv}", + NM_DNS_MANAGER_CONFIGURATION), ), ), }; static void diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h index 937ba62a..501085f7 100644 --- a/src/core/dns/nm-dns-manager.h +++ b/src/core/dns/nm-dns-manager.h @@ -11,6 +11,7 @@ #include "nm-ip4-config.h" #include "nm-ip6-config.h" #include "nm-setting-connection.h" +#include "nm-dns-plugin.h" typedef enum { NM_DNS_IP_CONFIG_TYPE_REMOVED = -1, @@ -148,7 +149,7 @@ typedef enum { void nm_dns_manager_stop(NMDnsManager *self); -gboolean nm_dns_manager_has_systemd_resolved(NMDnsManager *self); +NMDnsPlugin *nm_dns_manager_get_systemd_resolved(NMDnsManager *self); /*****************************************************************************/ diff --git a/src/core/dns/nm-dns-plugin.c b/src/core/dns/nm-dns-plugin.c index 74d4eb2b..e5035f06 100644 --- a/src/core/dns/nm-dns-plugin.c +++ b/src/core/dns/nm-dns-plugin.c @@ -12,7 +12,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" /*****************************************************************************/ diff --git a/src/core/dns/nm-dns-plugin.h b/src/core/dns/nm-dns-plugin.h index 644d01e5..82ca7d6b 100644 --- a/src/core/dns/nm-dns-plugin.h +++ b/src/core/dns/nm-dns-plugin.h @@ -6,7 +6,8 @@ #ifndef __NM_DNS_PLUGIN_H__ #define __NM_DNS_PLUGIN_H__ -#include "nm-dns-manager.h" +#include "c-list/src/c-list.h" + #include "nm-config-data.h" #define NM_TYPE_DNS_PLUGIN (nm_dns_plugin_get_type()) diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index f6e116f3..4b8c4f94 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -16,10 +16,10 @@ #include #include -#include "nm-glib-aux/nm-c-list.h" -#include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-core-internal.h" -#include "platform/nm-platform.h" +#include "libnm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-dbus-aux.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nm-platform.h" #include "nm-utils.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -28,7 +28,7 @@ #include "nm-setting-connection.h" #include "devices/nm-device.h" #include "NetworkManagerUtils.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/nm-dbus-compat.h" #define SYSTEMD_RESOLVED_DBUS_SERVICE "org.freedesktop.resolve1" #define SYSTEMD_RESOLVED_MANAGER_IFACE "org.freedesktop.resolve1.Manager" @@ -52,19 +52,40 @@ typedef struct { int ifindex; } RequestItem; +struct _NMDnsSystemdResolvedResolveHandle { + CList handle_lst; + NMDnsSystemdResolved *self; + GSource * timeout_source; + GCancellable * handle_cancellable; + gpointer callback_user_data; + guint timeout_msec; + bool is_failing_on_idle; + union { + struct { + NMDnsSystemdResolvedResolveAddressCallback callback; + guint64 flags; + int ifindex; + int addr_family; + NMIPAddr addr; + } r_address; + }; +}; + /*****************************************************************************/ typedef struct { GDBusConnection *dbus_connection; GHashTable * dirty_interfaces; GCancellable * cancellable; + GSource * try_start_timeout_source; CList request_queue_lst_head; + char * dbus_owner; + CList handle_lst_head; guint name_owner_changed_id; bool send_updates_warn_ratelimited : 1; bool try_start_blocked : 1; - bool dbus_has_owner : 1; bool dbus_initied : 1; - bool request_queue_to_send : 1; + bool send_updates_waiting : 1; NMTernary has_link_default_route : 3; } NMDnsSystemdResolvedPrivate; @@ -84,9 +105,39 @@ G_DEFINE_TYPE(NMDnsSystemdResolved, nm_dns_systemd_resolved, NM_TYPE_DNS_PLUGIN) /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_DNS +#define _NMLOG_DOMAIN LOGD_DNS +#define _NMLOG_PREFIX_NAME "dns-sd-resolved" + #define _NMLOG(level, ...) \ - __NMLOG_DEFAULT_WITH_ADDR(level, _NMLOG_DOMAIN, "dns-sd-resolved", __VA_ARGS__) + __NMLOG_DEFAULT_WITH_ADDR(level, _NMLOG_DOMAIN, _NMLOG_PREFIX_NAME, __VA_ARGS__) + +#define _NMLOG2(level, handle, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled(_level, (_NMLOG_DOMAIN))) { \ + const NMDnsSystemdResolvedResolveHandle *const _handle = (handle); \ + \ + _nm_log(_level, \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ + "%s[" NM_HASH_OBFUSCATE_PTR_FMT "]: request[" NM_HASH_OBFUSCATE_PTR_FMT \ + "]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + NM_HASH_OBFUSCATE_PTR(self), \ + NM_HASH_OBFUSCATE_PTR(_handle) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +/*****************************************************************************/ + +static void _resolve_complete_error(NMDnsSystemdResolvedResolveHandle *handle, GError *error); + +static void _resolve_start(NMDnsSystemdResolved *self, NMDnsSystemdResolvedResolveHandle *handle); /*****************************************************************************/ @@ -201,10 +252,7 @@ update_add_ip_config(NMDnsSystemdResolved *self, g_variant_builder_add(dns, "i", addr_family); g_variant_builder_add_value( dns, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, - nm_ip_config_get_nameserver(data->ip_config, i), - addr_size, - 1)); + nm_g_variant_new_ay(nm_ip_config_get_nameserver(data->ip_config, i), addr_size)); g_variant_builder_close(dns); has_config = TRUE; } @@ -326,57 +374,105 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) return has_config; } -static void -send_updates(NMDnsSystemdResolved *self) +static gboolean +_ensure_resolved_running_timeout(gpointer user_data) { - NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); - RequestItem * request_item; + NMDnsSystemdResolved * self = user_data; + NMDnsSystemdResolvedPrivate * priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + NMDnsSystemdResolvedResolveHandle *handle; - if (!priv->request_queue_to_send) { - /* nothing to do. */ - return; - } + nm_clear_g_source_inst(&priv->try_start_timeout_source); - if (!priv->dbus_initied) { - _LOGT("send-updates: D-Bus connection not ready"); - return; + _LOGT("timeout waiting to D-Bus activate systemd-resolved. Systemd-resolved won't be " + "used until it appears on the bus"); + +again: + c_list_for_each_entry (handle, &priv->handle_lst_head, handle_lst) { + gs_free_error GError *error = NULL; + + if (handle->is_failing_on_idle) + continue; + + nm_utils_error_set_literal(&error, + NM_UTILS_ERROR_NOT_READY, + "timeout waiting for systemd-resolved to start"); + _resolve_complete_error(handle, error); + goto again; } - if (!priv->dbus_has_owner) { + return G_SOURCE_CONTINUE; +} + +static NMTernary +ensure_resolved_running(NMDnsSystemdResolved *self) +{ + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + + if (!priv->dbus_initied) + return NM_TERNARY_DEFAULT; + + if (!priv->dbus_owner) { if (priv->try_start_blocked) { /* we have no name owner and we already tried poking the service to * autostart. */ - _LOGT("send-updates: no name owner"); - return; + return NM_TERNARY_FALSE; } - _LOGT("send-updates: no name owner. Try start service..."); + _LOGT("try D-Bus activating systemd-resolved..."); priv->try_start_blocked = TRUE; + priv->try_start_timeout_source = + nm_g_source_attach(nm_g_timeout_source_new(4000, + G_PRIORITY_DEFAULT, + _ensure_resolved_running_timeout, + self, + NULL), + NULL); + nm_dbus_connection_call_start_service_by_name(priv->dbus_connection, SYSTEMD_RESOLVED_DBUS_SERVICE, -1, NULL, NULL, NULL); + return NM_TERNARY_DEFAULT; + } + + return NM_TERNARY_TRUE; +} + +static void +send_updates(NMDnsSystemdResolved *self) +{ + NMDnsSystemdResolvedPrivate * priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + RequestItem * request_item; + NMDnsSystemdResolvedResolveHandle *handle; + + if (!priv->send_updates_waiting) { + /* nothing to do. */ return; } + if (ensure_resolved_running(self) != NM_TERNARY_TRUE) + return; + nm_clear_g_cancellable(&priv->cancellable); if (c_list_is_empty(&priv->request_queue_lst_head)) { _LOGT("send-updates: no requests to send"); - priv->request_queue_to_send = FALSE; - return; + priv->send_updates_waiting = FALSE; + goto start_resolve; } - _LOGT("send-updates: start %lu requests", c_list_length(&priv->request_queue_lst_head)); - priv->cancellable = g_cancellable_new(); - priv->request_queue_to_send = FALSE; + priv->send_updates_waiting = FALSE; + + _LOGT("send-updates: start %lu requests", c_list_length(&priv->request_queue_lst_head)); c_list_for_each_entry (request_item, &priv->request_queue_lst_head, request_queue_lst) { + gs_free char *ss = NULL; + if (request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE && priv->has_link_default_route == NM_TERNARY_FALSE) { /* The "SetLinkDefaultRoute" API is only supported since v240. @@ -386,16 +482,12 @@ send_updates(NMDnsSystemdResolved *self) continue; } - /* Above we explicitly call "StartServiceByName" trying to avoid D-Bus activating systmd-resolved - * multiple times. There is still a race, were we might hit this line although actually - * the service just quit this very moment. In that case, we would try to D-Bus activate the - * service multiple times during each call (something we wanted to avoid). - * - * But this is hard to avoid, because we'd have to check the error failure to detect the reason - * and retry. The race is not critical, because at worst it results in logging a warning - * about failure to start systemd.resolved. */ + _LOGT("send-updates: %s ( %s )", + request_item->operation, + (ss = g_variant_print(request_item->argument, FALSE))); + g_dbus_connection_call(priv->dbus_connection, - SYSTEMD_RESOLVED_DBUS_SERVICE, + priv->dbus_owner, SYSTEMD_RESOLVED_DBUS_PATH, SYSTEMD_RESOLVED_MANAGER_IFACE, request_item->operation, @@ -407,6 +499,15 @@ send_updates(NMDnsSystemdResolved *self) call_done, request_item); } + +start_resolve: + c_list_for_each_entry (handle, &priv->handle_lst_head, handle_lst) { + if (handle->handle_cancellable) + continue; + if (handle->is_failing_on_idle) + continue; + _resolve_start(self, handle); + } } static gboolean @@ -479,7 +580,7 @@ update(NMDnsPlugin * plugin, } } - priv->request_queue_to_send = TRUE; + priv->send_updates_waiting = TRUE; send_updates(self); return TRUE; } @@ -498,10 +599,13 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner) else _LOGT("D-Bus name for systemd-resolved has owner %s", owner); - priv->dbus_has_owner = !!owner; + nm_clear_g_source_inst(&priv->try_start_timeout_source); + + nm_utils_strdup_reset(&priv->dbus_owner, owner); + if (owner) { - priv->try_start_blocked = FALSE; - priv->request_queue_to_send = TRUE; + priv->try_start_blocked = FALSE; + priv->send_updates_waiting = TRUE; } else priv->has_link_default_route = NM_TERNARY_DEFAULT; @@ -531,6 +635,7 @@ name_owner_changed_cb(GDBusConnection *connection, * returns. */ priv->dbus_initied = TRUE; nm_clear_g_cancellable(&priv->cancellable); + _LOGT("D-Bus connection is ready"); } name_owner_changed(user_data, new_owner); @@ -551,6 +656,7 @@ get_name_owner_cb(const char *name_owner, GError *error, gpointer user_data) g_clear_object(&priv->cancellable); priv->dbus_initied = TRUE; + _LOGT("D-Bus connection is ready"); name_owner_changed(self, name_owner); } @@ -566,7 +672,253 @@ nm_dns_systemd_resolved_is_running(NMDnsSystemdResolved *self) priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); - return priv->dbus_initied && (priv->dbus_has_owner || !priv->try_start_blocked); + return priv->dbus_initied && (priv->dbus_owner || !priv->try_start_blocked); +} + +/*****************************************************************************/ + +static void +_resolve_complete(NMDnsSystemdResolvedResolveHandle * handle, + const NMDnsSystemdResolvedAddressResult *names, + guint names_len, + guint64 flags, + GError * error) +{ + NMDnsSystemdResolved * self; + NMDnsSystemdResolvedPrivate *priv; + + g_return_if_fail(handle && NM_IS_DNS_SYSTEMD_RESOLVED(handle->self)); + + self = handle->self; + priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + + nm_assert(c_list_contains(&priv->handle_lst_head, &handle->handle_lst)); + + c_list_unlink(&handle->handle_lst); + + handle->self = NULL; + + nm_clear_g_source_inst(&handle->timeout_source); + nm_clear_g_cancellable(&handle->handle_cancellable); + + handle->r_address + .callback(self, handle, names, names_len, flags, error, handle->callback_user_data); + + nm_g_slice_free(handle); +} + +static void +_resolve_complete_error(NMDnsSystemdResolvedResolveHandle *handle, GError *error) +{ + NMDnsSystemdResolved *self = handle->self; + + nm_assert(error); + _LOG2T(handle, "request failed: %s", error->message); + _resolve_complete(handle, NULL, 0, 0, error); +} + +static void +_resolve_handle_call_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + gs_unref_variant GVariant *v = NULL; + gs_free_error GError * error = NULL; + NMDnsSystemdResolvedResolveHandle *handle; + NMDnsSystemdResolved * self; + GVariantIter * v_names_iter; + guint64 v_flags; + int v_ifindex; + char * v_name; + gs_unref_array GArray *v_names = NULL; + gs_free char * ss = NULL; + + v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error); + if (nm_utils_error_is_cancelled(error)) + return; + + handle = user_data; + self = handle->self; + + if (error) { + gs_free char *remote_error = NULL; + + remote_error = g_dbus_error_get_remote_error(error); + if (nm_streq0(remote_error, "org.freedesktop.DBus.Error.ServiceUnknown")) { + _LOG2T(handle, "request failed due to service stop. Retry"); + g_clear_object(&handle->handle_cancellable); + _resolve_start(self, handle); + return; + } + + _resolve_complete_error(handle, error); + return; + } + + _LOG2T(handle, "request completed: %s", (ss = g_variant_print(v, FALSE))); + + v_names = g_array_new(FALSE, FALSE, sizeof(NMDnsSystemdResolvedAddressResult)); + + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDnsSystemdResolvedAddressResult, name) == 0); + g_array_set_clear_func(v_names, nm_indirect_g_free); + + g_variant_get(v, "(a(is)t)", &v_names_iter, &v_flags); + + while (g_variant_iter_next(v_names_iter, "(is)", &v_ifindex, &v_name)) { + NMDnsSystemdResolvedAddressResult *n; + + n = nm_g_array_append_new(v_names, NMDnsSystemdResolvedAddressResult); + *n = (NMDnsSystemdResolvedAddressResult){ + .name = g_steal_pointer(&v_name), + .ifindex = v_ifindex, + }; + } + g_variant_iter_free(v_names_iter); + + _resolve_complete(handle, + &g_array_index(v_names, NMDnsSystemdResolvedAddressResult, 0), + v_names->len, + v_flags, + NULL); +} + +static gboolean +_resolve_failing_on_idle(gpointer user_data) +{ + NMDnsSystemdResolvedResolveHandle *handle = user_data; + gs_free_error GError *error = NULL; + + nm_utils_error_set_literal(&error, + NM_UTILS_ERROR_NOT_READY, + "systemd-resolved is not available"); + _resolve_complete_error(handle, error); + return G_SOURCE_CONTINUE; +} + +static gboolean +_resolve_handle_timeout(gpointer user_data) +{ + NMDnsSystemdResolvedResolveHandle *handle = user_data; + gs_free_error GError *error = NULL; + + nm_utils_error_set_literal(&error, NM_UTILS_ERROR_UNKNOWN, "timeout for request"); + _resolve_complete_error(handle, error); + return G_SOURCE_CONTINUE; +} + +static void +_resolve_start(NMDnsSystemdResolved *self, NMDnsSystemdResolvedResolveHandle *handle) +{ + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + NMTernary is_running; + + nm_assert(!handle->handle_cancellable); + nm_assert(!handle->is_failing_on_idle); + + is_running = ensure_resolved_running(self); + + if (is_running == NM_TERNARY_FALSE) { + /* Systemd-resolved is not is_running and shall not be used. We fail + * on an idle handler. */ + _LOG2T(handle, "systemd-resolved not running. Failing on idle..."); + nm_assert(!handle->timeout_source); + handle->is_failing_on_idle = TRUE; + handle->timeout_source = nm_g_source_attach( + nm_g_idle_source_new(G_PRIORITY_DEFAULT, _resolve_failing_on_idle, handle, NULL), + NULL); + return; + } + + if (!handle->timeout_source) { + handle->timeout_source = nm_g_source_attach(nm_g_timeout_source_new(handle->timeout_msec, + G_PRIORITY_DEFAULT, + _resolve_handle_timeout, + handle, + NULL), + NULL); + } + + if (is_running == NM_TERNARY_DEFAULT) { + /* we are D-Bus activating systemd-resolved. Wait for it... */ + _LOG2T(handle, "waiting for systemd-resolved to start..."); + return; + } + + nm_assert(!priv->send_updates_waiting); + + handle->handle_cancellable = g_cancellable_new(); + + _LOG2T(handle, "start D-Bus request..."); + g_dbus_connection_call(priv->dbus_connection, + priv->dbus_owner, + SYSTEMD_RESOLVED_DBUS_PATH, + SYSTEMD_RESOLVED_MANAGER_IFACE, + "ResolveAddress", + g_variant_new("(ii@ayt)", + handle->r_address.ifindex, + handle->r_address.addr_family, + nm_g_variant_new_ay_inaddr(handle->r_address.addr_family, + &handle->r_address.addr), + handle->r_address.flags), + G_VARIANT_TYPE("(a(is)t)"), + G_DBUS_CALL_FLAGS_NONE, + handle->timeout_msec + 1000u, + handle->handle_cancellable, + _resolve_handle_call_cb, + handle); +} + +NMDnsSystemdResolvedResolveHandle * +nm_dns_systemd_resolved_resolve_address(NMDnsSystemdResolved * self, + int ifindex, + int addr_family, + const NMIPAddr * addr, + guint64 flags, + guint timeout_msec, + NMDnsSystemdResolvedResolveAddressCallback callback, + gpointer user_data) +{ + NMDnsSystemdResolvedPrivate * priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + NMDnsSystemdResolvedResolveHandle *handle; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_val_if_fail(NM_IS_DNS_SYSTEMD_RESOLVED(self), NULL); + nm_assert_addr_family(addr_family); + nm_assert(addr); + nm_assert(callback); + + handle = g_slice_new(NMDnsSystemdResolvedResolveHandle); + *handle = (NMDnsSystemdResolvedResolveHandle){ + .self = self, + .timeout_msec = timeout_msec, + .callback_user_data = user_data, + .r_address = + { + .ifindex = ifindex, + .addr_family = addr_family, + .addr = *addr, + .flags = flags, + .callback = callback, + }, + }; + c_list_link_tail(&priv->handle_lst_head, &handle->handle_lst); + + _LOG2T(handle, + "resolve-address(ifindex=%d, %s, flags=%" G_GINT64_MODIFIER "x): new request", + handle->r_address.ifindex, + nm_utils_inet_ntop(handle->r_address.addr_family, &handle->r_address.addr, addr_str), + handle->r_address.flags); + + _resolve_start(self, handle); + + return handle; +} + +void +nm_dns_systemd_resolved_resolve_cancel(NMDnsSystemdResolvedResolveHandle *handle) +{ + gs_free_error GError *error = NULL; + + nm_utils_error_set_cancelled(&error, FALSE, "NMDnsSystemdResolved"); + _resolve_complete_error(handle, error); } /*****************************************************************************/ @@ -579,6 +931,7 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) priv->has_link_default_route = NM_TERNARY_DEFAULT; c_list_init(&priv->request_queue_lst_head); + c_list_init(&priv->handle_lst_head); priv->dirty_interfaces = g_hash_table_new(nm_direct_hash, NULL); priv->dbus_connection = nm_g_object_ref(NM_MAIN_DBUS_CONNECTION_GET); @@ -611,8 +964,18 @@ nm_dns_systemd_resolved_new(void) static void dispose(GObject *object) { - NMDnsSystemdResolved * self = NM_DNS_SYSTEMD_RESOLVED(object); - NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + NMDnsSystemdResolved * self = NM_DNS_SYSTEMD_RESOLVED(object); + NMDnsSystemdResolvedPrivate * priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + NMDnsSystemdResolvedResolveHandle *handle; + + while ((handle = c_list_first_entry(&priv->handle_lst_head, + NMDnsSystemdResolvedResolveHandle, + handle_lst))) { + gs_free_error GError *error = NULL; + + nm_utils_error_set_cancelled(&error, TRUE, "NMDnsSystemdResolved"); + _resolve_complete_error(handle, error); + } free_pending_updates(self); @@ -620,10 +983,14 @@ dispose(GObject *object) nm_clear_g_cancellable(&priv->cancellable); + nm_clear_g_source_inst(&priv->try_start_timeout_source); + g_clear_object(&priv->dbus_connection); nm_clear_pointer(&priv->dirty_interfaces, g_hash_table_unref); G_OBJECT_CLASS(nm_dns_systemd_resolved_parent_class)->dispose(object); + + nm_clear_g_free(&priv->dbus_owner); } static void diff --git a/src/core/dns/nm-dns-systemd-resolved.h b/src/core/dns/nm-dns-systemd-resolved.h index 4ab04ab4..9f973318 100644 --- a/src/core/dns/nm-dns-systemd-resolved.h +++ b/src/core/dns/nm-dns-systemd-resolved.h @@ -8,6 +8,7 @@ #define __NETWORKMANAGER_DNS_SYSTEMD_RESOLVED_H__ #include "nm-dns-plugin.h" +#include "nm-dns-manager.h" #define NM_TYPE_DNS_SYSTEMD_RESOLVED (nm_dns_systemd_resolved_get_type()) #define NM_DNS_SYSTEMD_RESOLVED(obj) \ @@ -30,4 +31,34 @@ NMDnsPlugin *nm_dns_systemd_resolved_new(void); gboolean nm_dns_systemd_resolved_is_running(NMDnsSystemdResolved *self); +/*****************************************************************************/ + +typedef struct _NMDnsSystemdResolvedResolveHandle NMDnsSystemdResolvedResolveHandle; + +typedef struct { + const char *name; + int ifindex; +} NMDnsSystemdResolvedAddressResult; + +typedef void (*NMDnsSystemdResolvedResolveAddressCallback)( + NMDnsSystemdResolved * self, + NMDnsSystemdResolvedResolveHandle * handle, + const NMDnsSystemdResolvedAddressResult *names, + guint names_len, + guint64 flags, + GError * error, + gpointer user_data); + +NMDnsSystemdResolvedResolveHandle * +nm_dns_systemd_resolved_resolve_address(NMDnsSystemdResolved * self, + int ifindex, + int addr_family, + const NMIPAddr * addr, + guint64 flags, + guint timeout_msec, + NMDnsSystemdResolvedResolveAddressCallback callback, + gpointer user_data); + +void nm_dns_systemd_resolved_resolve_cancel(NMDnsSystemdResolvedResolveHandle *handle); + #endif /* __NETWORKMANAGER_DNS_SYSTEMD_RESOLVED_H__ */ diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c index 82c002b0..e8697e81 100644 --- a/src/core/dnsmasq/nm-dnsmasq-manager.c +++ b/src/core/dnsmasq/nm-dnsmasq-manager.c @@ -17,7 +17,7 @@ #include "nm-dnsmasq-utils.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define CONFDIR NMCONFDIR "/dnsmasq-shared.d" diff --git a/src/core/dnsmasq/nm-dnsmasq-utils.c b/src/core/dnsmasq/nm-dnsmasq-utils.c index ea23a78d..c2791b9e 100644 --- a/src/core/dnsmasq/nm-dnsmasq-utils.c +++ b/src/core/dnsmasq/nm-dnsmasq-utils.c @@ -5,10 +5,11 @@ #include "src/core/nm-default-daemon.h" +#include "nm-dnsmasq-utils.h" + #include -#include "nm-dnsmasq-utils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-utils.h" gboolean diff --git a/src/core/dnsmasq/nm-dnsmasq-utils.h b/src/core/dnsmasq/nm-dnsmasq-utils.h index 57bbc4c4..1fabc9ba 100644 --- a/src/core/dnsmasq/nm-dnsmasq-utils.h +++ b/src/core/dnsmasq/nm-dnsmasq-utils.h @@ -6,7 +6,7 @@ #ifndef __NETWORKMANAGER_DNSMASQ_UTILS_H__ #define __NETWORKMANAGER_DNSMASQ_UTILS_H__ -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" gboolean nm_dnsmasq_utils_get_range(const NMPlatformIP4Address *addr, char * out_first, diff --git a/src/core/initrd/meson.build b/src/core/initrd/meson.build deleted file mode 100644 index bd590e8c..00000000 --- a/src/core/initrd/meson.build +++ /dev/null @@ -1,31 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -libnmi_core = static_library( - 'nmi-core', - sources: files( - 'nmi-cmdline-reader.c', - 'nmi-dt-reader.c', - 'nmi-ibft-reader.c', - ), - dependencies: core_default_dep, - c_args: daemon_c_flags, -) - -executable( - 'nm-initrd-generator', - 'nm-initrd-generator.c', - dependencies: core_default_dep, - c_args: daemon_c_flags, - link_with: [ - libNetworkManagerBase, - libnmi_core, - ], - link_args: ldflags_linker_script_binary, - link_depends: linker_script_binary, - install: true, - install_dir: nm_libexecdir, -) - -if enable_tests - subdir('tests') -endif diff --git a/src/core/initrd/nm-initrd-generator.c b/src/core/initrd/nm-initrd-generator.c deleted file mode 100644 index 18c7258a..00000000 --- a/src/core/initrd/nm-initrd-generator.c +++ /dev/null @@ -1,226 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" -#include "nm-core-utils.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" -#include "nm-initrd-generator.h" -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-config.h" - -/*****************************************************************************/ - -#define _NMLOG(level, domain, ...) \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "initrd-generator: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)) - -/*****************************************************************************/ - -static void -output_conn(gpointer key, gpointer value, gpointer user_data) -{ - const char * basename = key; - NMConnection * connection = value; - char * connections_dir = user_data; - nm_auto_unref_keyfile GKeyFile *file = NULL; - gs_free char * data = NULL; - gs_free_error GError *error = NULL; - gsize len; - - if (!nm_connection_normalize(connection, NULL, NULL, &error)) - goto err_out; - - file = nm_keyfile_write(connection, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); - if (file == NULL) - goto err_out; - - data = g_key_file_to_data(file, &len, &error); - if (!data) - goto err_out; - - if (connections_dir) { - gs_free char *filename = NULL; - gs_free char *full_filename = NULL; - - filename = nm_keyfile_utils_create_filename(basename, TRUE); - full_filename = g_build_filename(connections_dir, filename, NULL); - - if (!nm_utils_file_set_contents(full_filename, data, len, 0600, NULL, &error)) - goto err_out; - } else - g_print("\n*** Connection '%s' ***\n\n%s", basename, data); - - return; -err_out: - g_print("%s\n", error->message); -} - -#define DEFAULT_SYSFS_DIR "/sys" -#define DEFAULT_INITRD_DATA_DIR NMRUNDIR "/initrd" -#define DEFAULT_RUN_CONFIG_DIR NMRUNDIR "/conf.d" - -int -main(int argc, char *argv[]) -{ - GHashTable * connections; - gs_free char * connections_dir = NULL; - gs_free char * initrd_dir = NULL; - gs_free char * sysfs_dir = NULL; - gs_free char * run_config_dir = NULL; - gboolean dump_to_stdout = FALSE; - gs_strfreev char **remaining = NULL; - GOptionEntry option_entries[] = { - {"connections-dir", - 'c', - 0, - G_OPTION_ARG_FILENAME, - &connections_dir, - "Output connection directory", - NM_KEYFILE_PATH_NAME_RUN}, - {"initrd-data-dir", - 'i', - 0, - G_OPTION_ARG_FILENAME, - &initrd_dir, - "Output initrd data directory", - DEFAULT_INITRD_DATA_DIR}, - {"sysfs-dir", - 'd', - 0, - G_OPTION_ARG_FILENAME, - &sysfs_dir, - "The sysfs mount point", - DEFAULT_SYSFS_DIR}, - {"run-config-dir", - 'r', - 0, - G_OPTION_ARG_FILENAME, - &run_config_dir, - "Output config directory", - DEFAULT_RUN_CONFIG_DIR}, - {"stdout", - 's', - 0, - G_OPTION_ARG_NONE, - &dump_to_stdout, - "Dump connections to standard output", - NULL}, - {G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining, NULL, NULL}, - {NULL}}; - nm_auto_free_option_context GOptionContext *option_context = NULL; - gs_free_error GError *error = NULL; - gs_free char * hostname = NULL; - int errsv; - gint64 carrier_timeout_sec = 0; - - option_context = g_option_context_new( - "-- [ip=...] [rd.route=...] [bridge=...] [bond=...] [team=...] [vlan=...] " - "[bootdev=...] [nameserver=...] [rd.peerdns=...] [rd.bootif=...] [BOOTIF=...] " - "[rd.znet=...] [rd.net.timeout.carrier=...] ... "); - - g_option_context_set_summary(option_context, "Generate early NetworkManager configuration."); - g_option_context_set_description( - option_context, - "This tool scans the command line for options relevant to network\n" - "configuration and creates configuration files for an early instance\n" - "of NetworkManager run from the initial ramdisk during early boot."); - g_option_context_add_main_entries(option_context, option_entries, GETTEXT_PACKAGE); - - if (!g_option_context_parse(option_context, &argc, &argv, &error)) { - _LOGW(LOGD_CORE, "%s", error->message); - return 1; - } - - if (!remaining) { - /* No arguments, no networking. Don't bother. */ - return 0; - } - - if (!connections_dir) - connections_dir = g_strdup(NM_KEYFILE_PATH_NAME_RUN); - if (!sysfs_dir) - sysfs_dir = g_strdup(DEFAULT_SYSFS_DIR); - if (!initrd_dir) - initrd_dir = g_strdup(DEFAULT_INITRD_DATA_DIR); - if (!run_config_dir) - run_config_dir = g_strdup(DEFAULT_RUN_CONFIG_DIR); - - connections = nmi_cmdline_reader_parse(sysfs_dir, - (const char *const *) remaining, - &hostname, - &carrier_timeout_sec); - - if (dump_to_stdout) { - nm_clear_g_free(&connections_dir); - nm_clear_g_free(&initrd_dir); - nm_clear_g_free(&run_config_dir); - if (hostname) - g_print("\n*** Hostname '%s' ***\n", hostname); - if (carrier_timeout_sec != 0) - g_print("\n*** Carrier Wait Timeout %" G_GINT64_FORMAT " sec ***\n", - carrier_timeout_sec); - } else { - if (g_mkdir_with_parents(connections_dir, 0755) != 0) { - errsv = errno; - _LOGW(LOGD_CORE, "%s: %s", connections_dir, nm_strerror_native(errsv)); - return 1; - } - if (g_mkdir_with_parents(initrd_dir, 0755) != 0) { - errsv = errno; - _LOGW(LOGD_CORE, "%s: %s", initrd_dir, nm_strerror_native(errsv)); - return 1; - } - if (g_mkdir_with_parents(run_config_dir, 0755) != 0) { - errsv = errno; - _LOGW(LOGD_CORE, "%s: %s", run_config_dir, nm_strerror_native(errsv)); - return 1; - } - - if (hostname) { - gs_free char *hostname_file = NULL; - gs_free char *data = NULL; - - hostname_file = g_strdup_printf("%s/hostname", initrd_dir); - data = g_strdup_printf("%s\n", hostname); - - if (!g_file_set_contents(hostname_file, data, strlen(data), &error)) { - _LOGW(LOGD_CORE, "%s: %s", hostname_file, error->message); - return 1; - } - } - if (carrier_timeout_sec != 0) { - nm_auto_unref_keyfile GKeyFile *keyfile = NULL; - gs_free char * filename = NULL; - - keyfile = g_key_file_new(); - g_key_file_set_list_separator(keyfile, NM_CONFIG_KEYFILE_LIST_SEPARATOR); - filename = g_strdup_printf("%s/15-carrier-timeout.conf", run_config_dir); - - g_key_file_set_value(keyfile, - NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE "-15-carrier-timeout", - NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE, - "*"); - g_key_file_set_int64(keyfile, - NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE "-15-carrier-timeout", - NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT, - carrier_timeout_sec * 1000); - - if (!g_key_file_save_to_file(keyfile, filename, &error)) { - _LOGW(LOGD_CORE, "%s: %s", filename, error->message); - return 1; - } - } - } - - g_hash_table_foreach(connections, output_conn, connections_dir); - g_hash_table_destroy(connections); - - return 0; -} diff --git a/src/core/initrd/nm-initrd-generator.h b/src/core/initrd/nm-initrd-generator.h deleted file mode 100644 index 56dcfd68..00000000 --- a/src/core/initrd/nm-initrd-generator.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014, 2018 Red Hat, Inc. - */ - -#ifndef __NM_INITRD_GENERATOR_H__ -#define __NM_INITRD_GENERATOR_H__ - -#include "nm-connection.h" -#include "nm-utils.h" - -#define NMI_WAIT_DEVICE_TIMEOUT_MS 60000 - -static inline int -get_ip_address_family(const char *str, gboolean with_prefix) -{ - int addr_family; - - if (!str) - return AF_UNSPEC; - - if (with_prefix) { - if (nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, str, &addr_family, NULL, NULL)) - return addr_family; - } else { - if (nm_utils_parse_inaddr_bin(AF_UNSPEC, str, &addr_family, NULL)) - return addr_family; - } - - return AF_UNSPEC; -} - -GHashTable *nmi_ibft_read(const char *sysfs_dir); - -gboolean -nmi_ibft_update_connection_from_nic(NMConnection *connection, GHashTable *nic, GError **error); - -NMConnection *nmi_dt_reader_parse(const char *sysfs_dir); - -GHashTable *nmi_cmdline_reader_parse(const char * sysfs_dir, - const char *const *argv, - char ** hostname, - gint64 * carrier_timeout_sec); - -#endif /* __NM_INITRD_GENERATOR_H__ */ diff --git a/src/core/initrd/nmi-cmdline-reader.c b/src/core/initrd/nmi-cmdline-reader.c deleted file mode 100644 index 0a24199e..00000000 --- a/src/core/initrd/nmi-cmdline-reader.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include -#include - -#include "nm-core-internal.h" -#include "nm-initrd-generator.h" -#include "systemd/nm-sd-utils-shared.h" - -/*****************************************************************************/ - -#define _NMLOG(level, domain, ...) \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "cmdline-reader: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)) - -/*****************************************************************************/ - -typedef struct { - GHashTable * hash; - GPtrArray * array; - GPtrArray * vlan_parents; - GHashTable * explicit_ip_connections; - NMConnection *bootdev_connection; /* connection for bootdev=$ifname */ - NMConnection *default_connection; /* connection not bound to any ifname */ - char * hostname; - - /* Parameters to be set for all connections */ - gboolean ignore_auto_dns; - int dhcp_timeout; - char * dhcp4_vci; - - gint64 carrier_timeout_sec; -} Reader; - -static Reader * -reader_new(void) -{ - Reader *reader; - - reader = g_slice_new(Reader); - *reader = (Reader){ - .hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_object_unref), - .explicit_ip_connections = - g_hash_table_new_full(nm_direct_hash, NULL, g_object_unref, NULL), - .vlan_parents = g_ptr_array_new_with_free_func(g_free), - .array = g_ptr_array_new(), - }; - - return reader; -} - -static GHashTable * -reader_destroy(Reader *reader, gboolean free_hash) -{ - gs_unref_hashtable GHashTable *hash = NULL; - - g_ptr_array_unref(reader->array); - g_ptr_array_unref(reader->vlan_parents); - g_hash_table_unref(reader->explicit_ip_connections); - hash = g_steal_pointer(&reader->hash); - nm_clear_g_free(&reader->hostname); - nm_clear_g_free(&reader->dhcp4_vci); - nm_g_slice_free(reader); - if (!free_hash) - return g_steal_pointer(&hash); - return NULL; -} - -static NMConnection * -reader_add_connection(Reader *reader, const char *name, NMConnection *connection_take) -{ - char *name_dup; - - name_dup = g_strdup(name); - if (g_hash_table_insert(reader->hash, name_dup, connection_take)) - g_ptr_array_add(reader->array, name_dup); - - return connection_take; -} - -/* Returns a new connection owned by the reader */ -static NMConnection * -reader_create_connection(Reader * reader, - const char * basename, - const char * id, - const char * ifname, - const char * mac, - const char * type_name, - NMConnectionMultiConnect multi_connect) -{ - NMConnection *connection; - NMSetting * setting; - - connection = reader_add_connection(reader, basename, nm_simple_connection_new()); - - /* Start off assuming dynamic IP configurations. */ - - setting = nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, setting); - g_object_set(setting, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, - TRUE, - NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, - reader->ignore_auto_dns, - NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, - reader->dhcp_timeout, - NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, - reader->dhcp4_vci, - NULL); - - setting = nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, setting); - g_object_set(setting, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, - TRUE, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, - reader->ignore_auto_dns, - NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, - reader->dhcp_timeout, - NULL); - - setting = nm_setting_connection_new(); - nm_connection_add_setting(connection, setting); - g_object_set(setting, - NM_SETTING_CONNECTION_ID, - id, - NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), - NM_SETTING_CONNECTION_INTERFACE_NAME, - ifname, - NM_SETTING_CONNECTION_TYPE, - type_name, - NM_SETTING_CONNECTION_MULTI_CONNECT, - multi_connect, - NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, - 1, - NULL); - - if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) { - setting = nm_setting_infiniband_new(); - nm_connection_add_setting(connection, setting); - g_object_set(setting, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); - } - - if (mac) { - if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) { - setting = (NMSetting *) nm_connection_get_setting_infiniband(connection); - g_object_set(setting, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL); - } else { - setting = nm_setting_wired_new(); - nm_connection_add_setting(connection, setting); - g_object_set(setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); - } - } - - return connection; -} - -static NMConnection * -reader_get_default_connection(Reader *reader) -{ - NMConnection *con; - - if (!reader->default_connection) { - con = reader_create_connection(reader, - "default_connection", - "Wired Connection", - NULL, - NULL, - NM_SETTING_WIRED_SETTING_NAME, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE); - nm_connection_add_setting(con, nm_setting_wired_new()); - reader->default_connection = con; - } - return reader->default_connection; -} - -static NMConnection * -reader_get_connection(Reader * reader, - const char *iface_spec, - const char *type_name, - gboolean create_if_missing) -{ - NMConnection *connection = NULL; - NMSetting * setting; - const char * ifname = NULL; - gs_free char *mac = NULL; - - if (iface_spec) { - if (nm_utils_is_valid_iface_name(iface_spec, NULL)) - ifname = iface_spec; - else { - mac = nm_utils_hwaddr_canonical(iface_spec, -1); - if (!mac) - _LOGW(LOGD_CORE, "invalid interface '%s'", iface_spec); - } - } - - if (!ifname && !mac) { - NMConnection * candidate; - NMSettingConnection *s_con; - guint i; - - /* - * If ifname was not given, we'll match the connection by type. - * If the type was not given either, then we're happy with any connection but slaves. - * This is so that things like "bond=bond0:eth1,eth2 nameserver=1.3.3.7 end up - * slapping the nameserver to the most reasonable connection (bond0). - */ - for (i = 0; i < reader->array->len; i++) { - candidate = g_hash_table_lookup(reader->hash, reader->array->pdata[i]); - s_con = nm_connection_get_setting_connection(candidate); - - if (type_name == NULL && nm_setting_connection_get_master(s_con) == NULL) { - connection = candidate; - break; - } - - if (type_name != NULL - && nm_streq(nm_setting_connection_get_connection_type(s_con), type_name)) { - connection = candidate; - break; - } - } - } else - connection = g_hash_table_lookup(reader->hash, (gpointer) ifname ?: mac); - - if (!connection) { - if (!create_if_missing) - return NULL; - - if (!type_name) { - if (NM_STR_HAS_PREFIX(ifname, "ib") - || (mac && nm_utils_hwaddr_valid(mac, INFINIBAND_ALEN))) - type_name = NM_SETTING_INFINIBAND_SETTING_NAME; - else - type_name = NM_SETTING_WIRED_SETTING_NAME; - } - - connection = reader_create_connection(reader, - ifname ?: mac, - ifname ?: (mac ?: "Wired Connection"), - ifname, - mac, - type_name, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - } - setting = (NMSetting *) nm_connection_get_setting_connection(connection); - - if (type_name) { - g_object_set(setting, NM_SETTING_CONNECTION_TYPE, type_name, NULL); - if (!nm_connection_get_setting_by_name(connection, type_name)) { - setting = g_object_new(nm_setting_lookup_type(type_name), NULL); - nm_connection_add_setting(connection, setting); - } - } - - return connection; -} - -static char * -get_word(char **argument, const char separator) -{ - char *word; - int nest = 0; - - if (*argument == NULL) - return NULL; - - if (**argument == '[') { - nest++; - (*argument)++; - } - - word = *argument; - - while (**argument != '\0') { - if (nest && **argument == ']') { - **argument = '\0'; - (*argument)++; - nest--; - continue; - } - - if (nest == 0 && **argument == separator) { - **argument = '\0'; - (*argument)++; - break; - } - (*argument)++; - } - - return *word ? word : NULL; -} - -static void -connection_set(NMConnection *connection, - const char * setting_name, - const char * property, - const char * value) -{ - NMSetting * setting; - GType setting_type; - nm_auto_unref_gtypeclass GObjectClass *object_class = NULL; - GParamSpec * spec; - - setting_type = nm_setting_lookup_type(setting_name); - object_class = g_type_class_ref(setting_type); - spec = g_object_class_find_property(object_class, property); - nm_assert(spec); - - setting = nm_connection_get_setting_by_name(connection, setting_name); - if (!setting) { - setting = g_object_new(setting_type, NULL); - nm_connection_add_setting(connection, setting); - } - - if (G_IS_PARAM_SPEC_UINT(spec)) { - guint v; - - v = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT, 0); - if (errno || !nm_g_object_set_property_uint(G_OBJECT(setting), property, v, NULL)) { - _LOGW(LOGD_CORE, - "Could not set property '%s.%s' to '%s'", - setting_name, - property, - value); - } - } else if (G_IS_PARAM_SPEC_STRING(spec)) - g_object_set(setting, property, value, NULL); - else - _LOGW(LOGD_CORE, "Don't know how to set '%s' of %s", property, setting_name); -} - -static void -reader_read_all_connections_from_fw(Reader *reader, const char *sysfs_dir) -{ - gs_unref_hashtable GHashTable *ibft = NULL; - NMConnection * dt_connection; - const char * mac; - GHashTable * nic; - const char * index; - GError * error = NULL; - guint i, length; - gs_free const char ** keys = NULL; - - ibft = nmi_ibft_read(sysfs_dir); - keys = nm_utils_strdict_get_keys(ibft, TRUE, &length); - - for (i = 0; i < length; i++) { - gs_unref_object NMConnection *connection = NULL; - gs_free char * name = NULL; - - mac = keys[i]; - nic = g_hash_table_lookup(ibft, mac); - connection = nm_simple_connection_new(); - index = g_hash_table_lookup(nic, "index"); - if (!index) { - _LOGW(LOGD_CORE, "Ignoring an iBFT entry without an index"); - continue; - } - - if (!nmi_ibft_update_connection_from_nic(connection, nic, &error)) { - _LOGW(LOGD_CORE, "Unable to merge iBFT configuration: %s", error->message); - g_error_free(error); - continue; - } - - name = g_strdup_printf("ibft%s", index); - reader_add_connection(reader, name, g_steal_pointer(&connection)); - } - - dt_connection = nmi_dt_reader_parse(sysfs_dir); - if (dt_connection) - reader_add_connection(reader, "ofw", dt_connection); -} - -static void -reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4 = NULL, *s_ip6 = NULL; - gs_unref_hashtable GHashTable *ibft = NULL; - const char * tmp; - const char * tmp2; - const char * kind = NULL; - const char * client_ip = NULL; - const char * peer = NULL; - const char * gateway_ip = NULL; - const char * netmask = NULL; - const char * client_hostname = NULL; - const char * iface_spec = NULL; - const char * mtu = NULL; - const char * macaddr = NULL; - int client_ip_family = AF_UNSPEC; - int client_ip_prefix = -1; - const char * dns[2] = { - 0, - }; - int dns_addr_family[2] = { - 0, - }; - int i; - GError *error = NULL; - - if (!*argument) - return; - - tmp = get_word(&argument, ':'); - if (!*argument) { - /* ip={dhcp|on|any|dhcp6|auto6|link6|ibft} */ - kind = tmp; - } else { - tmp2 = get_word(&argument, ':'); - if (NM_IN_STRSET(tmp2, - "none", - "off", - "dhcp", - "on" - "any", - "dhcp6", - "auto", - "auto6", - "link6", - "ibft")) { - /* :{none|off|dhcp|on|any|dhcp6|auto|auto6|link6|ibft} */ - iface_spec = tmp; - kind = tmp2; - } else { - /* :[]:::: */ - client_ip = tmp; - if (client_ip) { - client_ip_family = get_ip_address_family(client_ip, TRUE); - if (client_ip_family == AF_UNSPEC) { - _LOGW(LOGD_CORE, "Invalid IP address '%s'.", client_ip); - return; - } - } - - peer = tmp2; - gateway_ip = get_word(&argument, ':'); - netmask = get_word(&argument, ':'); - client_hostname = get_word(&argument, ':'); - iface_spec = get_word(&argument, ':'); - kind = get_word(&argument, ':'); - } - - if (client_hostname && !nm_sd_hostname_is_valid(client_hostname, FALSE)) - client_hostname = NULL; - - if (client_hostname) { - g_free(reader->hostname); - reader->hostname = g_strdup(client_hostname); - } - - tmp = get_word(&argument, ':'); - dns_addr_family[0] = get_ip_address_family(tmp, FALSE); - if (dns_addr_family[0] != AF_UNSPEC) { - dns[0] = tmp; - dns[1] = get_word(&argument, ':'); - dns_addr_family[1] = get_ip_address_family(dns[1], FALSE); - if (*argument) - _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument); - } else { - mtu = tmp; - macaddr = argument; - } - } - - if (iface_spec == NULL && NM_IN_STRSET(kind, "fw", "ibft")) { - reader_read_all_connections_from_fw(reader, sysfs_dir); - return; - } - - /* Parsing done, construct the NMConnection. */ - if (iface_spec) - connection = reader_get_connection(reader, iface_spec, NULL, TRUE); - else - connection = reader_get_default_connection(reader); - - g_hash_table_add(reader->explicit_ip_connections, g_object_ref(connection)); - - s_con = nm_connection_get_setting_connection(connection); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - - if (netmask && *netmask) { - gboolean is_ipv4 = client_ip_family == AF_INET; - NMIPAddr addr; - - if (is_ipv4 && nm_utils_parse_inaddr_bin(AF_INET, netmask, NULL, &addr)) - client_ip_prefix = nm_utils_ip4_netmask_to_prefix(addr.addr4); - else - client_ip_prefix = _nm_utils_ascii_str_to_int64(netmask, 10, 0, is_ipv4 ? 32 : 128, -1); - - if (client_ip_prefix == -1) - _LOGW(LOGD_CORE, "Invalid IP mask: %s", netmask); - } - - /* Static IP configuration might be present. */ - if (client_ip && *client_ip) { - NMIPAddress *address = NULL; - NMIPAddr addr; - - if (nm_utils_parse_inaddr_prefix_bin(client_ip_family, - client_ip, - NULL, - &addr, - client_ip_prefix == -1 ? &client_ip_prefix : NULL)) { - if (client_ip_prefix == -1) { - switch (client_ip_family) { - case AF_INET: - client_ip_prefix = _nm_utils_ip4_get_default_prefix(addr.addr4); - break; - case AF_INET6: - client_ip_prefix = 64; - break; - } - } - - address = nm_ip_address_new_binary(client_ip_family, - &addr.addr_ptr, - client_ip_prefix, - &error); - if (!address) { - _LOGW(LOGD_CORE, "Invalid address '%s': %s", client_ip, error->message); - g_clear_error(&error); - } - } else - nm_assert_not_reached(); - - if (address) { - /* We don't want to have multiple devices up with the - * same static address. */ - g_object_set(s_con, - NM_SETTING_CONNECTION_MULTI_CONNECT, - NM_CONNECTION_MULTI_CONNECT_SINGLE, - NULL); - switch (client_ip_family) { - case AF_INET: - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - nm_setting_ip_config_add_address(s_ip4, address); - break; - case AF_INET6: - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - nm_setting_ip_config_add_address(s_ip6, address); - break; - default: - nm_assert_not_reached(); - break; - } - nm_ip_address_unref(address); - } - } - - /* Dynamic IP configuration configured explicitly. */ - if (NM_IN_STRSET(kind, "none", "off")) { - if (nm_setting_ip_config_get_num_addresses(s_ip6) == 0) { - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED, - NULL); - } - if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) { - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NULL); - } - } else if (nm_streq0(kind, "dhcp")) { - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - if (nm_setting_ip_config_get_num_addresses(s_ip6) == 0) { - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NULL); - } - } else if (NM_IN_STRSET(kind, "auto6", "dhcp6")) { - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) { - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NULL); - } - } else if (nm_streq0(kind, "link6")) { - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) { - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NULL); - } - } else if (nm_streq0(kind, "ibft")) { - NMSettingWired *s_wired; - const char * mac = NULL; - const char * ifname; - gs_free char * mac_free = NULL; - gs_free char * address_path = NULL; - GHashTable * nic = NULL; - - if ((s_wired = nm_connection_get_setting_wired(connection)) - && (mac = nm_setting_wired_get_mac_address(s_wired))) { - /* got mac from the connection */ - } else if ((ifname = nm_connection_get_interface_name(connection))) { - /* read it from sysfs */ - address_path = g_build_filename(sysfs_dir, "class", "net", ifname, "address", NULL); - if (g_file_get_contents(address_path, &mac_free, NULL, &error)) { - g_strchomp(mac_free); - mac = mac_free; - } else { - _LOGW(LOGD_CORE, "Can't get a MAC address for %s: %s", ifname, error->message); - g_clear_error(&error); - } - } - - if (mac) { - gs_free char *mac_up = NULL; - - mac_up = g_ascii_strup(mac, -1); - ibft = nmi_ibft_read(sysfs_dir); - nic = g_hash_table_lookup(ibft, mac_up); - if (!nic) - _LOGW(LOGD_CORE, "No iBFT NIC for %s (%s)", iface_spec, mac_up); - } - - if (nic) { - if (!nmi_ibft_update_connection_from_nic(connection, nic, &error)) { - _LOGW(LOGD_CORE, "Unable to merge iBFT configuration: %s", error->message); - g_clear_error(&error); - } - } - } - - if (peer && *peer) - _LOGW(LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer); - - if (gateway_ip && *gateway_ip) { - switch (get_ip_address_family(gateway_ip, FALSE)) { - case AF_INET: - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); - break; - case AF_INET6: - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); - break; - default: - _LOGW(LOGD_CORE, "Invalid gateway: %s", gateway_ip); - break; - } - } - - if (client_hostname && *client_hostname) { - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, client_hostname, NULL); - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, client_hostname, NULL); - } - - for (i = 0; i < 2; i++) { - if (dns_addr_family[i] == AF_UNSPEC) - break; - if (nm_utils_ipaddr_is_valid(dns_addr_family[i], dns[i])) { - switch (dns_addr_family[i]) { - case AF_INET: - nm_setting_ip_config_add_dns(s_ip4, dns[i]); - break; - case AF_INET6: - nm_setting_ip_config_add_dns(s_ip6, dns[i]); - break; - default: - _LOGW(LOGD_CORE, "Unknown address family: %s", dns[i]); - break; - } - } else { - _LOGW(LOGD_CORE, "Invalid name server: %s", dns[i]); - } - } - - if (mtu && *mtu) - connection_set(connection, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MTU, mtu); - - if (macaddr && *macaddr) - connection_set(connection, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS, - macaddr); -} - -static void -reader_parse_master(Reader *reader, char *argument, const char *type_name, const char *default_name) -{ - NMConnection * connection; - NMSettingConnection *s_con; - gs_free char * master_to_free = NULL; - const char * master; - char * slaves; - const char * slave; - char * opts; - const char * mtu = NULL; - - master = get_word(&argument, ':'); - if (!master) - master = master_to_free = g_strdup_printf("%s0", default_name ?: type_name); - slaves = get_word(&argument, ':'); - - connection = reader_get_connection(reader, master, type_name, TRUE); - s_con = nm_connection_get_setting_connection(connection); - master = nm_setting_connection_get_uuid(s_con); - - if (nm_streq(type_name, NM_SETTING_BRIDGE_SETTING_NAME)) { - NMSettingBridge *s_bridge = nm_connection_get_setting_bridge(connection); - - /* Avoid the forwarding delay */ - g_object_set(s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); - } else if (nm_streq(type_name, NM_SETTING_BOND_SETTING_NAME)) { - NMSettingBond *s_bond = nm_connection_get_setting_bond(connection); - - opts = get_word(&argument, ':'); - while (opts && *opts) { - gs_free_error GError *error = NULL; - char * opt; - const char * opt_name; - - opt = get_word(&opts, ','); - opt_name = get_word(&opt, '='); - - if (!_nm_setting_bond_validate_option(opt_name, opt, &error)) { - _LOGW(LOGD_CORE, - "Ignoring invalid bond option: %s%s%s = %s%s%s: %s", - NM_PRINT_FMT_QUOTE_STRING(opt_name), - NM_PRINT_FMT_QUOTE_STRING(opt), - error->message); - continue; - } - nm_setting_bond_add_option(s_bond, opt_name, opt); - } - - mtu = get_word(&argument, ':'); - } - - if (mtu) - connection_set(connection, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MTU, mtu); - - do { - slave = get_word(&slaves, ','); - if (slave == NULL) - slave = "eth0"; - - connection = reader_get_connection(reader, slave, NULL, TRUE); - s_con = nm_connection_get_setting_connection(connection); - g_object_set(s_con, - NM_SETTING_CONNECTION_SLAVE_TYPE, - type_name, - NM_SETTING_CONNECTION_MASTER, - master, - NULL); - } while (slaves && *slaves != '\0'); - - if (argument && *argument) - _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument); -} - -static void -reader_add_routes(Reader *reader, GPtrArray *array) -{ - guint i; - - for (i = 0; i < array->len; i++) { - NMConnection * connection = NULL; - const char * net; - const char * gateway; - const char * interface; - int family = AF_UNSPEC; - NMIPAddr net_addr = {}; - NMIPAddr gateway_addr = {}; - int net_prefix = -1; - NMIPRoute * route; - NMSettingIPConfig *s_ip; - char * argument; - gs_free_error GError *error = NULL; - - argument = array->pdata[i]; - net = get_word(&argument, ':'); - gateway = get_word(&argument, ':'); - interface = get_word(&argument, ':'); - - if (interface) - connection = reader_get_connection(reader, interface, NULL, TRUE); - if (!connection) - connection = reader->bootdev_connection; - if (!connection) - connection = reader_get_connection(reader, interface, NULL, FALSE); - if (!connection) - connection = reader_get_default_connection(reader); - - if (net && *net) { - if (!nm_utils_parse_inaddr_prefix_bin(family, net, &family, &net_addr, &net_prefix)) { - _LOGW(LOGD_CORE, "Unrecognized address: %s", net); - continue; - } - } - - if (gateway && *gateway) { - if (!nm_utils_parse_inaddr_bin(family, gateway, &family, &gateway_addr)) { - _LOGW(LOGD_CORE, "Unrecognized address: %s", gateway); - continue; - } - } - - switch (family) { - case AF_INET: - s_ip = nm_connection_get_setting_ip4_config(connection); - if (net_prefix == -1) - net_prefix = 32; - break; - case AF_INET6: - s_ip = nm_connection_get_setting_ip6_config(connection); - if (net_prefix == -1) - net_prefix = 128; - break; - default: - _LOGW(LOGD_CORE, "Unknown address family: %s", net); - continue; - } - - route = nm_ip_route_new_binary(family, - &net_addr.addr_ptr, - net_prefix, - &gateway_addr.addr_ptr, - -1, - &error); - if (!route) { - g_warning("Invalid route '%s via %s': %s\n", net, gateway, error->message); - continue; - } - - nm_setting_ip_config_add_route(s_ip, route); - nm_ip_route_unref(route); - } -} - -static void -reader_parse_vlan(Reader *reader, char *argument) -{ - NMConnection * connection; - NMSettingVlan *s_vlan; - const char * vlan; - const char * phy; - const char * vlanid; - - vlan = get_word(&argument, ':'); - phy = get_word(&argument, ':'); - - for (vlanid = vlan + strlen(vlan); vlanid > vlan; vlanid--) { - if (!g_ascii_isdigit(*(vlanid - 1))) - break; - } - - connection = reader_get_connection(reader, vlan, NM_SETTING_VLAN_SETTING_NAME, TRUE); - - s_vlan = nm_connection_get_setting_vlan(connection); - g_object_set(s_vlan, - NM_SETTING_VLAN_PARENT, - phy, - NM_SETTING_VLAN_ID, - (guint) _nm_utils_ascii_str_to_int64(vlanid, 10, 0, G_MAXUINT, G_MAXUINT), - NULL); - - if (argument && *argument) - _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument); - - if (!nm_strv_ptrarray_contains(reader->vlan_parents, phy)) - g_ptr_array_add(reader->vlan_parents, g_strdup(phy)); -} - -static void -reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames) -{ - const char * nettype; - const char * subchannels[4] = {0, 0, 0, 0}; - const char * tmp; - gs_free char * ifname = NULL; - const char * prefix; - NMConnection * connection; - NMSettingWired *s_wired; - static int count_ctc = 0; - static int count_eth = 0; - int index; - - nettype = get_word(&argument, ','); - subchannels[0] = get_word(&argument, ','); - subchannels[1] = get_word(&argument, ','); - - /* Without subchannels we can't univocally match - * a device. */ - if (!subchannels[0] || !subchannels[1]) - return; - - if (nm_streq0(nettype, "ctc")) { - if (net_ifnames == TRUE) { - prefix = "sl"; - } else { - prefix = "ctc"; - index = count_ctc++; - } - } else { - subchannels[2] = get_word(&argument, ','); - if (net_ifnames == TRUE) { - prefix = "en"; - } else { - prefix = "eth"; - index = count_eth++; - } - } - - if (net_ifnames == TRUE) { - const char *bus_id; - size_t bus_id_len; - size_t bus_id_start; - - /* The following logic is taken from names_ccw() in systemd/src/udev/udev-builtin-net_id.c */ - bus_id = subchannels[0]; - bus_id_len = strlen(bus_id); - bus_id_start = strspn(bus_id, ".0"); - bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; - - ifname = g_strdup_printf("%sc%s", prefix, bus_id); - } else { - ifname = g_strdup_printf("%s%d", prefix, index); - } - - connection = reader_get_connection(reader, ifname, NM_SETTING_WIRED_SETTING_NAME, FALSE); - if (!connection) - return; - s_wired = nm_connection_get_setting_wired(connection); - g_object_set(s_wired, - NM_SETTING_WIRED_S390_NETTYPE, - nettype, - NM_SETTING_WIRED_S390_SUBCHANNELS, - &subchannels, - NULL); - - while ((tmp = get_word(&argument, ',')) != NULL) { - char *val; - - val = strchr(tmp, '='); - if (val) { - gs_free char *key = NULL; - - key = g_strndup(tmp, val - tmp); - val[0] = '\0'; - val++; - nm_setting_wired_add_s390_option(s_wired, key, val); - } - } -} - -static void -_normalize_conn(gpointer key, gpointer value, gpointer user_data) -{ - NMConnection *connection = value; - - nm_connection_normalize(connection, NULL, NULL, NULL); -} - -static void -reader_add_nameservers(Reader *reader, GPtrArray *nameservers) -{ - NMConnection * connection; - NMSettingIPConfig *s_ip; - GHashTableIter iter; - int addr_family; - const char * ns; - guint i; - - for (i = 0; i < nameservers->len; i++) { - ns = nameservers->pdata[i]; - addr_family = get_ip_address_family(ns, FALSE); - if (addr_family == AF_UNSPEC) { - _LOGW(LOGD_CORE, "Unknown address family: %s", ns); - continue; - } - - g_hash_table_iter_init(&iter, reader->hash); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &connection)) { - switch (addr_family) { - case AF_INET: - s_ip = nm_connection_get_setting_ip4_config(connection); - if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip), - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) - continue; - break; - case AF_INET6: - s_ip = nm_connection_get_setting_ip6_config(connection); - if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip), - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_METHOD_DHCP, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) - continue; - break; - default: - nm_assert_not_reached(); - continue; - } - - nm_setting_ip_config_add_dns(s_ip, ns); - } - } -} - -static void -connection_set_needed(NMConnection *connection) -{ - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection(connection); - if (!nm_streq0(nm_setting_connection_get_connection_type(s_con), NM_SETTING_WIRED_SETTING_NAME)) - return; - - g_object_set(s_con, - NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, - (int) NMI_WAIT_DEVICE_TIMEOUT_MS, - NULL); -} - -static void -connection_set_needed_cb(gpointer key, gpointer value, gpointer user_data) -{ - connection_set_needed(value); -} - -GHashTable * -nmi_cmdline_reader_parse(const char * sysfs_dir, - const char *const *argv, - char ** hostname, - gint64 * carrier_timeout_sec) -{ - Reader * reader; - const char * tag; - gboolean ignore_bootif = FALSE; - gboolean neednet = FALSE; - gs_free char * bootif_val = NULL; - gs_free char * bootdev = NULL; - gboolean net_ifnames = TRUE; - gs_unref_ptrarray GPtrArray *nameservers = NULL; - gs_unref_ptrarray GPtrArray *routes = NULL; - gs_unref_ptrarray GPtrArray *znets = NULL; - int i; - guint64 dhcp_timeout = 90; - guint64 dhcp_num_tries = 1; - - reader = reader_new(); - - for (i = 0; argv[i]; i++) { - gs_free char *argument_clone = NULL; - char * argument; - - argument_clone = g_strdup(argv[i]); - argument = argument_clone; - - tag = get_word(&argument, '='); - - if (nm_streq(tag, "net.ifnames")) - net_ifnames = !nm_streq(argument, "0"); - else if (nm_streq(tag, "rd.peerdns")) - reader->ignore_auto_dns = !_nm_utils_ascii_str_to_bool(argument, TRUE); - else if (nm_streq(tag, "rd.net.timeout.dhcp")) { - if (nm_streq0(argument, "infinity")) { - dhcp_timeout = G_MAXINT32; - } else { - dhcp_timeout = - _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_timeout); - } - } else if (nm_streq(tag, "rd.net.dhcp.retry")) { - dhcp_num_tries = - _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_num_tries); - } else if (nm_streq(tag, "rd.net.dhcp.vendor-class")) { - if (nm_utils_validate_dhcp4_vendor_class_id(argument, NULL)) - nm_utils_strdup_reset(&reader->dhcp4_vci, argument); - } else if (nm_streq(tag, "rd.net.timeout.carrier")) { - reader->carrier_timeout_sec = - _nm_utils_ascii_str_to_int64(argument, 10, 0, G_MAXINT32, 0); - } - } - - reader->dhcp_timeout = NM_CLAMP(dhcp_timeout * dhcp_num_tries, 1, G_MAXINT32); - - for (i = 0; argv[i]; i++) { - gs_free char *argument_clone = NULL; - char * argument; - char * word; - - argument_clone = g_strdup(argv[i]); - argument = argument_clone; - - tag = get_word(&argument, '='); - if (nm_streq(tag, "ip")) - reader_parse_ip(reader, sysfs_dir, argument); - else if (nm_streq(tag, "rd.route")) { - if (!routes) - routes = g_ptr_array_new_with_free_func(g_free); - g_ptr_array_add(routes, g_strdup(argument)); - } else if (nm_streq(tag, "bridge")) - reader_parse_master(reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); - else if (nm_streq(tag, "bond")) - reader_parse_master(reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL); - else if (nm_streq(tag, "team")) - reader_parse_master(reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); - else if (nm_streq(tag, "vlan")) - reader_parse_vlan(reader, argument); - else if (nm_streq(tag, "bootdev")) { - g_free(bootdev); - bootdev = g_strdup(argument); - } else if (nm_streq(tag, "nameserver")) { - word = get_word(&argument, '\0'); - if (word) { - if (!nameservers) - nameservers = g_ptr_array_new_with_free_func(g_free); - g_ptr_array_add(nameservers, g_strdup(word)); - } - if (argument && *argument) - _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument); - } else if (nm_streq(tag, "rd.iscsi.ibft") && _nm_utils_ascii_str_to_bool(argument, TRUE)) - reader_read_all_connections_from_fw(reader, sysfs_dir); - else if (nm_streq(tag, "rd.bootif")) - ignore_bootif = !_nm_utils_ascii_str_to_bool(argument, TRUE); - else if (nm_streq(tag, "rd.neednet")) - neednet = _nm_utils_ascii_str_to_bool(argument, TRUE); - else if (nm_streq(tag, "rd.znet")) { - if (!znets) - znets = g_ptr_array_new_with_free_func(g_free); - g_ptr_array_add(znets, g_strdup(argument)); - } else if (g_ascii_strcasecmp(tag, "BOOTIF") == 0) { - nm_clear_g_free(&bootif_val); - bootif_val = g_strdup(argument); - } - } - - for (i = 0; i < reader->vlan_parents->len; i++) { - NMConnection * connection; - NMSettingIPConfig *s_ip; - - /* Disable IP configuration for parent connections of VLANs, - * unless those interfaces were explicitly configured otherwise. */ - - connection = reader_get_connection(reader, reader->vlan_parents->pdata[i], NULL, TRUE); - if (!g_hash_table_contains(reader->explicit_ip_connections, connection)) { - s_ip = nm_connection_get_setting_ip4_config(connection); - if (s_ip) { - g_object_set(s_ip, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NULL); - } - - s_ip = nm_connection_get_setting_ip6_config(connection); - if (s_ip) { - g_object_set(s_ip, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED, - NULL); - } - } - } - - if (ignore_bootif) - nm_clear_g_free(&bootif_val); - if (bootif_val) { - NMConnection * connection; - NMSettingWired *s_wired; - const char * bootif = bootif_val; - char prefix[4]; - - if (!nm_utils_hwaddr_valid(bootif, ETH_ALEN)) { - strncpy(prefix, bootif, 3); - prefix[3] = '\0'; - - if (NM_IN_STRSET(prefix, "01-", "01:", "00-", "00:") - && nm_utils_hwaddr_valid(&bootif[3], ETH_ALEN)) { - /* - * BOOTIF MAC address can be prefixed with a hardware type identifier. - * "01" stays for "wired", "00" is also accepted as it means "undefined". - * No others are known. - */ - bootif += 3; - } - } - - connection = reader_get_connection(reader, NULL, NM_SETTING_WIRED_SETTING_NAME, FALSE); - if (!connection) - connection = reader_get_default_connection(reader); - - s_wired = nm_connection_get_setting_wired(connection); - - if (nm_connection_get_interface_name(connection) - || (nm_setting_wired_get_mac_address(s_wired) - && !nm_utils_hwaddr_matches(nm_setting_wired_get_mac_address(s_wired), - -1, - bootif, - -1))) { - connection = reader_create_connection(reader, - "bootif_connection", - "BOOTIF Connection", - NULL, - bootif, - NM_SETTING_WIRED_SETTING_NAME, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - } else { - g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, bootif, NULL); - } - } - - if (bootdev) { - NMConnection *connection; - - connection = reader_get_connection(reader, bootdev, NULL, TRUE); - reader->bootdev_connection = connection; - connection_set_needed(connection); - } - - if (neednet) { - if (g_hash_table_size(reader->hash) == 0) { - /* Make sure there's some connection. */ - reader_get_default_connection(reader); - } - - g_hash_table_foreach(reader->hash, connection_set_needed_cb, NULL); - } - - if (routes) - reader_add_routes(reader, routes); - - if (nameservers) - reader_add_nameservers(reader, nameservers); - - if (znets) { - for (i = 0; i < znets->len; i++) - reader_parse_rd_znet(reader, znets->pdata[i], net_ifnames); - } - - g_hash_table_foreach(reader->hash, _normalize_conn, NULL); - - NM_SET_OUT(hostname, g_steal_pointer(&reader->hostname)); - - NM_SET_OUT(carrier_timeout_sec, reader->carrier_timeout_sec); - - return reader_destroy(reader, FALSE); -} diff --git a/src/core/initrd/nmi-dt-reader.c b/src/core/initrd/nmi-dt-reader.c deleted file mode 100644 index 63e4524b..00000000 --- a/src/core/initrd/nmi-dt-reader.c +++ /dev/null @@ -1,371 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-initrd-generator.h" - -#include -#include - -#include "nm-core-internal.h" - -/*****************************************************************************/ - -#define _NMLOG(level, domain, ...) \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "dt-reader: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__)) - -/*****************************************************************************/ - -static gboolean -dt_get_property(const char *base, - const char *dev, - const char *prop, - char ** contents, - size_t * length) -{ - gs_free char *filename = g_build_filename(base, dev, prop, NULL); - gs_free_error GError *error = NULL; - - if (!g_file_test(filename, G_FILE_TEST_EXISTS)) - return FALSE; - - if (!contents) - return TRUE; - - if (!g_file_get_contents(filename, contents, length, &error)) { - _LOGW(LOGD_CORE, "%s: Can not read the %s property: %s", dev, prop, error->message); - return FALSE; - } - - return TRUE; -} - -static NMIPAddress * -dt_get_ipaddr_property(const char *base, const char *dev, const char *prop, int *family) -{ - gs_free char *buf = NULL; - size_t len; - int f; - - if (!dt_get_property(base, dev, prop, &buf, &len)) - return NULL; - - f = nm_utils_addr_family_from_size(len); - if (f == AF_UNSPEC || (*family != AF_UNSPEC && *family != f)) { - _LOGW(LOGD_CORE, "%s: Address %s has unrecognized length (%zd)", dev, prop, len); - return NULL; - } - - *family = f; - return nm_ip_address_new_binary(f, buf, 0, NULL); -} - -static char * -dt_get_hwaddr_property(const char *base, const char *dev, const char *prop) -{ - gs_free guint8 *buf = NULL; - size_t len; - - if (!dt_get_property(base, dev, prop, (char **) &buf, &len)) - return NULL; - - if (len != ETH_ALEN) { - _LOGW(LOGD_CORE, "%s: MAC address %s has unrecognized length (%zd)", dev, prop, len); - return NULL; - } - - return g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", - buf[0], - buf[1], - buf[2], - buf[3], - buf[4], - buf[4]); -} - -static NMIPAddress * -str_addr(const char *str, int *family) -{ - NMIPAddr addr_bin; - - if (!nm_utils_parse_inaddr_bin_full(*family, TRUE, str, family, &addr_bin)) { - _LOGW(LOGD_CORE, "Malformed IP address: '%s'", str); - return NULL; - } - return nm_ip_address_new_binary(*family, &addr_bin, 0, NULL); -} - -NMConnection * -nmi_dt_reader_parse(const char *sysfs_dir) -{ - gs_unref_object NMConnection *connection = NULL; - gs_free char * base = NULL; - gs_free char * bootpath = NULL; - gs_strfreev char ** tokens = NULL; - char * path = NULL; - gboolean bootp = FALSE; - const char * s_ipaddr = NULL; - const char * s_netmask = NULL; - const char * s_gateway = NULL; - nm_auto_unref_ip_address NMIPAddress *ipaddr = NULL; - nm_auto_unref_ip_address NMIPAddress *gateway = NULL; - const char * duplex = NULL; - gs_free char * hwaddr = NULL; - gs_free char * local_hwaddr = NULL; - gs_free char * hostname = NULL; - guint32 speed = 0; - int prefix = -1; - NMSettingIPConfig * s_ip = NULL; - NMSetting * s_ip4 = NULL; - NMSetting * s_ip6 = NULL; - NMSetting * s_wired = NULL; - int family = AF_UNSPEC; - int i = 0; - char * c; - gs_free_error GError *error = NULL; - - base = g_build_filename(sysfs_dir, "firmware", "devicetree", "base", NULL); - - if (!dt_get_property(base, "chosen", "bootpath", &bootpath, NULL)) - return NULL; - - c = strchr(bootpath, ':'); - if (c) { - *c = '\0'; - path = c + 1; - } else { - path = ""; - } - - dt_get_property(base, "chosen", "client-name", &hostname, NULL); - - local_hwaddr = dt_get_hwaddr_property(base, bootpath, "local-mac-address"); - hwaddr = dt_get_hwaddr_property(base, bootpath, "mac-address"); - if (nm_streq0(local_hwaddr, hwaddr)) - nm_clear_g_free(&local_hwaddr); - - tokens = g_strsplit(path, ",", 0); - - /* - * Ethernet device settings. Defined by "Open Firmware, - * Recommended Practice: Device Support Extensions, Version 1.0 [1] - * [1] https://www.devicetree.org/open-firmware/practice/devicex/dse1_0a.ps - */ - - for (i = 0; tokens[i]; i++) { - /* Skip these. They have magical meaning for OpenFirmware. */ - if (NM_IN_STRSET(tokens[i], "nfs", "last")) - continue; - if (nm_streq(tokens[i], "promiscuous")) { - /* Ignore. */ - continue; - } - - if (g_str_has_prefix(tokens[i], "speed=")) { - speed = _nm_utils_ascii_str_to_int64(tokens[i] + 6, 10, 0, G_MAXUINT32, 0); - continue; - } - - if (g_str_has_prefix(tokens[i], "duplex=auto")) { - continue; - } else if (g_str_has_prefix(tokens[i], "duplex=half") - || g_str_has_prefix(tokens[i], "duplex=full")) { - duplex = tokens[i] + 7; - continue; - } - - break; - } - - /* - * Network boot configuration. Defined by "Open Firmware, - * Recommended Practice: TFTP Booting Extension, Version 1.0 [1] - * [1] https://www.devicetree.org/open-firmware/practice/obp-tftp/tftp1_0.pdf - */ - - for (; tokens[i]; i++) { - if (NM_IN_STRSET(tokens[i], "bootp", "dhcp", "rarp")) { - bootp = TRUE; - continue; - } - break; - } - - /* s-iaddr, or perhaps a raw absolute filename */ - if (tokens[i] && tokens[i][0] != '/') - i++; - - /* filename */ - if (tokens[i]) - i++; - - /* c-iaddr */ - if (tokens[i]) { - s_ipaddr = tokens[i]; - i++; - } - - /* g-iaddr */ - if (tokens[i]) { - s_gateway = tokens[i]; - i++; - } - - if (tokens[i] && (strchr(tokens[i], '.') || strchr(tokens[i], ':'))) { - /* yaboot claims the mask can be specified here, - * though it doesn't support it. */ - s_netmask = tokens[i]; - i++; - } - - /* bootp-retries */ - if (tokens[i]) - i++; - - /* tftp-retries */ - if (tokens[i]) - i++; - - if (tokens[i]) { - /* yaboot accepts a mask here */ - s_netmask = tokens[i]; - i++; - } - - connection = nm_simple_connection_new(); - - nm_connection_add_setting(connection, - g_object_new(NM_TYPE_SETTING_CONNECTION, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRED_SETTING_NAME, - NM_SETTING_CONNECTION_ID, - "OpenFirmware Connection", - NULL)); - - s_ip4 = nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, s_ip4); - - s_ip6 = nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, s_ip6); - - g_object_set(s_ip6, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - NULL); - - if (!bootp && dt_get_property(base, "chosen", "bootp-response", NULL, NULL)) - bootp = TRUE; - - if (!bootp) { - nm_auto_unref_ip_address NMIPAddress *netmask = NULL; - - netmask = dt_get_ipaddr_property(base, "chosen", "netmask-ip", &family); - gateway = dt_get_ipaddr_property(base, "chosen", "gateway-ip", &family); - if (gateway) - s_gateway = nm_ip_address_get_address(gateway); - ipaddr = dt_get_ipaddr_property(base, "chosen", "client-ip", &family); - - if (family == AF_UNSPEC) { - nm_assert(netmask == NULL); - nm_assert(gateway == NULL); - nm_assert(ipaddr == NULL); - - netmask = str_addr(s_netmask, &family); - ipaddr = str_addr(s_ipaddr, &family); - - prefix = _nm_utils_ascii_str_to_int64(s_netmask, 10, 0, 128, -1); - } - - if (prefix == -1 && family == AF_INET && netmask) { - guint32 netmask_v4; - - nm_ip_address_get_address_binary(netmask, &netmask_v4); - prefix = nm_utils_ip4_netmask_to_prefix(netmask_v4); - } - - if (prefix == -1) - _LOGW(LOGD_CORE, "Unable to determine the network prefix"); - else - nm_ip_address_set_prefix(ipaddr, prefix); - } - - if (!ipaddr) { - family = AF_UNSPEC; - bootp = TRUE; - } - - if (bootp) { - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, - hostname, - NULL); - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, - hostname, - NULL); - } else { - switch (family) { - case AF_INET: - s_ip = (NMSettingIPConfig *) s_ip4; - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NULL); - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED, - NULL); - break; - case AF_INET6: - s_ip = (NMSettingIPConfig *) s_ip6; - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NULL); - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL, - NULL); - break; - default: - g_return_val_if_reached(NULL); - } - - nm_setting_ip_config_add_address(s_ip, ipaddr); - g_object_set(s_ip, NM_SETTING_IP_CONFIG_GATEWAY, s_gateway, NULL); - } - - if (duplex || speed || hwaddr || local_hwaddr) { - s_wired = nm_setting_wired_new(); - nm_connection_add_setting(connection, s_wired); - - g_object_set(s_wired, - NM_SETTING_WIRED_SPEED, - speed, - NM_SETTING_WIRED_DUPLEX, - duplex, - NM_SETTING_WIRED_MAC_ADDRESS, - hwaddr, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS, - local_hwaddr, - NULL); - } - - if (!nm_connection_normalize(connection, NULL, NULL, &error)) { - _LOGW(LOGD_CORE, "Generated an invalid connection: %s", error->message); - nm_clear_pointer(&connection, g_object_unref); - } - - return g_steal_pointer(&connection); -} diff --git a/src/core/initrd/nmi-ibft-reader.c b/src/core/initrd/nmi-ibft-reader.c deleted file mode 100644 index 9895cda4..00000000 --- a/src/core/initrd/nmi-ibft-reader.c +++ /dev/null @@ -1,463 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-initrd-generator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-core-internal.h" -#include "NetworkManagerUtils.h" - -/*****************************************************************************/ - -#define _NMLOG(level, domain, ...) \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "ibft-reader: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__)) - -/*****************************************************************************/ - -static GHashTable * -load_one_nic(const char *sysfs_dir, const char *dir_name) -{ - gs_free char *nic_path = g_build_filename(sysfs_dir, dir_name, NULL); - GDir * nic_dir; - const char * entry_name; - char * content; - gs_free_error GError *error = NULL; - GHashTable * nic; - - g_return_val_if_fail(sysfs_dir != NULL, FALSE); - - nic_dir = g_dir_open(nic_path, 0, &error); - if (!nic_dir) { - _LOGW(LOGD_CORE, "Can't open %s: %s", nic_path, error->message); - return NULL; - } - - nic = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); - while ((entry_name = g_dir_read_name(nic_dir))) { - gs_free char *entry_path = g_build_filename(nic_path, entry_name, NULL); - - if (!g_file_test(entry_path, G_FILE_TEST_IS_REGULAR)) - continue; - - if (!g_file_get_contents(entry_path, &content, NULL, &error)) { - _LOGW(LOGD_CORE, "Can't read %s: %s", entry_path, error->message); - g_clear_error(&error); - continue; - } - - g_strchomp(content); - if (!g_hash_table_insert(nic, g_strdup(entry_name), content)) - _LOGW(LOGD_CORE, "Duplicate iBFT entry: %s", entry_name); - } - - g_dir_close(nic_dir); - - return nic; -} - -GHashTable * -nmi_ibft_read(const char *sysfs_dir) -{ - gs_free char *ibft_path = NULL; - GDir * ibft_dir; - const char * dir_name; - GHashTable * ibft, *nic; - char * mac; - gs_free_error GError *error = NULL; - - g_return_val_if_fail(sysfs_dir != NULL, FALSE); - - ibft_path = g_build_filename(sysfs_dir, "firmware", "ibft", NULL); - - ibft = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_hash_table_unref); - - if (!g_file_test(ibft_path, G_FILE_TEST_IS_DIR)) - nm_utils_modprobe(NULL, FALSE, "iscsi_ibft", NULL); - if (!g_file_test(ibft_path, G_FILE_TEST_IS_DIR)) - return ibft; - - ibft_dir = g_dir_open(ibft_path, 0, &error); - if (!ibft_dir) { - _LOGW(LOGD_CORE, "Unable to open iBFT firmware directory: %s", error->message); - return ibft; - } - - while ((dir_name = g_dir_read_name(ibft_dir))) { - if (!g_str_has_prefix(dir_name, "ethernet")) - continue; - - nic = load_one_nic(ibft_path, dir_name); - mac = g_hash_table_lookup(nic, "mac"); - - if (!mac) { - _LOGW(LOGD_CORE, "Ignoring an iBFT record without a MAC address"); - g_hash_table_unref(nic); - continue; - } - - mac = g_ascii_strup(mac, -1); - if (!g_hash_table_insert(ibft, mac, nic)) - _LOGW(LOGD_CORE, "Duplicate iBFT record for %s", mac); - } - - g_dir_close(ibft_dir); - - return ibft; -} - -static gboolean -ip_setting_add_from_block(GHashTable *nic, NMConnection *connection, GError **error) -{ - NMSettingIPConfig *s_ip = NULL; - NMSettingIPConfig *s_ip4 = NULL; - NMSettingIPConfig *s_ip6 = NULL; - NMIPAddress * addr; - const char * s_ipaddr = NULL; - const char * s_prefix = NULL; - const char * s_gateway = NULL; - const char * s_dns1 = NULL; - const char * s_dns2 = NULL; - const char * s_origin = NULL; - const char * method = NULL; - int family; - gint64 prefix; - - s_ipaddr = (const char *) g_hash_table_lookup(nic, "ip-addr"); - s_prefix = (const char *) g_hash_table_lookup(nic, "prefix-len"); - s_gateway = (const char *) g_hash_table_lookup(nic, "gateway"); - s_dns1 = (const char *) g_hash_table_lookup(nic, "primary-dns"); - s_dns2 = (const char *) g_hash_table_lookup(nic, "secondary-dns"); - s_origin = (const char *) g_hash_table_lookup(nic, "origin"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - if (!s_ip4) { - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, (NMSetting *) s_ip4); - } - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - if (!s_ip6) { - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, (NMSetting *) s_ip6); - - g_object_set(s_ip6, - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, - (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, - NULL); - } - - family = get_ip_address_family(s_ipaddr, FALSE); - if (family == AF_UNSPEC) - family = get_ip_address_family(s_gateway, FALSE); - - switch (family) { - case AF_INET: - s_ip = s_ip4; - g_object_set(s_ip6, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED, - NULL); - break; - case AF_INET6: - s_ip = s_ip6; - g_object_set(s_ip4, - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NULL); - break; - default: - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: invalid IP address '%s'.", - s_ipaddr); - return FALSE; - } - - if ((nm_streq0(s_origin, "3") && family == AF_INET) - || (nm_streq0(s_origin, "4") && family == AF_INET)) { - method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - } else if (nm_streq0(s_origin, "3") && family == AF_INET6) { - method = NM_SETTING_IP6_CONFIG_METHOD_DHCP; - } else if (nm_streq0(s_origin, "4") && family == AF_INET6) { - method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - } else if (family == AF_INET) { - method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL; - } else if (family == AF_INET6) { - method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL; - } else { - g_return_val_if_reached(FALSE); - } - g_object_set(s_ip, - NM_SETTING_IP_CONFIG_METHOD, - method, - NM_SETTING_IP_CONFIG_MAY_FAIL, - FALSE, - NULL); - - if (s_gateway && !nm_utils_ipaddr_is_valid(family, s_gateway)) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: invalid IP gateway '%s'.", - s_gateway); - return FALSE; - } - - if (s_dns1 && !nm_utils_ipaddr_is_valid(family, s_dns1)) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: invalid DNS1 address '%s'.", - s_dns1); - return FALSE; - } - - if (s_dns2 && !nm_utils_ipaddr_is_valid(family, s_dns2)) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: invalid DNS2 address '%s'.", - s_dns2); - return FALSE; - } - - if (s_ipaddr) { - prefix = _nm_utils_ascii_str_to_int64(s_prefix, 10, 0, 128, -1); - if (prefix == -1) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: invalid IP prefix '%s'.", - s_prefix); - return FALSE; - } - - addr = nm_ip_address_new(family, s_ipaddr, prefix, error); - if (!addr) { - g_prefix_error(error, "iBFT: "); - return FALSE; - } - - nm_setting_ip_config_add_address(s_ip, addr); - nm_ip_address_unref(addr); - - g_object_set(s_ip, NM_SETTING_IP_CONFIG_GATEWAY, s_gateway, NULL); - } - - if (s_dns1) - nm_setting_ip_config_add_dns(s_ip, s_dns1); - if (s_dns2) - nm_setting_ip_config_add_dns(s_ip, s_dns2); - - return TRUE; -} - -static gboolean -connection_setting_add(GHashTable * nic, - NMConnection *connection, - const char * type, - const char * prefix, - GError ** error) -{ - NMSetting * s_con; - char * id, *uuid; - const char *s_index, *s_hwaddr, *s_ipaddr, *s_vlanid; - - s_index = (const char *) g_hash_table_lookup(nic, "index"); - s_hwaddr = (const char *) g_hash_table_lookup(nic, "mac"); - s_ipaddr = (const char *) g_hash_table_lookup(nic, "ip-addr"); - s_vlanid = (const char *) g_hash_table_lookup(nic, "vlan"); - - if (!s_hwaddr) { - g_set_error_literal(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: missing MAC address"); - return FALSE; - } - - id = g_strdup_printf("iBFT%s%s Connection%s%s", - prefix ? " " : "", - prefix ? prefix : "", - s_index ? " " : "", - s_index ? s_index : ""); - - uuid = _nm_utils_uuid_generate_from_strings("ibft", - s_hwaddr, - s_vlanid ? "V" : "v", - s_vlanid ? s_vlanid : "", - s_ipaddr ? "A" : "DHCP", - s_ipaddr ? s_ipaddr : "", - NULL); - - s_con = (NMSetting *) nm_connection_get_setting_connection(connection); - if (!s_con) { - s_con = nm_setting_connection_new(); - nm_connection_add_setting(connection, s_con); - } - - g_object_set(s_con, - NM_SETTING_CONNECTION_TYPE, - type, - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_ID, - id, - NM_SETTING_CONNECTION_INTERFACE_NAME, - NULL, - NULL); - - g_free(uuid); - g_free(id); - - return TRUE; -} - -static gboolean -is_ibft_vlan_device(GHashTable *nic) -{ - const char *s_vlan_id; - - g_assert(nic); - - s_vlan_id = (const char *) g_hash_table_lookup(nic, "vlan"); - - if (s_vlan_id) { - /* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it - * means "no VLAN". - */ - if (_nm_utils_ascii_str_to_int64(s_vlan_id, 10, 1, 4095, -1) != -1) - return TRUE; - } - - return FALSE; -} - -static gboolean -vlan_setting_add_from_block(GHashTable *nic, NMConnection *connection, GError **error) -{ - NMSetting * s_vlan = NULL; - const char *vlan_id_str = NULL; - gint64 vlan_id = -1; - - g_assert(nic); - g_assert(connection); - - /* This won't fail since this function shouldn't be called unless the - * iBFT VLAN ID exists and is > 0. - */ - vlan_id_str = (const char *) g_hash_table_lookup(nic, "vlan"); - g_assert(vlan_id_str); - - /* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it means "no VLAN" */ - vlan_id = _nm_utils_ascii_str_to_int64(vlan_id_str, 10, 1, 4095, -1); - if (vlan_id == -1) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid VLAN_ID '%s'", - vlan_id_str); - return FALSE; - } - - s_vlan = (NMSetting *) nm_connection_get_setting_vlan(connection); - if (!s_vlan) { - s_vlan = nm_setting_vlan_new(); - nm_connection_add_setting(connection, s_vlan); - } - - g_object_set(s_vlan, NM_SETTING_VLAN_ID, (guint32) vlan_id, NULL); - - return TRUE; -} - -static gboolean -wired_setting_add_from_block(GHashTable *nic, NMConnection *connection, GError **error) -{ - NMSetting * s_wired = NULL; - const char *hwaddr = NULL; - - g_assert(nic); - g_assert(connection); - - hwaddr = (const char *) g_hash_table_lookup(nic, "mac"); - if (!hwaddr) { - g_set_error_literal(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: missing MAC address"); - return FALSE; - } - - if (!nm_utils_hwaddr_valid(hwaddr, ETH_ALEN)) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "iBFT: invalid MAC address '%s'.", - hwaddr); - return FALSE; - } - - s_wired = (NMSetting *) nm_connection_get_setting_wired(connection); - if (!s_wired) { - s_wired = nm_setting_wired_new(); - nm_connection_add_setting(connection, s_wired); - } - - g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, hwaddr, NULL); - - return TRUE; -} - -gboolean -nmi_ibft_update_connection_from_nic(NMConnection *connection, GHashTable *nic, GError **error) -{ - gboolean is_vlan = FALSE; - - g_assert(nic); - - is_vlan = is_ibft_vlan_device(nic); - if (is_vlan && !vlan_setting_add_from_block(nic, connection, error)) - return FALSE; - - /* Always have a wired setting; for VLAN it defines the parent */ - if (!wired_setting_add_from_block(nic, connection, error)) - return FALSE; - - if (!ip_setting_add_from_block(nic, connection, error)) - return FALSE; - - if (!connection_setting_add(nic, - connection, - is_vlan ? NM_SETTING_VLAN_SETTING_NAME - : NM_SETTING_WIRED_SETTING_NAME, - is_vlan ? "VLAN" : NULL, - error)) - return FALSE; - - if (!nm_connection_normalize(connection, NULL, NULL, error)) - return FALSE; - - return TRUE; -} diff --git a/src/core/initrd/tests/meson.build b/src/core/initrd/tests/meson.build deleted file mode 100644 index e47ff790..00000000 --- a/src/core/initrd/tests/meson.build +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -test_units = [ - 'test-dt-reader', - 'test-ibft-reader', - 'test-cmdline-reader', -] - -foreach test_unit : test_units - exe = executable( - test_unit, - test_unit + '.c', - dependencies: libNetworkManagerTest_dep, - c_args: test_c_flags, - link_with: libnmi_core, - ) - - test( - 'initrd/' + test_unit, - test_script, - timeout: default_test_timeout, - args: test_args + [exe.full_path()], - ) -endforeach diff --git a/src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway deleted file mode 100644 index bf6cf454..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -192.168.35.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index 944c8d45..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.168.32.72 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index 8fdd954d..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -22 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index 2303dbdc..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10000.500.250.1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 7cb9d0a9..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.252.0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 509a7ab8..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.pjones6 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name deleted file mode 100644 index 32c9450a..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.0.2008-11.com.blahblah:iscsi0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway deleted file mode 100644 index bf6cf454..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -192.168.35.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index 944c8d45..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.168.32.72 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index 8fdd954d..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -22 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 5ed7b719..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -blah.foo.bar.baz \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 7cb9d0a9..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.252.0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 509a7ab8..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.pjones6 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name deleted file mode 100644 index 32c9450a..00000000 --- a/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.0.2008-11.com.blahblah:iscsi0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway deleted file mode 100644 index 1970856e..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -bb.cc.dd.ee \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index 944c8d45..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.168.32.72 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index 8fdd954d..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -22 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 7cb9d0a9..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.252.0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 509a7ab8..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.pjones6 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name deleted file mode 100644 index 32c9450a..00000000 --- a/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.0.2008-11.com.blahblah:iscsi0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway deleted file mode 100644 index bf6cf454..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -192.168.35.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index d526f324..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -aa.bb.cc.dd \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index 8fdd954d..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -22 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 7cb9d0a9..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.252.0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 509a7ab8..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.pjones6 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name deleted file mode 100644 index 32c9450a..00000000 --- a/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.0.2008-11.com.blahblah:iscsi0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address b/src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address b/src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address deleted file mode 100644 index befa7850..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway deleted file mode 100644 index 59ea5b82..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -10.16.52.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin deleted file mode 100644 index e440e5c8..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway deleted file mode 100644 index 59ea5b82..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway +++ /dev/null @@ -1 +0,0 @@ -10.16.52.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac deleted file mode 100644 index befa7850..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin deleted file mode 100644 index e440e5c8..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 509a7ab8..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.pjones6 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name deleted file mode 100644 index 32c9450a..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.0.2008-11.com.blahblah:iscsi0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name deleted file mode 100644 index ac3a6a2a..00000000 --- a/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.1.2008-11.com.blahblah:iscsi1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath b/src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath deleted file mode 100644 index 6f069ae0..00000000 Binary files a/src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request deleted file mode 100644 index 034d423e..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response deleted file mode 100644 index 25982d6f..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath deleted file mode 100644 index db880702..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip deleted file mode 100644 index 7bde8641..00000000 --- a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip +++ /dev/null @@ -1 +0,0 @@ -ÿÿÿÿ \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip deleted file mode 100644 index f108ba9b..00000000 --- a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip +++ /dev/null @@ -1,2 +0,0 @@ - -+ \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name deleted file mode 100644 index fe0f76b8..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name deleted file mode 100644 index b34f9f96..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip deleted file mode 100644 index f0361835..00000000 --- a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip +++ /dev/null @@ -1,2 +0,0 @@ - -+þ \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name deleted file mode 100644 index f3e58052..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip deleted file mode 100644 index d441cd83..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path deleted file mode 100644 index f76dd238..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip deleted file mode 100644 index a2a4b2e8..00000000 --- a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip +++ /dev/null @@ -1,2 +0,0 @@ - -& \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file deleted file mode 100644 index c0e0e330..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options deleted file mode 100644 index f76dd238..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type deleted file mode 100644 index df3c9d9f..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address deleted file mode 100644 index c983e752..00000000 --- a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address +++ /dev/null @@ -1 +0,0 @@ -¬>åØ \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address deleted file mode 100644 index c983e752..00000000 --- a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address +++ /dev/null @@ -1 +0,0 @@ -¬>åØ \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name deleted file mode 100644 index 88eaddfe..00000000 Binary files a/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name and /dev/null differ diff --git a/src/core/initrd/tests/sysfs-static/class/net/eth0/address b/src/core/initrd/tests/sysfs-static/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-static/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/class/net/eth1/address b/src/core/initrd/tests/sysfs-static/class/net/eth1/address deleted file mode 100644 index befa7850..00000000 --- a/src/core/initrd/tests/sysfs-static/class/net/eth1/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway deleted file mode 100644 index bf6cf454..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -192.168.35.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index 944c8d45..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.168.32.72 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index 8fdd954d..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -22 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 7cb9d0a9..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.252.0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway deleted file mode 100644 index 59ea5b82..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway +++ /dev/null @@ -1 +0,0 @@ -10.16.52.254 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac deleted file mode 100644 index befa7850..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin deleted file mode 100644 index e440e5c8..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns deleted file mode 100644 index 2e152cb0..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.2 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns deleted file mode 100644 index 2eb9e1d0..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -10.16.255.3 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 509a7ab8..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.pjones6 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name deleted file mode 100644 index 32c9450a..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.0.2008-11.com.blahblah:iscsi0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr deleted file mode 100644 index 7450fdf9..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr +++ /dev/null @@ -1 +0,0 @@ -10.16.52.16 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun deleted file mode 100644 index c43d0930..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun +++ /dev/null @@ -1 +0,0 @@ -00000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name deleted file mode 100644 index ac3a6a2a..00000000 --- a/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.1.2008-11.com.blahblah:iscsi1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/class/net/eth0/address b/src/core/initrd/tests/sysfs-vlan/class/net/eth0/address deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-vlan/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index 4923230c..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.168.6.200 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac deleted file mode 100644 index 20659db7..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:33:21:98:b9:f0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin deleted file mode 100644 index 56a6051c..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index cabf43b5..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -24 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 5a279b41..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.255.0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan deleted file mode 100644 index d800886d..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -123 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 8e9cd2c4..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.2010-04.org.ipxe:d05faa97-c4be-44f6-a723-efde9aa399a0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index deleted file mode 100644 index c2270834..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr deleted file mode 100644 index a32ce01b..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.168.6.32 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun deleted file mode 100644 index f309ca6a..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -01000000 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port deleted file mode 100644 index 58f0d919..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name deleted file mode 100644 index f0e61157..00000000 --- a/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.2003-01.org.x:disk1 \ No newline at end of file diff --git a/src/core/initrd/tests/sysfs/class/net/eth0/address b/src/core/initrd/tests/sysfs/class/net/eth0/address deleted file mode 100644 index 1f2f610e..00000000 --- a/src/core/initrd/tests/sysfs/class/net/eth0/address +++ /dev/null @@ -1 +0,0 @@ -00:53:00:AB:00:01 diff --git a/src/core/initrd/tests/sysfs/class/net/eth2/address b/src/core/initrd/tests/sysfs/class/net/eth2/address deleted file mode 100644 index 6ec1078a..00000000 --- a/src/core/initrd/tests/sysfs/class/net/eth2/address +++ /dev/null @@ -1 +0,0 @@ -00:53:06:66:ab:01 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id deleted file mode 100644 index 590d9cd2..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id +++ /dev/null @@ -1 +0,0 @@ -NMTst diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id deleted file mode 100644 index 35d4d09c..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id +++ /dev/null @@ -1 +0,0 @@ -Whatevs diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature deleted file mode 100644 index e3a5d7ef..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature +++ /dev/null @@ -1 +0,0 @@ -IBFT diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp deleted file mode 100644 index 98a0d797..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:0002 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags deleted file mode 100644 index 00750edc..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway deleted file mode 100644 index 7f378f8f..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:0001 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname deleted file mode 100644 index 3ed5163c..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname +++ /dev/null @@ -1 +0,0 @@ -host0.example.com diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr deleted file mode 100644 index 98a0d797..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:0002 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac deleted file mode 100644 index f2441319..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac +++ /dev/null @@ -1 +0,0 @@ -00:53:00:ab:00:01 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin deleted file mode 100644 index b8626c4c..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len deleted file mode 100644 index 900731ff..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len +++ /dev/null @@ -1 +0,0 @@ -64 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns deleted file mode 100644 index e7511d5a..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:0053 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns deleted file mode 100644 index 1f6c5c95..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:5353 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask deleted file mode 100644 index 5df93454..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.255.255 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan deleted file mode 100644 index 7cc86ad1..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan +++ /dev/null @@ -1 +0,0 @@ -666 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp deleted file mode 100644 index 61ef5585..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp +++ /dev/null @@ -1 +0,0 @@ -192.0.2.2 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags deleted file mode 100644 index 00750edc..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway deleted file mode 100644 index 2096f194..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway +++ /dev/null @@ -1 +0,0 @@ -192.0.2.1 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname deleted file mode 100644 index 5dc539d5..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname +++ /dev/null @@ -1 +0,0 @@ -host2.example.com diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index deleted file mode 100644 index 0cfbf088..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr deleted file mode 100644 index 61ef5585..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr +++ /dev/null @@ -1 +0,0 @@ -192.0.2.2 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac deleted file mode 100644 index 2fc3d525..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac +++ /dev/null @@ -1 +0,0 @@ -00:53:06:66:AB:01 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin deleted file mode 100644 index 00750edc..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len deleted file mode 100644 index a45fd52c..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len +++ /dev/null @@ -1 +0,0 @@ -24 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns deleted file mode 100644 index 6fa8c742..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns +++ /dev/null @@ -1 +0,0 @@ -192.0.2.53 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns deleted file mode 100644 index a7269ff5..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns +++ /dev/null @@ -1 +0,0 @@ -192.0.2.54 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask deleted file mode 100644 index d30f9e9f..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask +++ /dev/null @@ -1 +0,0 @@ -255.255.255.0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags deleted file mode 100644 index 00750edc..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/index b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/index deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/index +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name deleted file mode 100644 index 337b5a0f..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name +++ /dev/null @@ -1 +0,0 @@ -iqn.1994-05.com.example.initiator:48b055856417 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server deleted file mode 100644 index 4aff9398..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:3205 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server deleted file mode 100644 index a26fb649..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:1812 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server deleted file mode 100644 index 908be27f..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server +++ /dev/null @@ -1 +0,0 @@ -192.0.2.181 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server deleted file mode 100644 index fca9e24b..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:0427 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type b/src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/flags b/src/core/initrd/tests/sysfs/firmware/ibft/target0/flags deleted file mode 100644 index 00750edc..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/flags +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs/firmware/ibft/target0/index deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/index +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr deleted file mode 100644 index 994b6e9c..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0000:3260 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs/firmware/ibft/target0/lun deleted file mode 100644 index 7c295bd4..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/lun +++ /dev/null @@ -1 +0,0 @@ -01000000 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc b/src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs/firmware/ibft/target0/port deleted file mode 100644 index 53f0295f..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target0/port +++ /dev/null @@ -1 +0,0 @@ -3260 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type b/src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type deleted file mode 100644 index 573541ac..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/flags b/src/core/initrd/tests/sysfs/firmware/ibft/target2/flags deleted file mode 100644 index 00750edc..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/flags +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/index b/src/core/initrd/tests/sysfs/firmware/ibft/target2/index deleted file mode 100644 index 0cfbf088..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/index +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr deleted file mode 100644 index a210477e..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr +++ /dev/null @@ -1 +0,0 @@ -2001:0db8:0000:0000:0000:0000:0002:3260 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/lun b/src/core/initrd/tests/sysfs/firmware/ibft/target2/lun deleted file mode 100644 index 7c295bd4..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/lun +++ /dev/null @@ -1 +0,0 @@ -01000000 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc b/src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc deleted file mode 100644 index 0cfbf088..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/port b/src/core/initrd/tests/sysfs/firmware/ibft/target2/port deleted file mode 100644 index 53f0295f..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/port +++ /dev/null @@ -1 +0,0 @@ -3260 diff --git a/src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name b/src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name deleted file mode 100644 index f4094320..00000000 --- a/src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name +++ /dev/null @@ -1 +0,0 @@ -iqn.1994-05.com.example.target:48b055851337 diff --git a/src/core/initrd/tests/test-cmdline-reader.c b/src/core/initrd/tests/test-cmdline-reader.c deleted file mode 100644 index e3a3753e..00000000 --- a/src/core/initrd/tests/test-cmdline-reader.c +++ /dev/null @@ -1,2247 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include -#include -#include -#include -#include -#include - -#include "nm-core-internal.h" -#include "NetworkManagerUtils.h" - -#include "../nm-initrd-generator.h" - -#include "nm-test-utils-core.h" - -#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/core/initrd/tests" - -/*****************************************************************************/ - -#define _parse(ARGV, out_hostname, out_carrier_timeout_sec) \ - ({ \ - const char *const *const _ARGV = (ARGV); \ - char **const _out_hostname = (out_hostname); \ - gint64 *const _out_carrier_timeout_sec = (out_carrier_timeout_sec); \ - GHashTable * _connections; \ - \ - _connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", \ - _ARGV, \ - _out_hostname, \ - _out_carrier_timeout_sec); \ - \ - g_assert(_connections); \ - \ - _connections; \ - }) - -#define _parse_cons(ARGV) \ - ({ \ - GHashTable * _con_connections; \ - gs_free char *_con_hostname = NULL; \ - gint64 _con_carrier_timeout_sec = 0; \ - \ - _con_connections = _parse((ARGV), \ - nmtst_get_rand_bool() ? &_con_hostname : NULL, \ - nmtst_get_rand_bool() ? &_con_carrier_timeout_sec : NULL); \ - g_assert_cmpstr(_con_hostname, ==, NULL); \ - g_assert_cmpint(_con_carrier_timeout_sec, ==, 0); \ - \ - _con_connections; \ - }) - -#define _parse_con(ARGV, connection_name) \ - ({ \ - gs_unref_hashtable GHashTable *_1_connections = NULL; \ - NMConnection * _1_connection; \ - const char *const _1_connection_name = (connection_name); \ - \ - g_assert(_1_connection_name); \ - \ - _1_connections = _parse_cons((ARGV)); \ - \ - g_assert_cmpint(g_hash_table_size(_1_connections), ==, 1); \ - \ - _1_connection = g_hash_table_lookup(_1_connections, _1_connection_name); \ - g_assert(NM_IS_CONNECTION(_1_connection)); \ - \ - nmtst_assert_connection_verifies_without_normalization(_1_connection); \ - \ - NM_CONNECTION(g_object_ref(_1_connection)); \ - }) - -/*****************************************************************************/ - -static void -test_auto(void) -{ - const char *const *ARGV = NM_MAKE_STRV("ip=auto"); - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV, "default_connection"); - - g_assert(!nm_connection_get_setting_vlan(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "Wired Connection"); - g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - - g_assert(nm_setting_connection_get_autoconnect(s_con)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); -} - -static void -test_dhcp_with_hostname(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=::::host1::dhcp"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, "host1"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "default_connection"); - - nmtst_assert_connection_verifies_without_normalization(connection); - - g_assert(!nm_connection_get_setting_vlan(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "Wired Connection"); - g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - - g_assert(nm_setting_connection_get_autoconnect(s_con)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); -} - -static void -test_dhcp_with_mtu(void) -{ - const char *const *ARGV0 = NM_MAKE_STRV("ip=:dhcp:1499"); - const char *const *ARGV1 = NM_MAKE_STRV("ip=::::::dhcp:1499"); - const char *const *ARGV[] = {ARGV0, ARGV1}; - guint i; - - for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV[i], "default_connection"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "Wired Connection"); - g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - - g_assert(nm_setting_connection_get_autoconnect(s_con)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1499); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - } -} - -static void -test_dhcp_timeout(void) -{ - struct { - const char *const *cmdline; - int timeout; - } data[] = { - {NM_MAKE_STRV("ip=dhcp"), 90}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=0"), 90}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=foobar"), 90}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=42"), 42}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.dhcp.retry=2"), 180}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.dhcp.retry=3", "rd.net.timeout.dhcp=40"), 120}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=infinity"), G_MAXINT32}, - {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=infinity", "rd.net.dhcp.retry=100"), - G_MAXINT32}, - }; - guint i; - - for (i = 0; i < G_N_ELEMENTS(data); i++) { - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(data[i].cmdline, "default_connection"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "Wired Connection"); - g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE); - 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)); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, data[i].timeout); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip6), ==, data[i].timeout); - } -} - -static void -test_if_auto_with_mtu(void) -{ - const char *const *ARGV = NM_MAKE_STRV("ip=eth0:auto:1666"); - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV, "eth0"); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_autoconnect_retries(s_con), ==, 1); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1666); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, 90); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); -} - -static void -test_if_dhcp6(void) -{ - const char *const *ARGV = NM_MAKE_STRV("ip=eth1:dhcp6"); - gs_unref_object NMConnection *connection = NULL; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV, "eth1"); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); -} - -static void -test_if_auto_with_mtu_and_mac(void) -{ - const char *const *ARGV = NM_MAKE_STRV("ip=eth2:auto6:2048:00:53:ef:12:34:56"); - gs_unref_object NMConnection *connection = NULL; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV, "eth2"); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth2"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 2048); - g_assert_cmpstr(nm_setting_wired_get_cloned_mac_address(s_wired), ==, "00:53:EF:12:34:56"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); -} - -static void -test_if_ip4_manual(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=192.0.2.2::192.0.2.1:255.255.255.0:" - "hostname0.example.com:eth3:none:192.0.2.53", - "ip=203.0.113.2::203.0.113.1:26:" - "hostname1.example.com:eth4"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMIPAddress * ip_addr; - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, "hostname1.example.com"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "eth3"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth3"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "192.0.2.53"); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "192.0.2.2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 24); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.0.2.1"); - g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip4), ==, "hostname0.example.com"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); - - connection = g_hash_table_lookup(connections, "eth4"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth4"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "203.0.113.2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 26); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "203.0.113.1"); - g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip4), ==, "hostname1.example.com"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); -} - -static void -test_if_ip4_manual_no_dev(void) -{ - const char *const * ARGV = NM_MAKE_STRV("ip=192.0.2.2::192.0.2.1:24:::"); - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMIPAddress * ip_addr; - - connection = _parse_con(ARGV, "default_connection"); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "192.0.2.2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 24); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.0.2.1"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); -} - -static void -test_if_ip6_manual(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=[2001:0db8::02]/64::[2001:0db8::01]::" - "hostname0.example.com:eth4::[2001:0db8::53]"); - NMConnection * connection; - NMSettingIPConfig * s_ip6; - NMIPAddress * ip_addr; - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, "hostname0.example.com"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "eth4"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth4"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 0), ==, "2001:db8::53"); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip6, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "2001:db8::2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 64); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "2001:db8::1"); - g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, "hostname0.example.com"); -} - -static void -test_if_off(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=off", - "ip=ens3:off", - "ip=10.0.0.8:::::ens4:off", - "ip=[2001:DB8::8]:::::ens5:off"); - NMConnection * connection; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - struct { - const char name[32]; - const char ipv4_method[32]; - const char ipv6_method[32]; - - } conn_expected[] = { - {"default_connection", - NM_SETTING_IP4_CONFIG_METHOD_DISABLED, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED}, - {"ens3", NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NM_SETTING_IP6_CONFIG_METHOD_DISABLED}, - {"ens4", NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NM_SETTING_IP6_CONFIG_METHOD_DISABLED}, - {"ens5", NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NM_SETTING_IP6_CONFIG_METHOD_MANUAL}, - }; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, G_N_ELEMENTS(conn_expected)); - - for (int i = 0; i < G_N_ELEMENTS(conn_expected); ++i) { - connection = g_hash_table_lookup(connections, conn_expected[i].name); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, conn_expected[i].ipv4_method); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, conn_expected[i].ipv6_method); - } -} - -static void -test_if_mac_ifname(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=[2001:0db8::42]/64::[2001:0db8::01]::" - "hostname0:00-11-22-33-44-55::[2001:0db8::53]"); - NMConnection * connection; - NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; - NMIPAddress * ip_addr; - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, "hostname0"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "00:11:22:33:44:55"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "00:11:22:33:44:55"); - g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert_cmpstr(nm_setting_wired_get_mac_address(s_wired), ==, "00:11:22:33:44:55"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 0), ==, "2001:db8::53"); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip6, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "2001:db8::42"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 64); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "2001:db8::1"); - g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, "hostname0"); -} - -static void -test_multiple_merge(void) -{ - const char *const *ARGV = - NM_MAKE_STRV("ip=192.0.2.2/16:::::eth0", "ip=[2001:db8::2]:::56::eth0"); - gs_unref_object NMConnection *connection = NULL; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMIPAddress * ip_addr; - - connection = _parse_con(ARGV, "eth0"); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "192.0.2.2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 16); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_MANUAL); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip6, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "2001:db8::2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 56); -} - -static void -test_multiple_bootdev(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - - const char *const *ARGV = NM_MAKE_STRV("nameserver=1.2.3.4", - "ip=eth3:auto6", - "ip=eth4:dhcp", - "ip=eth5:link6", - "bootdev=eth4"); - - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - - connection = g_hash_table_lookup(connections, "eth3"); - g_assert(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - - connection = g_hash_table_lookup(connections, "eth4"); - g_assert(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), - ==, - NMI_WAIT_DEVICE_TIMEOUT_MS); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "1.2.3.4"); - - connection = g_hash_table_lookup(connections, "eth5"); - g_assert(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL); -} - -static void -test_bootdev(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("vlan=vlan2:ens5", "bootdev=ens3"); - NMConnection * connection; - NMSettingConnection * s_con; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - - connection = g_hash_table_lookup(connections, "ens3"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "ens3"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "ens3"); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), - ==, - NMI_WAIT_DEVICE_TIMEOUT_MS); - - connection = g_hash_table_lookup(connections, "vlan2"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_VLAN_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "vlan2"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "vlan2"); - - connection = g_hash_table_lookup(connections, "ens5"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "ens5"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "ens5"); -} - -static void -test_some_more(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("bootdev=eth1", - "hail", - "nameserver=[2001:DB8:3::53]", - "satan", - "nameserver=192.0.2.53", - "worship", - "doom", - "rd.peerdns=0", - "rd.route=[2001:DB8:3::/48]:[2001:DB8:2::1]:ens10"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMIPRoute * ip_route; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - connection = g_hash_table_lookup(connections, "eth1"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth1"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eth1"); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "192.0.2.53"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 1); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 0), ==, "2001:db8:3::53"); - - connection = g_hash_table_lookup(connections, "ens10"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "ens10"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "ens10"); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 0), ==, "2001:db8:3::53"); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 1); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - ip_route = nm_setting_ip_config_get_route(s_ip6, 0); - g_assert_cmpstr(nm_ip_route_get_dest(ip_route), ==, "2001:db8:3::"); - g_assert_cmpint(nm_ip_route_get_family(ip_route), ==, AF_INET6); - g_assert_cmpint(nm_ip_route_get_metric(ip_route), ==, -1); - g_assert_cmpstr(nm_ip_route_get_next_hop(ip_route), ==, "2001:db8:2::1"); - g_assert_cmpint(nm_ip_route_get_prefix(ip_route), ==, 48); -} - -static void -test_bond(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("rd.route=192.0.2.53::bong0", - "bond=bong0:eth0,eth1:mode=balance-rr:9000", - "nameserver=203.0.113.53"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingBond * s_bond; - NMSettingWired * s_wired; - NMIPRoute * ip_route; - const char * master_uuid; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - - connection = g_hash_table_lookup(connections, "bong0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bong0"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 9000); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "203.0.113.53"); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 1); - ip_route = nm_setting_ip_config_get_route(s_ip4, 0); - g_assert_cmpstr(nm_ip_route_get_dest(ip_route), ==, "192.0.2.53"); - g_assert_cmpint(nm_ip_route_get_family(ip_route), ==, AF_INET); - g_assert_cmpint(nm_ip_route_get_metric(ip_route), ==, -1); - g_assert(!nm_ip_route_get_next_hop(ip_route)); - g_assert_cmpint(nm_ip_route_get_prefix(ip_route), ==, 32); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - - s_bond = nm_connection_get_setting_bond(connection); - g_assert(s_bond); - g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 1); - g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "mode"), ==, "balance-rr"); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - connection = g_hash_table_lookup(connections, "eth1"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth1"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); -} - -static void -test_bond_ip(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = - NM_MAKE_STRV("bond=bond0:eth0,eth1", - "ip=192.168.1.1::192.168.1.254:24::bond0:none:1480:01:02:03:04:05:06", - "nameserver=4.8.15.16"); - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; - NMSettingBond * s_bond; - NMIPAddress * ip_addr; - const char * master_uuid; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - - connection = g_hash_table_lookup(connections, "bond0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bond0"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1480); - g_assert_cmpstr(nm_setting_wired_get_cloned_mac_address(s_wired), ==, "01:02:03:04:05:06"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "192.168.1.1"); - g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 24); - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.254"); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "4.8.15.16"); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - - s_bond = nm_connection_get_setting_bond(connection); - g_assert(s_bond); - g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 1); - g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "mode"), ==, "balance-rr"); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - connection = g_hash_table_lookup(connections, "eth1"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth1"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); -} - -static void -test_bond_default(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("bond"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingBond * s_bond; - const char * master_uuid; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - connection = g_hash_table_lookup(connections, "bond0"); - - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bond0"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - - s_bond = nm_connection_get_setting_bond(connection); - g_assert(s_bond); - g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 1); - g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "mode"), ==, "balance-rr"); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); -} - -static void -test_bridge(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("bridge=bridge0:eth0,eth1", - "rd.route=192.0.2.53::bridge0", - "rd.net.timeout.dhcp=10"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingBridge * s_bridge; - NMIPRoute * ip_route; - const char * master_uuid; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - - connection = g_hash_table_lookup(connections, "bridge0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bridge0"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 1); - g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, 10); - ip_route = nm_setting_ip_config_get_route(s_ip4, 0); - g_assert_cmpstr(nm_ip_route_get_dest(ip_route), ==, "192.0.2.53"); - g_assert_cmpint(nm_ip_route_get_family(ip_route), ==, AF_INET); - g_assert_cmpint(nm_ip_route_get_metric(ip_route), ==, -1); - g_assert(!nm_ip_route_get_next_hop(ip_route)); - g_assert_cmpint(nm_ip_route_get_prefix(ip_route), ==, 32); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip6), ==, 10); - - s_bridge = nm_connection_get_setting_bridge(connection); - g_assert(s_bridge); - g_assert_cmpint(nm_setting_bridge_get_stp(s_bridge), ==, FALSE); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - connection = g_hash_table_lookup(connections, "eth1"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth1"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); -} - -static void -test_bridge_default(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("bridge"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingBridge * s_bridge; - const char * master_uuid; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - connection = g_hash_table_lookup(connections, "br0"); - - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "br0"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - - s_bridge = nm_connection_get_setting_bridge(connection); - g_assert(s_bridge); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); -} - -static void -test_bridge_ip(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = - NM_MAKE_STRV("ip=bridge123:auto:1280:00:11:22:33:CA:fe", - "bridge=bridge123:eth0,eth1,eth2,eth3,eth4,eth5,eth6,eth7,eth8,eth9"); - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; - NMSettingBridge * s_bridge; - const char * master_uuid; - guint i; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 11); - - connection = g_hash_table_lookup(connections, "bridge123"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bridge123"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1280); - g_assert_cmpstr(nm_setting_wired_get_cloned_mac_address(s_wired), ==, "00:11:22:33:CA:FE"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - - s_bridge = nm_connection_get_setting_bridge(connection); - g_assert(s_bridge); - - for (i = 0; i < 10; i++) { - char ifname[16]; - - nm_sprintf_buf(ifname, "eth%u", i); - - connection = g_hash_table_lookup(connections, ifname); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, ifname); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, ifname); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), - ==, - NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - } -} - -static void -test_team(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("team=team0:eth0,eth1", "ip=team0:dhcp6"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingTeam * s_team; - const char * master_uuid; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - - connection = g_hash_table_lookup(connections, "team0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_TEAM_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "team0"); - master_uuid = nm_connection_get_uuid(connection); - g_assert(master_uuid); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip4)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 0); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0); - g_assert(!nm_setting_ip_config_get_gateway(s_ip6)); - g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0); - - s_team = nm_connection_get_setting_team(connection); - g_assert(s_team); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_TEAM_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); - - connection = g_hash_table_lookup(connections, "eth1"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth1"); - g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_TEAM_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, master_uuid); - g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con), - ==, - NM_CONNECTION_MULTI_CONNECT_SINGLE); -} - -static void -test_vlan(void) -{ - const char *const *ARGV0 = NM_MAKE_STRV("ip=eth0.100:dhcp", "vlan=eth0.100:eth0"); - const char *const *ARGV1 = NM_MAKE_STRV("vlan=eth0.100:eth0", "ip=eth0.100:dhcp"); - const char *const *ARGV[] = {ARGV0, ARGV1}; - guint i; - - for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_hashtable GHashTable *connections = NULL; - NMConnection * connection; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingVlan * s_vlan; - - connections = _parse_cons(ARGV[i]); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - /* VLAN eth0.100 */ - connection = g_hash_table_lookup(connections, "eth0.100"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_VLAN_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0.100"); - - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); - g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); - g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 100); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - - /* Ethernet eth0 */ - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - } -} - -static void -test_vlan_with_dhcp_on_parent(void) -{ - const char *const *ARGV0 = NM_MAKE_STRV("vlan=eth0.100:eth0", "ip=eth0:dhcp"); - const char *const *ARGV1 = NM_MAKE_STRV("ip=eth0:dhcp", "vlan=eth0.100:eth0"); - const char *const *ARGV[] = {ARGV0, ARGV1}; - guint i; - - for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_hashtable GHashTable *connections = NULL; - NMConnection * connection; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingVlan * s_vlan; - - connections = _parse_cons(ARGV[i]); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - /* VLAN eth0.100 */ - connection = g_hash_table_lookup(connections, "eth0.100"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_VLAN_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0.100"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); - g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); - g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 100); - - /* Ethernet eth0 */ - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - } -} - -static void -test_vlan_over_bond(void) -{ - const char *const *ARGV0 = NM_MAKE_STRV("ip=1.2.3.4:::24::vlan1:none", - "bond=bond2:ens3,ens4:mode=active-backup", - "vlan=vlan1:bond2"); - const char *const *ARGV1 = NM_MAKE_STRV("vlan=vlan1:bond2", - "ip=1.2.3.4:::24::vlan1:none", - "bond=bond2:ens3,ens4:mode=active-backup"); - const char *const *ARGV2 = NM_MAKE_STRV("bond=bond2:ens3,ens4:mode=active-backup", - "ip=1.2.3.4:::24::vlan1:none", - "vlan=vlan1:bond2"); - const char *const *ARGV[] = {ARGV0, ARGV1, ARGV2}; - guint i; - - for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_hashtable GHashTable *connections = NULL; - NMConnection * connection; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMSettingVlan * s_vlan; - - connections = _parse_cons(ARGV[i]); - g_assert_cmpint(g_hash_table_size(connections), ==, 4); - - /* VLAN vlan1 */ - connection = g_hash_table_lookup(connections, "vlan1"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_VLAN_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "vlan1"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); - g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "bond2"); - g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 1); - - /* Bond bond2 */ - connection = g_hash_table_lookup(connections, "bond2"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_BOND_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "bond2"); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - - /* Ethernet ens3 and ens4 */ - connection = g_hash_table_lookup(connections, "ens3"); - g_assert(connection); - connection = g_hash_table_lookup(connections, "ens4"); - g_assert(connection); - } -} - -static void -test_ibft_ip_dev(void) -{ - const char *const * ARGV = NM_MAKE_STRV("ip=eth0:ibft"); - NMSettingConnection *s_con; - gs_unref_object NMConnection *connection = NULL; - - connection = _parse_con(ARGV, "eth0"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_VLAN_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL); -} - -static void -test_ibft_ip_dev_mac(void) -{ - const char *const * ARGV = NM_MAKE_STRV("ip=00-53-06-66-ab-01:ibft"); - NMSettingConnection *s_con; - gs_unref_object NMConnection *connection = NULL; - - connection = _parse_con(ARGV, "00:53:06:66:AB:01"); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL); -} - -static void -_test_ibft_ip(const char *const *ARGV) -{ - gs_unref_hashtable GHashTable *connections = NULL; - NMConnection * connection; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - connection = g_hash_table_lookup(connections, "ibft0"); - nmtst_assert_connection_verifies_without_normalization(connection); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "iBFT VLAN Connection 0"); - g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); - - connection = g_hash_table_lookup(connections, "ibft2"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "iBFT Connection 2"); - g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); -} - -static void -test_ibft_ip(void) -{ - const char *const *ARGV = NM_MAKE_STRV("ip=ibft"); - - _test_ibft_ip(ARGV); -} - -static void -test_ibft_rd_iscsi_ibft(void) -{ - const char *const *ARGV = NM_MAKE_STRV("rd.iscsi.ibft"); - - _test_ibft_ip(ARGV); -} - -static void -test_ignore_extra(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("blabla", "extra", "lalala"); - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); -} - -static void -test_rd_znet(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const *const ARGV = - NM_MAKE_STRV("ip=10.11.12.13::10.11.12.1:24:foo.example.com:enc800:none", - "ip=slc600:dhcp", - "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1", - "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - const char *const * v_subchannels; - const NMUtilsNamedValue s390_options[] = { - {.name = "layer2", .value_str = "0"}, - {.name = "portno", .value_str = "1"}, - }; - int i_s390_options_keys; - gs_free char *hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, "foo.example.com"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "enc800"); - g_assert(NM_IS_CONNECTION(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(NM_IS_SETTING_CONNECTION(s_con)); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "enc800"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "enc800"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(NM_IS_SETTING_WIRED(s_wired)); - - v_subchannels = nm_setting_wired_get_s390_subchannels(s_wired); - g_assert(v_subchannels); - g_assert_cmpstr(v_subchannels[0], ==, "0.0.0800"); - g_assert_cmpstr(v_subchannels[1], ==, "0.0.0801"); - g_assert_cmpstr(v_subchannels[2], ==, "0.0.0802"); - g_assert_cmpstr(v_subchannels[3], ==, NULL); - - g_assert_cmpint(nm_setting_wired_get_num_s390_options(s_wired), ==, G_N_ELEMENTS(s390_options)); - for (i_s390_options_keys = 0; i_s390_options_keys < G_N_ELEMENTS(s390_options); - i_s390_options_keys++) { - const NMUtilsNamedValue *s390_option = &s390_options[i_s390_options_keys]; - const char * k; - const char * v; - const char * v2; - - g_assert(s390_option->name); - g_assert(s390_option->value_str); - v = nm_setting_wired_get_s390_option_by_key(s_wired, s390_option->name); - g_assert(v); - g_assert_cmpstr(v, ==, s390_option->value_str); - - if (!nm_setting_wired_get_s390_option(s_wired, i_s390_options_keys, &k, &v2)) - g_assert_not_reached(); - g_assert_cmpstr(k, ==, s390_option->name); - g_assert(v == v2); - g_assert_cmpstr(v2, ==, s390_option->value_str); - } - - nmtst_assert_connection_verifies_without_normalization(connection); - - connection = g_hash_table_lookup(connections, "slc600"); - g_assert(NM_IS_CONNECTION(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(NM_IS_SETTING_CONNECTION(s_con)); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "slc600"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "slc600"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(NM_IS_SETTING_WIRED(s_wired)); - - v_subchannels = nm_setting_wired_get_s390_subchannels(s_wired); - g_assert(v_subchannels); - g_assert_cmpstr(v_subchannels[0], ==, "0.0.0600"); - g_assert_cmpstr(v_subchannels[1], ==, "0.0.0601"); - g_assert_cmpstr(v_subchannels[2], ==, NULL); - - nmtst_assert_connection_verifies_without_normalization(connection); -} - -static void -test_rd_znet_legacy(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const *const ARGV = - NM_MAKE_STRV("ip=10.11.12.13::10.11.12.1:24:foo.example.com:eth0:none", - "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1", - "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0", - "ip=ctc0:dhcp", - "net.ifnames=0"); - NMConnection * connection; - NMSettingConnection *s_con; - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, "foo.example.com"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "eth0"); - g_assert(NM_IS_CONNECTION(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(NM_IS_SETTING_CONNECTION(s_con)); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "eth0"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eth0"); - - nmtst_assert_connection_verifies_without_normalization(connection); - - connection = g_hash_table_lookup(connections, "ctc0"); - g_assert(NM_IS_CONNECTION(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(NM_IS_SETTING_CONNECTION(s_con)); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "ctc0"); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "ctc0"); - - nmtst_assert_connection_verifies_without_normalization(connection); -} - -static void -test_rd_znet_no_ip(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const *const ARGV = - NM_MAKE_STRV("rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1"); - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); -} - -static void -test_rd_znet_malformed(void) -{ - const char *const *const ARGV0 = NM_MAKE_STRV("rd.znet="); - const char *const *const ARGV1 = NM_MAKE_STRV("rd.znet=,"); - const char *const *const ARGV2 = NM_MAKE_STRV("rd.znet=foobar"); - const char *const *const ARGV3 = NM_MAKE_STRV("rd.znet=qeth,0.0.0800,,,layer2=0,portno=1"); - const char *const *const ARGV[] = {ARGV0, ARGV1, ARGV2, ARGV3}; - guint i; - - for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_hashtable GHashTable *connections = NULL; - - connections = _parse_cons(ARGV[i]); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - } -} - -static void -test_bootif_ip(void) -{ - const char *const *ARGV = NM_MAKE_STRV("BOOTIF=00:53:AB:cd:02:03", "ip=dhcp"); - gs_unref_object NMConnection *connection = NULL; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV, "default_connection"); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert_cmpstr(nm_setting_wired_get_mac_address(s_wired), ==, "00:53:AB:CD:02:03"); - g_assert(s_wired); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert(!nm_setting_ip_config_get_may_fail(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); -} - -static void -test_neednet(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("rd.neednet", - "ip=eno1:dhcp", - "ip=172.25.1.100::172.25.1.1:24::eno2", - "bridge=br0:eno3"); - NMConnection * connection; - NMSettingConnection * s_con; - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 4); - - connection = g_hash_table_lookup(connections, "eno1"); - nmtst_assert_connection_verifies_without_normalization(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eno1"); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), - ==, - NMI_WAIT_DEVICE_TIMEOUT_MS); - - connection = g_hash_table_lookup(connections, "eno2"); - nmtst_assert_connection_verifies_without_normalization(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eno2"); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), - ==, - NMI_WAIT_DEVICE_TIMEOUT_MS); - - connection = g_hash_table_lookup(connections, "eno3"); - nmtst_assert_connection_verifies_without_normalization(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eno3"); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), - ==, - NMI_WAIT_DEVICE_TIMEOUT_MS); - - connection = g_hash_table_lookup(connections, "br0"); - nmtst_assert_connection_verifies_without_normalization(connection); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "br0"); - g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); -} - -static void -test_bootif_no_ip(void) -{ - const char *const *ARGV = NM_MAKE_STRV("BOOTIF=00:53:AB:cd:02:03"); - gs_unref_object NMConnection *connection = NULL; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connection = _parse_con(ARGV, "default_connection"); - - g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert_cmpstr(nm_setting_wired_get_mac_address(s_wired), ==, "00:53:AB:CD:02:03"); - g_assert(s_wired); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(nm_setting_ip_config_get_may_fail(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); -} - -static void -test_bootif_hwtype(void) -{ - const char *const *ARGV0 = NM_MAKE_STRV("ip=eth0:dhcp", "BOOTIF=01-00-53-AB-cd-02-03"); - const char *const *ARGV1 = NM_MAKE_STRV("ip=eth0:dhcp", "BOOTIF=00-00-53-Ab-cD-02-03"); - const char *const *ARGV[] = {ARGV0, ARGV1}; - guint i; - - for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_hashtable GHashTable *connections = NULL; - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - - connections = _parse_cons(ARGV[i]); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - g_assert(s_wired); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert(!nm_setting_ip_config_get_may_fail(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - - connection = g_hash_table_lookup(connections, "bootif_connection"); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "BOOTIF Connection"); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert_cmpstr(nm_setting_wired_get_mac_address(s_wired), ==, "00:53:AB:CD:02:03"); - g_assert(s_wired); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert(nm_setting_ip_config_get_may_fail(s_ip4)); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); - } -} - -/* Check that nameservers are assigned to all existing - * connections that support the specific IPv4/IPv6 address - * family. - */ -static void -test_nameserver(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = - NM_MAKE_STRV("nameserver=1.1.1.1", - "ip=eth0:dhcp", - "ip=eth1:auto6", - "ip=10.11.12.13::10.11.12.1:24:foo.example.com:eth2:none", - "nameserver=1.0.0.1", - "nameserver=[2606:4700:4700::1111]"); - NMConnection * connection; - NMSettingIPConfig *s_ip; - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 3); - g_assert_cmpstr(hostname, ==, "foo.example.com"); - g_assert_cmpint(carrier_timeout_sec, ==, 0); - - connection = g_hash_table_lookup(connections, "eth0"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_ip = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip), ==, 2); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 0), ==, "1.1.1.1"); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 1), ==, "1.0.0.1"); - - connection = g_hash_table_lookup(connections, "eth1"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_ip = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip), ==, 1); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 0), ==, "2606:4700:4700::1111"); - - connection = g_hash_table_lookup(connections, "eth2"); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_ip = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip); - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip), ==, 2); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 0), ==, "1.1.1.1"); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 1), ==, "1.0.0.1"); -} - -static void -test_bootif_off(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const *ARGV = NM_MAKE_STRV("BOOTIF=01-00-53-AB-cd-02-03", "rd.bootif=0"); - - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); -} - -static void -test_dhcp_vendor_class_id(void) -{ - const char *const *ARGV; - gs_unref_object NMConnection *connection = NULL; - NMSettingIP4Config * s_ip4; - gs_free char * vci_long = NULL; - char vci_arg_long[512] = {0}; - - ARGV = NM_MAKE_STRV("rd.net.dhcp.vendor-class=testvci", "ip=eno1:dhcp"); - connection = _parse_con(ARGV, "eno1"); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); - g_assert_cmpstr(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4), ==, "testvci"); - - g_clear_object(&connection); - - ARGV = NM_MAKE_STRV("rd.net.dhcp.vendor-class", "ip=eno1:dhcp"); - connection = _parse_con(ARGV, "eno1"); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); - g_assert(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4) == NULL); - - g_clear_object(&connection); - - memset(vci_arg_long, 'A', 400); - vci_long = g_strdup_printf("rd.net.dhcp.vendor-class=%s", vci_arg_long); - ARGV = NM_MAKE_STRV(vci_long, "ip=eno1:dhcp"); - connection = _parse_con(ARGV, "eno1"); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); - g_assert(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4) == NULL); -} - -static void -test_infiniband_iface(void) -{ - const char *const *ARGV = NM_MAKE_STRV("ip=ib1:dhcp"); - gs_unref_object NMConnection *connection = NULL; - NMSettingInfiniband * s_ib; - - connection = _parse_con(ARGV, "ib1"); - - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_INFINIBAND_SETTING_NAME); - s_ib = nm_connection_get_setting_infiniband(connection); - g_assert(s_ib); -} - -static void -test_infiniband_mac(void) -{ - const char *const *ARGV = - NM_MAKE_STRV("ip=00-11-22-33-44-55-66-77-88-99-aa-bb-cc-dd-ee-ff-00-11-22-33:dhcp"); - gs_unref_object NMConnection *connection = NULL; - NMSettingInfiniband * s_ib; - - connection = _parse_con(ARGV, "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); - - g_assert_cmpstr(nm_connection_get_connection_type(connection), - ==, - NM_SETTING_INFINIBAND_SETTING_NAME); - g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); - s_ib = nm_connection_get_setting_infiniband(connection); - g_assert(s_ib); - g_assert_cmpstr(nm_setting_infiniband_get_mac_address(s_ib), - ==, - "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); -} - -static void -test_carrier_timeout(void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("rd.net.timeout.carrier=20"); - gs_free char * hostname = NULL; - gint64 carrier_timeout_sec = 0; - - connections = _parse(ARGV, &hostname, &carrier_timeout_sec); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_assert_cmpstr(hostname, ==, NULL); - g_assert_cmpint(carrier_timeout_sec, ==, 20); -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT"); - - g_test_add_func("/initrd/cmdline/auto", test_auto); - g_test_add_func("/initrd/cmdline/dhcp_with_hostname", test_dhcp_with_hostname); - g_test_add_func("/initrd/cmdline/dhcp_with_mtu", test_dhcp_with_mtu); - g_test_add_func("/initrd/cmdline/dhcp_timeout", test_dhcp_timeout); - g_test_add_func("/initrd/cmdline/if_auto_with_mtu", test_if_auto_with_mtu); - g_test_add_func("/initrd/cmdline/if_dhcp6", test_if_dhcp6); - g_test_add_func("/initrd/cmdline/if_auto_with_mtu_and_mac", test_if_auto_with_mtu_and_mac); - g_test_add_func("/initrd/cmdline/if_ip4_manual", test_if_ip4_manual); - g_test_add_func("/initrd/cmdline/if_ip4_manual_no_dev", test_if_ip4_manual_no_dev); - g_test_add_func("/initrd/cmdline/if_ip6_manual", test_if_ip6_manual); - g_test_add_func("/initrd/cmdline/if_mac_ifname", test_if_mac_ifname); - g_test_add_func("/initrd/cmdline/if_off", test_if_off); - g_test_add_func("/initrd/cmdline/multiple/merge", test_multiple_merge); - g_test_add_func("/initrd/cmdline/multiple/bootdev", test_multiple_bootdev); - g_test_add_func("/initrd/cmdline/nameserver", test_nameserver); - g_test_add_func("/initrd/cmdline/some_more", test_some_more); - g_test_add_func("/initrd/cmdline/bootdev", test_bootdev); - g_test_add_func("/initrd/cmdline/bond", test_bond); - g_test_add_func("/initrd/cmdline/bond/ip", test_bond_ip); - g_test_add_func("/initrd/cmdline/bond/default", test_bond_default); - g_test_add_func("/initrd/cmdline/team", test_team); - g_test_add_func("/initrd/cmdline/vlan", test_vlan); - g_test_add_func("/initrd/cmdline/vlan/dhcp-on-parent", test_vlan_with_dhcp_on_parent); - g_test_add_func("/initrd/cmdline/vlan/over-bond", test_vlan_over_bond); - g_test_add_func("/initrd/cmdline/bridge", test_bridge); - g_test_add_func("/initrd/cmdline/bridge/default", test_bridge_default); - g_test_add_func("/initrd/cmdline/bridge/ip", test_bridge_ip); - g_test_add_func("/initrd/cmdline/ibft/ip_dev", test_ibft_ip_dev); - g_test_add_func("/initrd/cmdline/ibft/ip_dev_mac", test_ibft_ip_dev_mac); - g_test_add_func("/initrd/cmdline/ibft/ip", test_ibft_ip); - g_test_add_func("/initrd/cmdline/ibft/rd_iscsi_ibft", test_ibft_rd_iscsi_ibft); - g_test_add_func("/initrd/cmdline/ignore_extra", test_ignore_extra); - g_test_add_func("/initrd/cmdline/rd_znet", test_rd_znet); - g_test_add_func("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy); - g_test_add_func("/initrd/cmdline/rd_znet/no_ip", test_rd_znet_no_ip); - g_test_add_func("/initrd/cmdline/rd_znet/empty", test_rd_znet_malformed); - g_test_add_func("/initrd/cmdline/bootif/ip", test_bootif_ip); - g_test_add_func("/initrd/cmdline/bootif/no_ip", test_bootif_no_ip); - g_test_add_func("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype); - g_test_add_func("/initrd/cmdline/bootif/off", test_bootif_off); - g_test_add_func("/initrd/cmdline/neednet", test_neednet); - g_test_add_func("/initrd/cmdline/dhcp/vendor_class_id", test_dhcp_vendor_class_id); - g_test_add_func("/initrd/cmdline/infiniband/iface", test_infiniband_iface); - g_test_add_func("/initrd/cmdline/infiniband/mac", test_infiniband_mac); - g_test_add_func("/initrd/cmdline/carrier_timeout", test_carrier_timeout); - - return g_test_run(); -} diff --git a/src/core/initrd/tests/test-dt-reader.c b/src/core/initrd/tests/test-dt-reader.c deleted file mode 100644 index 619a4e6f..00000000 --- a/src/core/initrd/tests/test-dt-reader.c +++ /dev/null @@ -1,144 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include -#include -#include -#include -#include -#include - -#include "nm-core-internal.h" -#include "NetworkManagerUtils.h" - -#include "../nm-initrd-generator.h" - -#include "nm-test-utils-core.h" - -#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/core/initrd/tests" - -/*****************************************************************************/ - -static void -test_read_dt_ofw(void) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - const char * mac_address; - - connection = nmi_dt_reader_parse(TEST_INITRD_DIR "/sysfs-dt"); - g_assert(connection); - nmtst_assert_connection_verifies(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "OpenFirmware Connection"); - g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); - g_assert(nm_setting_connection_get_autoconnect(s_con)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - mac_address = nm_setting_wired_get_mac_address(s_wired); - g_assert(mac_address); - g_assert(nm_utils_hwaddr_matches(mac_address, -1, "ac:7f:3e:e5:d8:d8", -1)); - g_assert(!nm_setting_wired_get_duplex(s_wired)); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 0); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip4), ==, "demiurge"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - - g_object_unref(connection); -} - -static void -test_read_dt_slof(void) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMIPAddress * ip4_addr; - - connection = nmi_dt_reader_parse(TEST_INITRD_DIR "/sysfs-dt-tftp"); - g_assert(connection); - nmtst_assert_connection_verifies(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "OpenFirmware Connection"); - g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); - g_assert(nm_setting_connection_get_autoconnect(s_con)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - g_assert_cmpstr(nm_setting_wired_get_duplex(s_wired), ==, "half"); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 10); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip4_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "192.168.32.2"); - g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 16); - - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.32.1"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - - g_object_unref(connection); -} - -static void -test_read_dt_none(void) -{ - NMConnection *connection; - - connection = nmi_dt_reader_parse(TEST_INITRD_DIR "/sysfs"); - g_assert(!connection); -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT"); - - g_test_add_func("/initrd/dt/ofw", test_read_dt_ofw); - g_test_add_func("/initrd/dt/slof", test_read_dt_slof); - g_test_add_func("/initrd/dt/none", test_read_dt_none); - - return g_test_run(); -} diff --git a/src/core/initrd/tests/test-ibft-reader.c b/src/core/initrd/tests/test-ibft-reader.c deleted file mode 100644 index 1d263b9e..00000000 --- a/src/core/initrd/tests/test-ibft-reader.c +++ /dev/null @@ -1,303 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include -#include -#include -#include -#include -#include - -#include "nm-core-internal.h" -#include "NetworkManagerUtils.h" - -#include "../nm-initrd-generator.h" - -#include "nm-test-utils-core.h" - -#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/core/initrd/tests" - -/*****************************************************************************/ - -static NMConnection * -read_connection(const char *sysfs_dir, const char *expected_mac, GError **error) -{ - NMConnection * connection = NULL; - gs_unref_hashtable GHashTable *ibft = NULL; - gs_free char * mac = NULL; - GHashTable * nic = NULL; - - ibft = nmi_ibft_read(sysfs_dir); - - mac = g_ascii_strup(expected_mac, -1); - nic = g_hash_table_lookup(ibft, mac); - if (!nic) - return NULL; - - connection = nm_simple_connection_new(); - - if (!nmi_ibft_update_connection_from_nic(connection, nic, error)) - g_clear_object(&connection); - - return connection; -} - -static void -test_read_ibft_dhcp(void) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - GError * error = NULL; - const char * mac_address; - const char * expected_mac_address = "00:33:21:98:b9:f1"; - - connection = read_connection(TEST_INITRD_DIR "/sysfs-dhcp", expected_mac_address, &error); - g_assert_no_error(error); - nmtst_assert_connection_verifies_without_normalization(connection); - - g_assert(!nm_connection_get_setting_vlan(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "iBFT Connection 1"); - 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)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - mac_address = nm_setting_wired_get_mac_address(s_wired); - g_assert(mac_address); - g_assert(nm_utils_hwaddr_matches(mac_address, -1, expected_mac_address, -1)); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - - g_object_unref(connection); -} - -static void -test_read_ibft_static(void) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - GError * error = NULL; - const char * mac_address; - const char * expected_mac_address = "00:33:21:98:b9:f0"; - NMIPAddress * ip4_addr; - - connection = read_connection(TEST_INITRD_DIR "/sysfs-static", expected_mac_address, &error); - g_assert_no_error(error); - nmtst_assert_connection_verifies_without_normalization(connection); - - g_assert(!nm_connection_get_setting_vlan(connection)); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "iBFT Connection 0"); - 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)); - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - mac_address = nm_setting_wired_get_mac_address(s_wired); - g_assert(mac_address); - g_assert(nm_utils_hwaddr_matches(mac_address, -1, expected_mac_address, -1)); - g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 2); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "10.16.255.2"); - g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 1), ==, "10.16.255.3"); - - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip4_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "192.168.32.72"); - g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 22); - - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.35.254"); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - - g_object_unref(connection); -} - -static void -test_read_ibft_bad_address(gconstpointer user_data) -{ - const char * sysfs_dir = user_data; - NMConnection *connection; - GError * error = NULL; - - g_assert(g_file_test(sysfs_dir, G_FILE_TEST_EXISTS)); - - connection = read_connection(sysfs_dir, "00:33:21:98:b9:f0", &error); - g_assert(connection == NULL); - g_assert(error); - g_clear_error(&error); -} - -static void -test_read_ibft_vlan(void) -{ - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingVlan * s_vlan; - NMSettingIPConfig * s_ip4; - const char * mac_address; - const char * expected_mac_address = "00:33:21:98:b9:f0"; - NMIPAddress * ip4_addr; - GError * error = NULL; - - connection = read_connection(TEST_INITRD_DIR "/sysfs-vlan", expected_mac_address, &error); - g_assert_no_error(error); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), - ==, - NM_SETTING_VLAN_SETTING_NAME); - g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL); - - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - mac_address = nm_setting_wired_get_mac_address(s_wired); - g_assert(mac_address); - g_assert(nm_utils_hwaddr_matches(mac_address, -1, expected_mac_address, -1)); - - /* ===== VLAN SETTING ===== */ - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); - g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 123); - g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, NULL); - - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - - g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - - g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); - ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); - g_assert(ip4_addr); - g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "192.168.6.200"); - g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 24); - - g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, NULL); - - g_object_unref(connection); -} - -static void -test_read_ibft(void) -{ - NMConnection * connection; - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; - GError * error = NULL; - - /* This test doesn't actually test too much (apart from the presence of - * IPv6 that is not covered by other tests), but the test fixture is a good - * example of about everything that can be included in iBFT table (as of - * ACPI 3.0b). */ - - connection = read_connection(TEST_INITRD_DIR "/sysfs", "00:53:00:AB:00:01", &error); - g_assert(connection); - g_assert_no_error(error); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert(nm_setting_ip_config_get_num_addresses(s_ip4) == 0); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(nm_setting_ip_config_get_num_addresses(s_ip6) == 1); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_object_unref(connection); - - connection = read_connection(TEST_INITRD_DIR "/sysfs", "00:53:06:66:AB:01", &error); - g_assert(connection); - g_assert_no_error(error); - nmtst_assert_connection_verifies_without_normalization(connection); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(nm_setting_ip_config_get_num_addresses(s_ip4) == 1); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(nm_setting_ip_config_get_num_addresses(s_ip6) == 0); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), - ==, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED); - g_object_unref(connection); -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT"); - - g_test_add_func("/initrd/ibft", test_read_ibft); - g_test_add_func("/initrd/ibft/dhcp", test_read_ibft_dhcp); - g_test_add_func("/initrd/ibft/static", test_read_ibft_static); - g_test_add_func("/initrd/ibft/vlan", test_read_ibft_vlan); - g_test_add_data_func("/initrd/ibft/bad-ipaddr-read", - TEST_INITRD_DIR "/sysfs-bad-ipaddr", - test_read_ibft_bad_address); - g_test_add_data_func("/initrd/ibft/bad-gateway-read", - TEST_INITRD_DIR "/sysfs-bad-gateway", - test_read_ibft_bad_address); - g_test_add_data_func("/initrd/ibft/bad-dns1-read", - TEST_INITRD_DIR "/sysfs-bad-dns1", - test_read_ibft_bad_address); - g_test_add_data_func("/initrd/ibft/bad-dns2-read", - TEST_INITRD_DIR "/sysfs-bad-dns2", - test_read_ibft_bad_address); - - return g_test_run(); -} diff --git a/src/core/main.c b/src/core/main.c index 9b79bcbb..3cb5c07f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,7 @@ #include "nm-dbus-interface.h" #include "NetworkManagerUtils.h" #include "nm-manager.h" -#include "platform/nm-linux-platform.h" +#include "libnm-platform/nm-linux-platform.h" #include "nm-dbus-manager.h" #include "devices/nm-device.h" #include "dhcp/nm-dhcp-manager.h" @@ -29,11 +30,11 @@ #include "nm-dispatcher.h" #include "settings/nm-settings.h" #include "nm-auth-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-object.h" #include "nm-connectivity.h" #include "dns/nm-dns-manager.h" -#include "systemd/nm-sd.h" +#include "libnm-systemd-core/nm-sd.h" #include "nm-netns.h" #if !defined(NM_DIST_VERSION) @@ -303,14 +304,14 @@ main(int argc, char *argv[]) const char *const * warnings; int errsv; + _nm_utils_is_manager_process = TRUE; + /* Known to cause a possible deadlock upon GDBus initialization: * https://bugzilla.gnome.org/show_bug.cgi?id=674885 */ g_type_ensure(G_TYPE_SOCKET); g_type_ensure(G_TYPE_DBUS_CONNECTION); g_type_ensure(NM_TYPE_DBUS_MANAGER); - _nm_utils_is_manager_process = TRUE; - main_loop = g_main_loop_new(NULL, FALSE); /* we determine a first-start (contrary to a restart during the same boot) @@ -508,7 +509,7 @@ main(int argc, char *argv[]) * physical interfaces. */ nm_log_dbg(LOGD_CORE, "setting up local loopback"); - nm_platform_link_set_up(NM_PLATFORM_GET, 1, NULL); + nm_platform_link_change_flags(NM_PLATFORM_GET, 1, IFF_UP, TRUE); success = TRUE; diff --git a/src/core/meson.build b/src/core/meson.build index 368a3e85..f4d7af64 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -1,27 +1,27 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -src_inc = include_directories('.') +src_core_inc = include_directories('.') core_plugin_dep = declare_dependency( - sources: libnm_core_enum_sources[1], include_directories: [ - src_inc, + src_core_inc, top_inc, - shared_inc, - libnm_core_inc, + libnm_core_public_inc, ], dependencies: [ + libnm_core_public_dep, glib_dep, ], ) core_default_dep = declare_dependency( - sources: libnm_core_enum_sources[1], - include_directories: src_inc, + include_directories: [ + src_core_inc, + src_inc, + top_inc, + ], dependencies: [ - libnm_core_nm_default_dep, - libnm_log_core_dep, - libnm_platform_dep, + libnm_core_public_dep, ], ) @@ -30,19 +30,8 @@ install_data( install_dir: dbus_conf_dir, ) -subdir('systemd') - core_plugins = [] -daemon_c_flags = [ - '-DG_LOG_DOMAIN="NetworkManager"', -] - -platform_wifi_wext_source = files() -if enable_wext - platform_wifi_wext_source += files('platform/wifi/nm-wifi-utils-wext.c') -endif - libNetworkManagerBase = static_library( 'NetworkManagerBase', sources: files( @@ -54,13 +43,6 @@ libNetworkManagerBase = static_library( 'dhcp/nm-dhcp-options.c', 'ndisc/nm-lndp-ndisc.c', 'ndisc/nm-ndisc.c', - 'platform/wifi/nm-wifi-utils-nl80211.c', - 'platform/wifi/nm-wifi-utils.c', - 'platform/wpan/nm-wpan-utils.c', - 'platform/nm-linux-platform.c', - 'platform/nm-platform.c', - 'platform/nmp-object.c', - 'platform/nmp-rules-manager.c', 'main-utils.c', 'NetworkManagerUtils.c', 'nm-core-utils.c', @@ -73,23 +55,19 @@ libNetworkManagerBase = static_library( 'nm-ip-config.c', 'nm-ip4-config.c', 'nm-ip6-config.c', - ) + platform_wifi_wext_source, + ), dependencies: [ core_default_dep, - libn_dhcp4_dep, - libnm_core_dep, - libnm_systemd_shared_dep, - libnm_udev_aux_dep, + libnm_core_public_dep, libsystemd_dep, libudev_dep, ], - c_args: daemon_c_flags, ) nm_deps = [ + libnm_core_public_dep, core_default_dep, dl_dep, - libn_acd_dep, libndp_dep, libudev_dep, logind_dep, @@ -119,6 +97,7 @@ libNetworkManager = static_library( 'devices/nm-device-bond.c', 'devices/nm-device-bridge.c', 'devices/nm-device.c', + 'devices/nm-device-utils.c', 'devices/nm-device-dummy.c', 'devices/nm-device-ethernet.c', 'devices/nm-device-ethernet-utils.c', @@ -182,7 +161,8 @@ libNetworkManager = static_library( 'nm-dcb.c', 'nm-dhcp-config.c', 'nm-dispatcher.c', - 'nm-firewall-manager.c', + 'nm-firewall-utils.c', + 'nm-firewalld-manager.c', 'nm-hostname-manager.c', 'nm-keep-alive.c', 'nm-manager.c', @@ -194,7 +174,6 @@ libNetworkManager = static_library( 'nm-sleep-monitor.c', ), dependencies: nm_deps, - c_args: daemon_c_flags, link_with: [ libNetworkManagerBase, libnm_systemd_core, @@ -207,16 +186,28 @@ executable( 'nm-iface-helper.c', dependencies: [ core_default_dep, - dl_dep, - libndp_dep, + glib_dep, libudev_dep, - libn_acd_dep, + libndp_dep, + dl_dep, ], - c_args: daemon_c_flags, link_with: [ libNetworkManagerBase, + libnm_core_aux_intern, + libnm_core_impl, + libnm_crypto, libnm_systemd_core, + libnm_platform, libnm_systemd_shared, + libnm_base, + libnm_udev_aux, + libnm_log_core, + libnm_glib_aux, + libnm_std_aux, + libn_acd, + libn_dhcp4, + libc_rbtree, + libc_siphash, ], link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, @@ -225,7 +216,7 @@ executable( ) if enable_tests - test_c_flags = daemon_c_flags + test_c_flags = [] if require_root_tests test_c_flags += ['-DREQUIRE_ROOT_TESTS=1'] endif @@ -244,7 +235,23 @@ if enable_tests libNetworkManagerTest_dep = declare_dependency( dependencies: core_default_dep, - link_with: libNetworkManagerTest, + link_with: [ + libNetworkManagerTest, + libnm_core_aux_intern, + libnm_core_impl, + libnm_crypto, + libnm_platform, + libnm_base, + libnm_systemd_shared, + libnm_udev_aux, + libnm_log_core, + libnm_glib_aux, + libnm_std_aux, + libn_acd, + libn_dhcp4, + libc_siphash, + libc_rbtree, + ], ) subdir('dnsmasq/tests') @@ -261,7 +268,6 @@ if enable_ppp endif subdir('devices') -subdir('initrd') subdir('settings/plugins') # NetworkManager binary @@ -274,13 +280,27 @@ subdir('settings/plugins') NetworkManager_all_sym = executable( 'NetworkManager-all-sym', 'main.c', - dependencies: nm_deps, - c_args: daemon_c_flags, + dependencies: [ + nm_deps, + libudev_dep, + ], link_args: '-Wl,--no-gc-sections', link_whole: [ libNetworkManager, libNetworkManagerBase, - libnm_core, + libnm_core_aux_intern, + libnm_core_impl, + libnm_crypto, + libnm_platform, + libnm_base, + libnm_log_core, + libnm_udev_aux, + libnm_glib_aux, + libnm_std_aux, + libn_acd, + libn_dhcp4, + libc_rbtree, + libc_siphash, ], ) @@ -301,9 +321,27 @@ ver_script = custom_target( NetworkManager = executable( 'NetworkManager', 'main.c', - dependencies: nm_deps, - c_args: daemon_c_flags, - link_with: libNetworkManager, + dependencies: [ + nm_deps, + libudev_dep, + ], + link_with: [ + libNetworkManager, + libNetworkManagerBase, + libnm_core_aux_intern, + libnm_core_impl, + libnm_crypto, + libnm_platform, + libnm_base, + libnm_udev_aux, + libnm_log_core, + libnm_glib_aux, + libnm_std_aux, + libn_acd, + libn_dhcp4, + libc_rbtree, + libc_siphash, + ], link_args: [ '-rdynamic', '-Wl,--version-script,@0@'.format(ver_script.full_path()), diff --git a/src/core/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c index f773478f..f11178f8 100644 --- a/src/core/ndisc/nm-lndp-ndisc.c +++ b/src/core/ndisc/nm-lndp-ndisc.c @@ -13,12 +13,12 @@ #include #include -#include "nm-glib-aux/nm-str-buf.h" -#include "systemd/nm-sd-utils-shared.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" #include "nm-ndisc-private.h" #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" -#include "nm-platform/nmp-netns.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-netns.h" #define _NMLOG_PREFIX_NAME "ndisc-lndp" @@ -85,14 +85,14 @@ send_rs(NMNDisc *ndisc, GError **error) static NMIcmpv6RouterPref _route_preference_coerce(enum ndp_route_preference pref) { -#define _ASSERT_ENUM(v1, v2) \ - G_STMT_START \ - { \ - G_STATIC_ASSERT((NMIcmpv6RouterPref)(v1) == (v2)); \ - G_STATIC_ASSERT((enum ndp_route_preference)(v2) == (v1)); \ - G_STATIC_ASSERT((gint64)(v1) == (v2)); \ - G_STATIC_ASSERT((gint64)(v2) == (v1)); \ - } \ +#define _ASSERT_ENUM(v1, v2) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT((NMIcmpv6RouterPref) (v1) == (v2)); \ + G_STATIC_ASSERT((enum ndp_route_preference) (v2) == (v1)); \ + G_STATIC_ASSERT((gint64) (v1) == (v2)); \ + G_STATIC_ASSERT((gint64) (v2) == (v1)); \ + } \ G_STMT_END switch (pref) { diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index a5c1b935..cf1b58ec 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -14,8 +14,8 @@ #include "nm-ndisc-private.h" #include "nm-utils.h" -#include "platform/nm-platform.h" -#include "nm-platform/nmp-netns.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-netns.h" #include "nm-l3-config-data.h" #define _NMLOG_PREFIX_NAME "ndisc" @@ -806,7 +806,7 @@ solicit_retransmit_time_jitter(gint32 solicit_retransmit_time_msec) ten_percent = NM_MAX(1, solicit_retransmit_time_msec / 10); return solicit_retransmit_time_msec - ten_percent - + ((gint32)(g_random_int() % (2u * ((guint32) ten_percent)))); + + ((gint32) (g_random_int() % (2u * ((guint32) ten_percent)))); } static gboolean @@ -882,7 +882,7 @@ solicit_timer_start(NMNDisc *ndisc) * a suitable delay in 2021. Wait only up to 250 msec instead. */ delay_msec = - g_random_int() % ((guint32)(NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4)); + g_random_int() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4)); _LOGD("solicit: schedule sending first solicitation (of %d) in %.3f seconds", priv->router_solicitations, diff --git a/src/core/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h index 93aee4db..15f95d20 100644 --- a/src/core/ndisc/nm-ndisc.h +++ b/src/core/ndisc/nm-ndisc.h @@ -13,8 +13,8 @@ #include "nm-setting-ip6-config.h" #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #define NM_RA_TIMEOUT_DEFAULT ((guint32) 0) #define NM_RA_TIMEOUT_INFINITY ((guint32) G_MAXINT32) @@ -99,7 +99,7 @@ _nm_ndisc_lifetime_from_expiry(gint64 now_msec, gint64 expiry_msec, gboolean cei diff += 999; } - return NM_MIN(diff / 1000, (gint64)(G_MAXUINT32 - 1)); + return NM_MIN(diff / 1000, (gint64) (G_MAXUINT32 - 1)); } /*****************************************************************************/ @@ -159,10 +159,10 @@ typedef enum { #define NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY 1 /* seconds */ #define NM_NDISC_MAX_ADDRESSES_DEFAULT 16 -#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861, MAX_RTR_SOLICITATIONS */ -#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861, MAX_INITIAL_RTR_ADVERTISEMENTS */ -#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861, MIN_DELAY_BETWEEN_RAS */ -#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861, MAX_INITIAL_RTR_ADVERT_INTERVAL */ +#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861, MAX_RTR_SOLICITATIONS */ +#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861, MAX_INITIAL_RTR_ADVERTISEMENTS */ +#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861, MIN_DELAY_BETWEEN_RAS */ +#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861, MAX_INITIAL_RTR_ADVERT_INTERVAL */ #define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861, MAX_RA_DELAY_TIME */ #define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861, MaxRtrAdvInterval default */ #define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */ diff --git a/src/core/ndisc/tests/test-ndisc-linux.c b/src/core/ndisc/tests/test-ndisc-linux.c index 9a5df60b..c84ee142 100644 --- a/src/core/ndisc/tests/test-ndisc-linux.c +++ b/src/core/ndisc/tests/test-ndisc-linux.c @@ -10,7 +10,7 @@ #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" -#include "platform/nm-linux-platform.h" +#include "libnm-platform/nm-linux-platform.h" #include "nm-test-utils-core.h" diff --git a/src/core/nm-act-request.c b/src/core/nm-act-request.c index defe3e8c..d0a2e0c7 100644 --- a/src/core/nm-act-request.c +++ b/src/core/nm-act-request.c @@ -13,17 +13,19 @@ #include #include "c-list/src/c-list.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" -#include "nm-setting-wireless-security.h" #include "nm-setting-8021x.h" +#include "nm-setting-wireless-security.h" + #include "devices/nm-device.h" #include "nm-active-connection.h" +#include "nm-firewall-utils.h" #include "settings/nm-settings-connection.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" typedef struct { - CList call_ids_lst_head; - NMUtilsShareRules *share_rules; + CList call_ids_lst_head; + NMFirewallConfig *firewall_config; } NMActRequestPrivate; struct _NMActRequest { @@ -248,31 +250,31 @@ nm_act_request_clear_secrets(NMActRequest *self) /*****************************************************************************/ -NMUtilsShareRules * +NMFirewallConfig * nm_act_request_get_shared(NMActRequest *req) { g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE); - return NM_ACT_REQUEST_GET_PRIVATE(req)->share_rules; + return NM_ACT_REQUEST_GET_PRIVATE(req)->firewall_config; } void -nm_act_request_set_shared(NMActRequest *req, NMUtilsShareRules *rules) +nm_act_request_set_shared(NMActRequest *req, NMFirewallConfig *rules) { NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req); g_return_if_fail(NM_IS_ACT_REQUEST(req)); - if (priv->share_rules == rules) + if (priv->firewall_config == rules) return; - if (priv->share_rules) { - nm_utils_share_rules_apply(priv->share_rules, FALSE); - priv->share_rules = NULL; + if (priv->firewall_config) { + nm_firewall_config_apply(priv->firewall_config, FALSE); + priv->firewall_config = NULL; } if (rules) { - priv->share_rules = rules; - nm_utils_share_rules_apply(priv->share_rules, TRUE); + priv->firewall_config = rules; + nm_firewall_config_apply(priv->firewall_config, TRUE); } } @@ -506,9 +508,9 @@ dispose(GObject *object) c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst) _do_cancel_secrets(self, call_id, TRUE); - if (priv->share_rules) { - nm_utils_share_rules_apply(priv->share_rules, FALSE); - nm_clear_pointer(&priv->share_rules, nm_utils_share_rules_free); + if (priv->firewall_config) { + nm_firewall_config_apply(priv->firewall_config, FALSE); + nm_clear_pointer(&priv->firewall_config, nm_firewall_config_free); } G_OBJECT_CLASS(nm_act_request_parent_class)->dispose(object); diff --git a/src/core/nm-act-request.h b/src/core/nm-act-request.h index 2a568430..9c702d31 100644 --- a/src/core/nm-act-request.h +++ b/src/core/nm-act-request.h @@ -38,11 +38,11 @@ NMConnection *nm_act_request_get_applied_connection(NMActRequest *req); /*****************************************************************************/ -struct _NMUtilsShareRules; +struct _NMFirewallConfig; -struct _NMUtilsShareRules *nm_act_request_get_shared(NMActRequest *req); +struct _NMFirewallConfig *nm_act_request_get_shared(NMActRequest *req); -void nm_act_request_set_shared(NMActRequest *req, struct _NMUtilsShareRules *rules); +void nm_act_request_set_shared(NMActRequest *req, struct _NMFirewallConfig *rules); /*****************************************************************************/ diff --git a/src/core/nm-active-connection.c b/src/core/nm-active-connection.c index 3c8c472e..40fe3c96 100644 --- a/src/core/nm-active-connection.c +++ b/src/core/nm-active-connection.c @@ -7,17 +7,17 @@ #include "nm-active-connection.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-interface.h" #include "devices/nm-device.h" #include "settings/nm-settings-connection.h" #include "nm-simple-connection.h" #include "nm-auth-utils.h" #include "nm-auth-manager.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-keep-alive.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #define AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED ((NMAuthManagerCallId *) GINT_TO_POINTER(1)) @@ -516,11 +516,6 @@ nm_active_connection_clear_secrets(NMActiveConnection *self) priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - if (nm_settings_connection_has_unmodified_applied_connection(priv->settings_connection.obj, - priv->applied_connection, - NM_SETTING_COMPARE_FLAG_NONE)) { - nm_settings_connection_clear_secrets(priv->settings_connection.obj, FALSE, FALSE); - } nm_connection_clear_secrets(priv->applied_connection); } @@ -683,6 +678,7 @@ nm_active_connection_set_device(NMActiveConnection *self, NMDevice *device) { NMActiveConnectionPrivate *priv; gs_unref_object NMDevice *old_device = NULL; + NMMetered old_metered, new_metered; g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), FALSE); g_return_val_if_fail(!device || NM_IS_DEVICE(device), FALSE); @@ -700,6 +696,8 @@ nm_active_connection_set_device(NMActiveConnection *self, NMDevice *device) device); old_device = priv->device ? g_object_ref(priv->device) : NULL; + + old_metered = old_device ? nm_device_get_metered(old_device) : NM_METERED_UNKNOWN; _device_cleanup(self); if (device) { @@ -735,7 +733,11 @@ nm_active_connection_set_device(NMActiveConnection *self, NMDevice *device) } _notify(self, PROP_INT_DEVICE); + new_metered = priv->device ? nm_device_get_metered(priv->device) : NM_METERED_UNKNOWN; + g_signal_emit(self, signals[DEVICE_CHANGED], 0, priv->device, old_device); + if (new_metered != old_metered) + g_signal_emit(self, signals[DEVICE_METERED_CHANGED], 0, new_metered); _notify(self, PROP_DEVICES); @@ -1560,54 +1562,48 @@ static const GDBusSignalInfo signal_info_state_changed = NM_DEFINE_GDBUS_SIGNAL_ static const NMDBusInterfaceInfoExtended interface_info_active_connection = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_ACTIVE_CONNECTION, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_state_changed, ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_state_changed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Connection", - "o", - NM_ACTIVE_CONNECTION_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("SpecificObject", - "o", - NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Id", "s", NM_ACTIVE_CONNECTION_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Uuid", - "s", - NM_ACTIVE_CONNECTION_UUID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Type", - "s", - NM_ACTIVE_CONNECTION_TYPE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Devices", - "ao", - NM_ACTIVE_CONNECTION_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("State", - "u", - NM_ACTIVE_CONNECTION_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("StateFlags", - "u", - NM_ACTIVE_CONNECTION_STATE_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Default", - "b", - NM_ACTIVE_CONNECTION_DEFAULT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip4Config", - "o", - NM_ACTIVE_CONNECTION_IP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp4Config", - "o", - NM_ACTIVE_CONNECTION_DHCP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Default6", - "b", - NM_ACTIVE_CONNECTION_DEFAULT6), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip6Config", - "o", - NM_ACTIVE_CONNECTION_IP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp6Config", - "o", - NM_ACTIVE_CONNECTION_DHCP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Vpn", "b", NM_ACTIVE_CONNECTION_VPN), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Master", - "o", - NM_ACTIVE_CONNECTION_MASTER), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Connection", + "o", + NM_ACTIVE_CONNECTION_CONNECTION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("SpecificObject", + "o", + NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Id", "s", NM_ACTIVE_CONNECTION_ID), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Uuid", "s", NM_ACTIVE_CONNECTION_UUID), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Type", "s", NM_ACTIVE_CONNECTION_TYPE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Devices", + "ao", + NM_ACTIVE_CONNECTION_DEVICES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("State", + "u", + NM_ACTIVE_CONNECTION_STATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("StateFlags", + "u", + NM_ACTIVE_CONNECTION_STATE_FLAGS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Default", + "b", + NM_ACTIVE_CONNECTION_DEFAULT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip4Config", + "o", + NM_ACTIVE_CONNECTION_IP4_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Dhcp4Config", + "o", + NM_ACTIVE_CONNECTION_DHCP4_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Default6", + "b", + NM_ACTIVE_CONNECTION_DEFAULT6), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ip6Config", + "o", + NM_ACTIVE_CONNECTION_IP6_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Dhcp6Config", + "o", + NM_ACTIVE_CONNECTION_DHCP6_CONFIG), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Vpn", "b", NM_ACTIVE_CONNECTION_VPN), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Master", + "o", + NM_ACTIVE_CONNECTION_MASTER), ), ), }; static void diff --git a/src/core/nm-audit-manager.c b/src/core/nm-audit-manager.c index 8f419472..2ef5d860 100644 --- a/src/core/nm-audit-manager.c +++ b/src/core/nm-audit-manager.c @@ -11,14 +11,18 @@ #include #endif -#include "nm-libnm-core-intern/nm-auth-subject.h" +#define NM_VALUE_TYPE_DEFINE_FUNCTIONS + +#include "libnm-core-aux-intern/nm-auth-subject.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-value-type.h" #include "nm-config.h" #include "nm-dbus-manager.h" #include "settings/nm-settings-connection.h" /*****************************************************************************/ -typedef enum { +typedef enum _nm_packed { BACKEND_LOG = (1 << 0), BACKEND_AUDITD = (1 << 1), _BACKEND_LAST, @@ -26,10 +30,11 @@ typedef enum { } AuditBackend; typedef struct { - const char * name; - GValue value; - gboolean need_encoding; - AuditBackend backends; + const char * name; + AuditBackend backends; + bool need_encoding; + NMValueType value_type; + NMValueTypUnion value; } AuditField; /*****************************************************************************/ @@ -85,66 +90,77 @@ _audit_field_init_string(AuditField * field, gboolean need_encoding, AuditBackend backends) { - field->name = name; - field->need_encoding = need_encoding; - field->backends = backends; - g_value_init(&field->value, G_TYPE_STRING); - g_value_set_static_string(&field->value, str); + *field = (AuditField){ + .name = name, + .need_encoding = need_encoding, + .backends = backends, + .value_type = NM_VALUE_TYPE_STRING, + .value.v_string = str, + }; } static void -_audit_field_init_uint(AuditField *field, const char *name, uint val, AuditBackend backends) +_audit_field_init_uint64(AuditField *field, const char *name, guint64 val, AuditBackend backends) { - field->name = name; - field->backends = backends; - g_value_init(&field->value, G_TYPE_UINT); - g_value_set_uint(&field->value, val); + *field = (AuditField){ + .name = name, + .backends = backends, + .value_type = NM_VALUE_TYPE_UINT64, + .value.v_uint64 = val, + }; } -static char * -build_message(GPtrArray *fields, AuditBackend backend) +static const char * +build_message(NMStrBuf *strbuf, AuditBackend backend, GPtrArray *fields) { - GString * string; - AuditField *field; - gboolean first = TRUE; - guint i; + guint i; - string = g_string_new(NULL); + if (strbuf->len == 0) { + /* preallocate a large buffer... */ + nm_str_buf_maybe_expand(strbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_232, FALSE); + } else + nm_str_buf_reset(strbuf); for (i = 0; i < fields->len; i++) { - field = fields->pdata[i]; + const AuditField *field = fields->pdata[i]; if (!NM_FLAGS_ANY(field->backends, backend)) continue; - if (first) - first = FALSE; - else - g_string_append_c(string, ' '); + nm_str_buf_append_required_delimiter(strbuf, ' '); - if (G_VALUE_HOLDS_STRING(&field->value)) { - const char *str = g_value_get_string(&field->value); + if (field->value_type == NM_VALUE_TYPE_STRING) { + const char *str = field->value.v_string; #if HAVE_LIBAUDIT if (backend == BACKEND_AUDITD) { if (field->need_encoding) { - char *value; + gs_free char *value = NULL; value = audit_encode_nv_string(field->name, str, 0); - g_string_append(string, value); - g_free(value); + nm_str_buf_append(strbuf, value); } else - g_string_append_printf(string, "%s=%s", field->name, str); + nm_str_buf_append_printf(strbuf, "%s=%s", field->name, str); continue; } #endif /* HAVE_LIBAUDIT */ - g_string_append_printf(string, "%s=\"%s\"", field->name, str); - } else if (G_VALUE_HOLDS_UINT(&field->value)) { - g_string_append_printf(string, "%s=%u", field->name, g_value_get_uint(&field->value)); - } else - g_assert_not_reached(); + + nm_str_buf_append_printf(strbuf, "%s=\"%s\"", field->name, str); + continue; + } + + if (field->value_type == NM_VALUE_TYPE_UINT64) { + nm_str_buf_append_printf(strbuf, + "%s=%" G_GUINT64_FORMAT, + field->name, + field->value.v_uint64); + continue; + } + + g_return_val_if_reached(NULL); } - return g_string_free(string, FALSE); + + return nm_str_buf_get_str(strbuf); } static void @@ -155,10 +171,10 @@ nm_audit_log(NMAuditManager *self, const char * func, gboolean success) { + nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(0, FALSE); #if HAVE_LIBAUDIT NMAuditManagerPrivate *priv; #endif - char *msg; g_return_if_fail(NM_IS_AUDIT_MANAGER(self)); @@ -166,16 +182,29 @@ nm_audit_log(NMAuditManager *self, priv = NM_AUDIT_MANAGER_GET_PRIVATE(self); if (priv->auditd_fd >= 0) { - msg = build_message(fields, BACKEND_AUDITD); - audit_log_user_message(priv->auditd_fd, AUDIT_USYS_CONFIG, msg, NULL, NULL, NULL, success); - g_free(msg); + audit_log_user_message(priv->auditd_fd, + AUDIT_USYS_CONFIG, + build_message(&strbuf, BACKEND_AUDITD, fields), + NULL, + NULL, + NULL, + success); } #endif if (nm_logging_enabled(AUDIT_LOG_LEVEL, LOGD_AUDIT)) { - msg = build_message(fields, BACKEND_LOG); - _NMLOG(AUDIT_LOG_LEVEL, LOGD_AUDIT, "%s", msg); - g_free(msg); + _nm_log_full(file, + line, + func, + !(NM_THREAD_SAFE_ON_MAIN_THREAD), + AUDIT_LOG_LEVEL, + LOGD_AUDIT, + 0, + NULL, + NULL, + "%s%s", + _NMLOG_PREFIX_NAME ": ", + build_message(&strbuf, BACKEND_LOG, fields)); } } @@ -190,9 +219,13 @@ _audit_log_helper(NMAuditManager *self, gpointer subject_context, const char * reason) { - AuditField op_field = {}, pid_field = {}, uid_field = {}; - AuditField result_field = {}, reason_field = {}; - gulong pid, uid; + AuditField op_field; + AuditField pid_field; + AuditField uid_field; + AuditField result_field; + AuditField reason_field; + gulong pid; + gulong uid; NMAuthSubject * subject = NULL; gs_unref_object NMAuthSubject *subject_free = NULL; @@ -213,11 +246,11 @@ _audit_log_helper(NMAuditManager *self, pid = nm_auth_subject_get_unix_process_pid(subject); uid = nm_auth_subject_get_unix_process_uid(subject); if (pid != G_MAXULONG) { - _audit_field_init_uint(&pid_field, "pid", pid, BACKEND_ALL); + _audit_field_init_uint64(&pid_field, "pid", pid, BACKEND_ALL); g_ptr_array_add(fields, &pid_field); } if (uid != G_MAXULONG) { - _audit_field_init_uint(&uid_field, "uid", uid, BACKEND_ALL); + _audit_field_init_uint64(&uid_field, "uid", uid, BACKEND_ALL); g_ptr_array_add(fields, &uid_field); } } @@ -262,8 +295,10 @@ _nm_audit_manager_log_connection_op(NMAuditManager * self, gpointer subject_context, const char * reason) { - gs_unref_ptrarray GPtrArray *fields = NULL; - AuditField uuid_field = {}, name_field = {}, args_field = {}; + gs_unref_ptrarray GPtrArray *fields = NULL; + AuditField uuid_field; + AuditField name_field; + AuditField args_field; g_return_if_fail(op); @@ -304,8 +339,8 @@ _nm_audit_manager_log_generic_op(NMAuditManager *self, gpointer subject_context, const char * reason) { - gs_unref_ptrarray GPtrArray *fields = NULL; - AuditField arg_field = {}; + gs_unref_ptrarray GPtrArray *fields = NULL; + AuditField arg_field; g_return_if_fail(op); g_return_if_fail(arg); @@ -330,8 +365,10 @@ _nm_audit_manager_log_device_op(NMAuditManager *self, gpointer subject_context, const char * reason) { - gs_unref_ptrarray GPtrArray *fields = NULL; - AuditField interface_field = {}, ifindex_field = {}, args_field = {}; + gs_unref_ptrarray GPtrArray *fields = NULL; + AuditField interface_field; + AuditField ifindex_field; + AuditField args_field; int ifindex; g_return_if_fail(op); @@ -348,7 +385,7 @@ _nm_audit_manager_log_device_op(NMAuditManager *self, ifindex = nm_device_get_ip_ifindex(device); if (ifindex > 0) { - _audit_field_init_uint(&ifindex_field, "ifindex", ifindex, BACKEND_ALL); + _audit_field_init_uint64(&ifindex_field, "ifindex", ifindex, BACKEND_ALL); g_ptr_array_add(fields, &ifindex_field); } diff --git a/src/core/nm-auth-manager.c b/src/core/nm-auth-manager.c index 9470838c..5c0e465a 100644 --- a/src/core/nm-auth-manager.c +++ b/src/core/nm-auth-manager.c @@ -8,9 +8,9 @@ #include "nm-auth-manager.h" #include "c-list/src/c-list.h" -#include "nm-glib-aux/nm-dbus-aux.h" +#include "libnm-glib-aux/nm-dbus-aux.h" #include "nm-errors.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" diff --git a/src/core/nm-auth-manager.h b/src/core/nm-auth-manager.h index 991083c1..0586322f 100644 --- a/src/core/nm-auth-manager.h +++ b/src/core/nm-auth-manager.h @@ -6,7 +6,7 @@ #ifndef NM_AUTH_MANAGER_H #define NM_AUTH_MANAGER_H -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-config-data.h" /*****************************************************************************/ diff --git a/src/core/nm-auth-utils.c b/src/core/nm-auth-utils.c index 12da5749..006264dd 100644 --- a/src/core/nm-auth-utils.c +++ b/src/core/nm-auth-utils.c @@ -7,9 +7,9 @@ #include "nm-auth-utils.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-setting-connection.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-auth-manager.h" #include "nm-session-monitor.h" #include "nm-dbus-manager.h" diff --git a/src/core/nm-checkpoint.c b/src/core/nm-checkpoint.c index 2088c247..164f4a86 100644 --- a/src/core/nm-checkpoint.c +++ b/src/core/nm-checkpoint.c @@ -9,7 +9,7 @@ #include "nm-active-connection.h" #include "nm-act-request.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-core-utils.h" #include "nm-dbus-interface.h" #include "devices/nm-device.h" @@ -229,14 +229,16 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp if (need_update) { _LOGD("rollback: updating connection %s", nm_settings_connection_get_uuid(connection)); persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP; - nm_settings_connection_update(connection, - dev_checkpoint->settings_connection, - persist_mode, - sett_flags, - sett_mask, - NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE, - "checkpoint-rollback", - NULL); + nm_settings_connection_update( + connection, + dev_checkpoint->settings_connection, + persist_mode, + sett_flags, + sett_mask, + NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET, + "checkpoint-rollback", + NULL); } } else { /* The connection was deleted, recreate it */ @@ -737,16 +739,12 @@ dispose(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_checkpoint = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_CHECKPOINT, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Devices", - "ao", - NM_CHECKPOINT_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Created", "x", NM_CHECKPOINT_CREATED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("RollbackTimeout", - "u", - NM_CHECKPOINT_ROLLBACK_TIMEOUT), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Devices", "ao", NM_CHECKPOINT_DEVICES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Created", "x", NM_CHECKPOINT_CREATED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RollbackTimeout", + "u", + NM_CHECKPOINT_ROLLBACK_TIMEOUT), ), ), }; static void diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index d457f505..0cbff027 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -10,9 +10,9 @@ #include "nm-config.h" #include "devices/nm-device.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" -#include "nm-keyfile-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-utils.h" /*****************************************************************************/ @@ -26,6 +26,17 @@ typedef struct { gboolean has; GSList * spec; } match_device; + union { + struct { + GSList * allowed_connections; + gboolean allowed_connections_has; + } device; + }; + gboolean is_device; + + /* List of key/value pairs in the section, sorted by key */ + gsize lookup_len; + const NMUtilsNamedValue *lookup_idx; } MatchSectionInfo; struct _NMGlobalDnsDomain { @@ -97,6 +108,8 @@ typedef struct { NMGlobalDnsConfig *global_dns; bool systemd_resolved : 1; + + char *iwd_config_path; } NMConfigDataPrivate; struct _NMConfigData { @@ -114,6 +127,11 @@ G_DEFINE_TYPE(NMConfigData, nm_config_data, G_TYPE_OBJECT) /*****************************************************************************/ +static const char * +_match_section_info_get_str(const MatchSectionInfo *m, GKeyFile *keyfile, const char *property); + +/*****************************************************************************/ + const char * nm_config_data_get_config_main_file(const NMConfigData *self) { @@ -341,12 +359,18 @@ nm_config_data_get_systemd_resolved(const NMConfigData *self) return NM_CONFIG_DATA_GET_PRIVATE(self)->systemd_resolved; } +const char * +nm_config_data_get_iwd_config_path(const NMConfigData *self) +{ + return NM_CONFIG_DATA_GET_PRIVATE(self)->iwd_config_path; +} + gboolean nm_config_data_get_ignore_carrier(const NMConfigData *self, NMDevice *device) { - gs_free char *value = NULL; - gboolean has_match; - int m; + const char *value; + gboolean has_match; + int m; g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); @@ -576,7 +600,7 @@ _merge_keyfiles(GKeyFile *keyfile_user, GKeyFile *keyfile_intern) const char * key = keys[k]; gs_free char *value = NULL; - if (is_atomic && strcmp(key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0) + if (is_atomic && nm_streq(key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS)) continue; if (!is_intern && !is_atomic @@ -684,6 +708,7 @@ static const struct { NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT, NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT}, {NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_DHCP, NM_CONFIG_DEFAULT_MAIN_DHCP}, + {NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_IWD_CONFIG_PATH, ""}, {NM_CONFIG_KEYFILE_GROUP_LOGGING, "backend", NM_CONFIG_DEFAULT_LOGGING_BACKEND}, {NM_CONFIG_KEYFILE_GROUP_LOGGING, "audit", NM_CONFIG_DEFAULT_LOGGING_AUDIT}, }; @@ -1116,7 +1141,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) g_hash_table_insert(dns_config->domains, strdup(name), domain); - if (!strcmp(name, "*")) + if (name[0] == '*' && name[1] == '\0') default_found = TRUE; } @@ -1213,7 +1238,7 @@ global_dns_domain_from_dbus(char *name, GVariant *variant) g_variant_iter_init(&iter, variant); while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) { - if (!g_strcmp0(key, "servers") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { + if (nm_streq0(key, "servers") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); for (i = 0, j = 0; strv && strv[i]; i++) { @@ -1230,7 +1255,7 @@ global_dns_domain_from_dbus(char *name, GVariant *variant) g_strfreev(domain->servers); domain->servers = strv; } - } else if (!g_strcmp0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { + } else if (nm_streq0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); g_strfreev(domain->options); domain->options = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); @@ -1278,10 +1303,10 @@ nm_global_dns_config_from_dbus(const GValue *value, GError **error) g_variant_iter_init(&iter, variant); while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) { - if (!g_strcmp0(key, "searches") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { + if (nm_streq0(key, "searches") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); dns_config->searches = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - } else if (!g_strcmp0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { + } else if (nm_streq0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); @@ -1297,7 +1322,7 @@ nm_global_dns_config_from_dbus(const GValue *value, GError **error) strv[j] = NULL; dns_config->options = strv; } - } else if (!g_strcmp0(key, "domains") + } else if (nm_streq0(key, "domains") && g_variant_is_of_type(val, G_VARIANT_TYPE("a{sv}"))) { NMGlobalDnsDomain *domain; GVariantIter domain_iter; @@ -1381,18 +1406,18 @@ _match_section_infos_lookup(const MatchSectionInfo *match_section_infos, NMDevice * device, const NMPlatformLink * pllink, const char * match_device_type, - char ** out_value) + const char ** out_value) { const char *match_dhcp_plugin; if (!match_section_infos) - return NULL; + goto out; match_dhcp_plugin = nm_dhcp_manager_get_config(nm_dhcp_manager_get()); for (; match_section_infos->group_name; match_section_infos++) { - char * value = NULL; - gboolean match; + const char *value; + gboolean match; /* FIXME: Here we use g_key_file_get_string(). This should be in sync with what keyfile-reader * does. @@ -1401,7 +1426,7 @@ _match_section_infos_lookup(const MatchSectionInfo *match_section_infos, * string_to_value(keyfile_to_string(keyfile)) in one. Optimally, keyfile library would * expose both functions, and we would return here keyfile_to_string(keyfile). * The caller then could convert the string to the proper value via string_to_value(value). */ - value = g_key_file_get_string(keyfile, match_section_infos->group_name, property, NULL); + value = _match_section_info_get_str(match_section_infos, keyfile, property); if (!value && !match_section_infos->stop_match) continue; @@ -1420,15 +1445,17 @@ _match_section_infos_lookup(const MatchSectionInfo *match_section_infos, match = TRUE; if (match) { - *out_value = value; + NM_SET_OUT(out_value, value); return match_section_infos; } - g_free(value); } + +out: + NM_SET_OUT(out_value, NULL); return NULL; } -char * +const char * nm_config_data_get_device_config(const NMConfigData *self, const char * property, NMDevice * device, @@ -1436,7 +1463,7 @@ nm_config_data_get_device_config(const NMConfigData *self, { const NMConfigDataPrivate *priv; const MatchSectionInfo * connection_info; - char * value = NULL; + const char * value; NM_SET_OUT(has_match, FALSE); @@ -1456,7 +1483,7 @@ nm_config_data_get_device_config(const NMConfigData *self, return value; } -char * +const char * nm_config_data_get_device_config_by_pllink(const NMConfigData * self, const char * property, const NMPlatformLink *pllink, @@ -1465,7 +1492,7 @@ nm_config_data_get_device_config_by_pllink(const NMConfigData * self, { const NMConfigDataPrivate *priv; const MatchSectionInfo * connection_info; - char * value = NULL; + const char * value; g_return_val_if_fail(self, NULL); g_return_val_if_fail(property && *property, NULL); @@ -1490,8 +1517,8 @@ nm_config_data_get_device_config_boolean(const NMConfigData *self, int val_no_match, int val_invalid) { - gs_free char *value = NULL; - gboolean has_match; + const char *value; + gboolean has_match; value = nm_config_data_get_device_config(self, property, device, &has_match); if (!has_match) @@ -1499,13 +1526,65 @@ nm_config_data_get_device_config_boolean(const NMConfigData *self, return nm_config_parse_boolean(value, val_invalid); } -char * +gint64 +nm_config_data_get_device_config_int64(const NMConfigData *self, + const char * property, + NMDevice * device, + int base, + gint64 min, + gint64 max, + gint64 val_no_match, + gint64 val_invalid) +{ + const char *value; + gboolean has_match; + + value = nm_config_data_get_device_config(self, property, device, &has_match); + if (!has_match) { + errno = ENOENT; + return val_no_match; + } + return _nm_utils_ascii_str_to_int64(value, base, min, max, val_invalid); +} + +const GSList * +nm_config_data_get_device_allowed_connections_specs(const NMConfigData *self, + NMDevice * device, + gboolean * has_match) +{ + const NMConfigDataPrivate *priv; + const MatchSectionInfo * connection_info; + const GSList * ret = NULL; + + g_return_val_if_fail(self, NULL); + + priv = NM_CONFIG_DATA_GET_PRIVATE(self); + + connection_info = _match_section_infos_lookup(&priv->device_infos[0], + priv->keyfile, + NM_CONFIG_KEYFILE_KEY_DEVICE_ALLOWED_CONNECTIONS, + device, + NULL, + NULL, + NULL); + + if (connection_info) { + nm_assert(connection_info->device.allowed_connections_has); + ret = connection_info->device.allowed_connections; + NM_SET_OUT(has_match, TRUE); + } else + NM_SET_OUT(has_match, FALSE); + + return ret; +} + +const char * nm_config_data_get_connection_default(const NMConfigData *self, const char * property, NMDevice * device) { const NMConfigDataPrivate *priv; - char * value = NULL; + const char * value; g_return_val_if_fail(self, NULL); g_return_val_if_fail(property && *property, NULL); @@ -1544,15 +1623,44 @@ nm_config_data_get_connection_default_int64(const NMConfigData *self, gint64 max, gint64 fallback) { - gs_free char *value = NULL; + const char *value; value = nm_config_data_get_connection_default(self, property, device); return _nm_utils_ascii_str_to_int64(value, 10, min, max, fallback); } +static const char * +_match_section_info_get_str(const MatchSectionInfo *m, GKeyFile *keyfile, const char *property) +{ + gssize idx; + const char *value; + + idx = nm_utils_named_value_list_find(m->lookup_idx, m->lookup_len, property, TRUE); + value = idx >= 0 ? m->lookup_idx[idx].value_str : NULL; + +#if NM_MORE_ASSERTS > 10 + { + gs_free char *value2 = g_key_file_get_string(keyfile, m->group_name, property, NULL); + + nm_assert(nm_streq0(value2, value)); + } +#endif + + return value; +} + static void -_get_connection_info_init(MatchSectionInfo *connection_info, GKeyFile *keyfile, char *group) +_match_section_info_init(MatchSectionInfo *connection_info, + GKeyFile * keyfile, + char * group, + gboolean is_device) { + char ** keys = NULL; + gsize n_keys; + gsize i; + gsize j; + NMUtilsNamedValue *vals; + /* pass ownership of @group on... */ connection_info->group_name = group; @@ -1563,29 +1671,93 @@ _get_connection_info_init(MatchSectionInfo *connection_info, GKeyFile *keyfile, &connection_info->match_device.has); connection_info->stop_match = nm_config_keyfile_get_boolean(keyfile, group, NM_CONFIG_KEYFILE_KEY_STOP_MATCH, FALSE); + + if (is_device) { + connection_info->device.allowed_connections = + nm_config_get_match_spec(keyfile, + group, + NM_CONFIG_KEYFILE_KEY_DEVICE_ALLOWED_CONNECTIONS, + &connection_info->device.allowed_connections_has); + } + + keys = g_key_file_get_keys(keyfile, group, &n_keys, NULL); + nm_utils_strv_sort(keys, n_keys); + + vals = g_new(NMUtilsNamedValue, n_keys); + + for (i = 0, j = 0; i < n_keys; i++) { + gs_free char *key = g_steal_pointer(&keys[i]); + char * value; + + if (NM_IN_STRSET(key, NM_CONFIG_KEYFILE_KEY_STOP_MATCH, NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE)) + continue; + + if (j > 0 && nm_streq(vals[j - 1].name, key)) + continue; + + value = g_key_file_get_string(keyfile, group, key, NULL); + if (!value) + continue; + + vals[j++] = (NMUtilsNamedValue){ + .name = g_steal_pointer(&key), + .value_str = value, + }; + } + + g_free(keys); + + if (n_keys != j) { + gs_free NMUtilsNamedValue *vals2 = vals; + + /* since this buffer will be kept around for a long time, + * get rid of the excess allocation. */ + vals = nm_memdup(vals2, sizeof(NMUtilsNamedValue) * j); + n_keys = j; + } + + if (n_keys == 0) + nm_clear_g_free(&vals); + + connection_info->lookup_idx = vals; + connection_info->lookup_len = n_keys; } static void _match_section_infos_free(MatchSectionInfo *match_section_infos) { - guint i; + MatchSectionInfo *m; + gsize i; if (!match_section_infos) return; - for (i = 0; match_section_infos[i].group_name; i++) { - g_free(match_section_infos[i].group_name); - g_slist_free_full(match_section_infos[i].match_device.spec, g_free); + + for (m = match_section_infos; m->group_name; m++) { + g_free(m->group_name); + g_slist_free_full(m->match_device.spec, g_free); + if (m->is_device) { + g_slist_free_full(m->device.allowed_connections, g_free); + } + for (i = 0; i < m->lookup_len; i++) { + g_free(m->lookup_idx[i].name_mutable); + g_free(m->lookup_idx[i].value_str_mutable); + } + g_free((gpointer) m->lookup_idx); } g_free(match_section_infos); } static MatchSectionInfo * -_match_section_infos_construct(GKeyFile *keyfile, const char *prefix) +_match_section_infos_construct(GKeyFile *keyfile, gboolean is_device) { char ** groups; gsize i, j, ngroups; char * connection_tag = NULL; MatchSectionInfo *match_section_infos = NULL; + const char * prefix; + + prefix = + is_device ? NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE : NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION; /* get the list of existing [connection.\+]/[device.\+] sections. * @@ -1617,13 +1789,17 @@ _match_section_infos_construct(GKeyFile *keyfile, const char *prefix) } match_section_infos = g_new0(MatchSectionInfo, ngroups + 1 + (connection_tag ? 1 : 0)); + match_section_infos->is_device = is_device; for (i = 0; i < ngroups; i++) { /* pass ownership of @group on... */ - _get_connection_info_init(&match_section_infos[i], keyfile, groups[ngroups - i - 1]); + _match_section_info_init(&match_section_infos[i], + keyfile, + groups[ngroups - i - 1], + is_device); } if (connection_tag) { /* pass ownership of @connection_tag on... */ - _get_connection_info_init(&match_section_infos[i], keyfile, connection_tag); + _match_section_info_init(&match_section_infos[i], keyfile, connection_tag, is_device); } g_free(groups); @@ -1644,28 +1820,26 @@ nm_config_data_diff(NMConfigData *old_data, NMConfigData *new_data) priv_old = NM_CONFIG_DATA_GET_PRIVATE(old_data); priv_new = NM_CONFIG_DATA_GET_PRIVATE(new_data); - if (!_nm_keyfile_equals(priv_old->keyfile_user, priv_new->keyfile_user, TRUE)) + if (!_nm_keyfile_equal(priv_old->keyfile_user, priv_new->keyfile_user, TRUE)) changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_USER; - if (!_nm_keyfile_equals(priv_old->keyfile_intern, priv_new->keyfile_intern, TRUE)) + if (!_nm_keyfile_equal(priv_old->keyfile_intern, priv_new->keyfile_intern, TRUE)) changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; - if (g_strcmp0(nm_config_data_get_config_main_file(old_data), - nm_config_data_get_config_main_file(new_data)) - != 0 - || g_strcmp0(nm_config_data_get_config_description(old_data), - nm_config_data_get_config_description(new_data)) - != 0) + if (!nm_streq0(nm_config_data_get_config_main_file(old_data), + nm_config_data_get_config_main_file(new_data)) + || !nm_streq0(nm_config_data_get_config_description(old_data), + nm_config_data_get_config_description(new_data))) changes |= NM_CONFIG_CHANGE_CONFIG_FILES; if (nm_config_data_get_connectivity_enabled(old_data) != nm_config_data_get_connectivity_enabled(new_data) || nm_config_data_get_connectivity_interval(old_data) != nm_config_data_get_connectivity_interval(new_data) - || g_strcmp0(nm_config_data_get_connectivity_uri(old_data), - nm_config_data_get_connectivity_uri(new_data)) - || g_strcmp0(nm_config_data_get_connectivity_response(old_data), - nm_config_data_get_connectivity_response(new_data))) + || !nm_streq0(nm_config_data_get_connectivity_uri(old_data), + nm_config_data_get_connectivity_uri(new_data)) + || !nm_streq0(nm_config_data_get_connectivity_response(old_data), + nm_config_data_get_connectivity_response(new_data))) changes |= NM_CONFIG_CHANGE_CONNECTIVITY; if (nm_utils_g_slist_strlist_cmp(priv_old->no_auto_default.specs, @@ -1676,10 +1850,11 @@ nm_config_data_diff(NMConfigData *old_data, NMConfigData *new_data) != 0) changes |= NM_CONFIG_CHANGE_NO_AUTO_DEFAULT; - if (g_strcmp0(nm_config_data_get_dns_mode(old_data), nm_config_data_get_dns_mode(new_data))) + if (!nm_streq0(nm_config_data_get_dns_mode(old_data), nm_config_data_get_dns_mode(new_data))) changes |= NM_CONFIG_CHANGE_DNS_MODE; - if (g_strcmp0(nm_config_data_get_rc_manager(old_data), nm_config_data_get_rc_manager(new_data))) + if (!nm_streq0(nm_config_data_get_rc_manager(old_data), + nm_config_data_get_rc_manager(new_data))) changes |= NM_CONFIG_CHANGE_RC_MANAGER; if (!global_dns_equal(priv_old->global_dns, priv_new->global_dns)) @@ -1838,10 +2013,8 @@ constructed(GObject *object) priv->keyfile = _merge_keyfiles(priv->keyfile_user, priv->keyfile_intern); - priv->connection_infos = - _match_section_infos_construct(priv->keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); - priv->device_infos = - _match_section_infos_construct(priv->keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); + priv->connection_infos = _match_section_infos_construct(priv->keyfile, FALSE); + priv->device_infos = _match_section_infos_construct(priv->keyfile, TRUE); priv->connectivity.enabled = nm_config_keyfile_get_boolean(priv->keyfile, @@ -1910,6 +2083,12 @@ constructed(GObject *object) if (!priv->global_dns) priv->global_dns = load_global_dns(priv->keyfile_intern, TRUE); + priv->iwd_config_path = + nm_strstrip(g_key_file_get_string(priv->keyfile, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_IWD_CONFIG_PATH, + NULL)); + G_OBJECT_CLASS(nm_config_data_parent_class)->constructed(object); } @@ -1996,6 +2175,8 @@ finalize(GObject *gobject) nm_global_dns_config_free(priv->global_dns); + g_free(priv->iwd_config_path); + _match_section_infos_free(priv->connection_infos); _match_section_infos_free(priv->device_infos); diff --git a/src/core/nm-config-data.h b/src/core/nm-config-data.h index 07cffb43..fa58d869 100644 --- a/src/core/nm-config-data.h +++ b/src/core/nm-config-data.h @@ -6,6 +6,8 @@ #ifndef NM_CONFIG_DATA_H #define NM_CONFIG_DATA_H +#include "libnm-platform/nmp-base.h" + /*****************************************************************************/ typedef enum { @@ -48,71 +50,71 @@ typedef enum { #define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" #define NM_CONFIG_DATA_DNS_MODE "dns" -typedef enum { /*< flags >*/ - NM_CONFIG_GET_VALUE_NONE = 0, +typedef enum { + NM_CONFIG_GET_VALUE_NONE = 0, - /* use g_key_file_get_value() instead of g_key_file_get_string(). */ - NM_CONFIG_GET_VALUE_RAW = (1LL << 0), + /* use g_key_file_get_value() instead of g_key_file_get_string(). */ + NM_CONFIG_GET_VALUE_RAW = (1LL << 0), - /* strip whitespaces */ - NM_CONFIG_GET_VALUE_STRIP = (1LL << 1), + /* strip whitespaces */ + NM_CONFIG_GET_VALUE_STRIP = (1LL << 1), - /* if the returned string would be the empty word, return NULL. */ - NM_CONFIG_GET_VALUE_NO_EMPTY = (1LL << 2), + /* if the returned string would be the empty word, return NULL. */ + NM_CONFIG_GET_VALUE_NO_EMPTY = (1LL << 2), - /* special flag to read device spec. You want to use this before passing the + /* special flag to read device spec. You want to use this before passing the * value to nm_match_spec_split(). */ - NM_CONFIG_GET_VALUE_TYPE_SPEC = NM_CONFIG_GET_VALUE_RAW, + NM_CONFIG_GET_VALUE_TYPE_SPEC = NM_CONFIG_GET_VALUE_RAW, } NMConfigGetValueFlags; -typedef enum { /*< flags >*/ - NM_CONFIG_CHANGE_NONE = 0, +typedef enum { + NM_CONFIG_CHANGE_NONE = 0, - /************************************************************************** + /************************************************************************** * The external cause which triggered the reload/configuration-change *************************************************************************/ - NM_CONFIG_CHANGE_CAUSE_SIGHUP = (1L << 0), - NM_CONFIG_CHANGE_CAUSE_SIGUSR1 = (1L << 1), - NM_CONFIG_CHANGE_CAUSE_SIGUSR2 = (1L << 2), - NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT = (1L << 3), - NM_CONFIG_CHANGE_CAUSE_SET_VALUES = (1L << 4), - NM_CONFIG_CHANGE_CAUSE_CONF = (1L << 5), - NM_CONFIG_CHANGE_CAUSE_DNS_RC = (1L << 6), - NM_CONFIG_CHANGE_CAUSE_DNS_FULL = (1L << 7), + NM_CONFIG_CHANGE_CAUSE_SIGHUP = (1L << 0), + NM_CONFIG_CHANGE_CAUSE_SIGUSR1 = (1L << 1), + NM_CONFIG_CHANGE_CAUSE_SIGUSR2 = (1L << 2), + NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT = (1L << 3), + NM_CONFIG_CHANGE_CAUSE_SET_VALUES = (1L << 4), + NM_CONFIG_CHANGE_CAUSE_CONF = (1L << 5), + NM_CONFIG_CHANGE_CAUSE_DNS_RC = (1L << 6), + NM_CONFIG_CHANGE_CAUSE_DNS_FULL = (1L << 7), - NM_CONFIG_CHANGE_CAUSES = ((1L << 8) - 1), + NM_CONFIG_CHANGE_CAUSES = ((1L << 8) - 1), - /************************************************************************** + /************************************************************************** * Following flags describe which property of the configuration changed: *************************************************************************/ - /* main-file or config-description changed */ - NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 10), + /* main-file or config-description changed */ + NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 10), - /* any configuration on disk changed */ - NM_CONFIG_CHANGE_VALUES = (1L << 11), + /* any configuration on disk changed */ + NM_CONFIG_CHANGE_VALUES = (1L << 11), - /* any user configuration on disk changed (NetworkManager.conf) */ - NM_CONFIG_CHANGE_VALUES_USER = (1L << 12), + /* any user configuration on disk changed (NetworkManager.conf) */ + NM_CONFIG_CHANGE_VALUES_USER = (1L << 12), - /* any internal configuration on disk changed (NetworkManager-intern.conf) */ - NM_CONFIG_CHANGE_VALUES_INTERN = (1L << 13), + /* any internal configuration on disk changed (NetworkManager-intern.conf) */ + NM_CONFIG_CHANGE_VALUES_INTERN = (1L << 13), - /* configuration regarding connectivity changed */ - NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 14), + /* configuration regarding connectivity changed */ + NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 14), - /* configuration regarding no-auto-default changed */ - NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 15), + /* configuration regarding no-auto-default changed */ + NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 15), - /* configuration regarding dns-mode changed */ - NM_CONFIG_CHANGE_DNS_MODE = (1L << 16), + /* configuration regarding dns-mode changed */ + NM_CONFIG_CHANGE_DNS_MODE = (1L << 16), - /* configuration regarding rc-manager changed */ - NM_CONFIG_CHANGE_RC_MANAGER = (1L << 17), + /* configuration regarding rc-manager changed */ + NM_CONFIG_CHANGE_RC_MANAGER = (1L << 17), - /* configuration regarding global dns-config changed */ - NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG = (1L << 18), + /* configuration regarding global dns-config changed */ + NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG = (1L << 18), } NMConfigChangeFlags; @@ -188,6 +190,8 @@ int nm_config_data_get_sriov_num_vfs(const NMConfigData *self, NMDevice *de NMGlobalDnsConfig *nm_config_data_get_global_dns_config(const NMConfigData *self); +const char *nm_config_data_get_iwd_config_path(const NMConfigData *self); + extern const char *__start_connection_defaults[]; extern const char *__stop_connection_defaults[]; @@ -203,9 +207,9 @@ extern const char *__stop_connection_defaults[]; name; \ }) -char *nm_config_data_get_connection_default(const NMConfigData *self, - const char * property, - NMDevice * device); +const char *nm_config_data_get_connection_default(const NMConfigData *self, + const char * property, + NMDevice * device); gint64 nm_config_data_get_connection_default_int64(const NMConfigData *self, const char * property, @@ -214,22 +218,34 @@ gint64 nm_config_data_get_connection_default_int64(const NMConfigData *self, gint64 max, gint64 fallback); -char *nm_config_data_get_device_config(const NMConfigData *self, - const char * property, - NMDevice * device, - gboolean * has_match); +const char *nm_config_data_get_device_config(const NMConfigData *self, + const char * property, + NMDevice * device, + gboolean * has_match); -char *nm_config_data_get_device_config_by_pllink(const NMConfigData * self, - const char * property, - const NMPlatformLink *pllink, - const char * match_device_type, - gboolean * has_match); +const char *nm_config_data_get_device_config_by_pllink(const NMConfigData * self, + const char * property, + const NMPlatformLink *pllink, + const char * match_device_type, + gboolean * has_match); gboolean nm_config_data_get_device_config_boolean(const NMConfigData *self, const char * property, NMDevice * device, int val_no_match, int val_invalid); +gint64 nm_config_data_get_device_config_int64(const NMConfigData *self, + const char * property, + NMDevice * device, + int base, + gint64 min, + gint64 max, + gint64 val_no_match, + gint64 val_invalid); + +const GSList *nm_config_data_get_device_allowed_connections_specs(const NMConfigData *self, + NMDevice * device, + gboolean * has_match); char ** nm_config_data_get_groups(const NMConfigData *self); char ** nm_config_data_get_keys(const NMConfigData *self, const char *group); diff --git a/src/core/nm-config.c b/src/core/nm-config.c index 55323919..817368d1 100644 --- a/src/core/nm-config.c +++ b/src/core/nm-config.c @@ -13,9 +13,9 @@ #include "nm-utils.h" #include "devices/nm-device.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" -#include "nm-keyfile-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-utils.h" #define DEFAULT_CONFIG_MAIN_FILE NMCONFDIR "/NetworkManager.conf" #define DEFAULT_CONFIG_DIR NMCONFDIR "/conf.d" @@ -433,13 +433,7 @@ nm_config_set_no_auto_default_for_device(NMConfig *self, NMDevice *device) len = NM_PTRARRAY_LEN(no_auto_default_current); - idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) no_auto_default_current, - len, - spec, - nm_strcmp_with_data, - NULL, - NULL, - NULL); + idx = nm_utils_strv_find_binary_search(no_auto_default_current, len, spec); if (idx >= 0) { /* @spec is already blocked. We don't have to update our in-memory representation. * Maybe we should write to no_auto_default_file anew, but let's save that too. */ @@ -802,6 +796,7 @@ static gboolean _setting_is_device_spec(const char *group, const char *key) { #define _IS(group_v, key_v) (nm_streq(group, "" group_v "") && nm_streq(key, "" key_v "")) + return _IS(NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_NO_AUTO_DEFAULT) || _IS(NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_IGNORE_CARRIER) || _IS(NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_ASSUME_IPV6LL_ONLY) @@ -812,6 +807,13 @@ _setting_is_device_spec(const char *group, const char *key) && nm_streq(key, NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE)); } +static gboolean +_setting_is_connection_spec(const char *group, const char *key) +{ + return NM_STR_HAS_PREFIX(group, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE) + && nm_streq(key, NM_CONFIG_KEYFILE_KEY_DEVICE_ALLOWED_CONNECTIONS); +} + static gboolean _setting_is_string_list(const char *group, const char *key) { @@ -842,8 +844,10 @@ static const ConfigGroup config_groups[] = { NM_CONFIG_KEYFILE_KEY_MAIN_DEBUG, NM_CONFIG_KEYFILE_KEY_MAIN_DHCP, NM_CONFIG_KEYFILE_KEY_MAIN_DNS, + NM_CONFIG_KEYFILE_KEY_MAIN_FIREWALL_BACKEND, NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE, NM_CONFIG_KEYFILE_KEY_MAIN_IGNORE_CARRIER, + NM_CONFIG_KEYFILE_KEY_MAIN_IWD_CONFIG_PATH, NM_CONFIG_KEYFILE_KEY_MAIN_MONITOR_CONNECTION_FILES, NM_CONFIG_KEYFILE_KEY_MAIN_NO_AUTO_DEFAULT, NM_CONFIG_KEYFILE_KEY_MAIN_PLUGINS, @@ -882,6 +886,8 @@ static const ConfigGroup config_groups[] = { NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER, NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED, NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS, + NM_CONFIG_KEYFILE_KEY_DEVICE_KEEP_CONFIGURATION, + NM_CONFIG_KEYFILE_KEY_DEVICE_ALLOWED_CONNECTIONS, NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_BACKEND, NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_RAND_MAC_ADDRESS, NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_GENERATE_MAC_ADDRESS_MASK, @@ -1063,7 +1069,8 @@ read_config(GKeyFile * keyfile, is_string_list = _setting_is_string_list(group, base_key); - if (is_string_list || _setting_is_device_spec(group, base_key)) { + if (is_string_list || _setting_is_device_spec(group, base_key) + || _setting_is_connection_spec(group, base_key)) { gs_unref_ptrarray GPtrArray *new = g_ptr_array_new_with_free_func(g_free); char ** iter_val; gs_strfreev char **old_val = NULL; @@ -2115,7 +2122,7 @@ nm_config_set_values(NMConfig *self, ""); } - if (!_nm_keyfile_equals(keyfile_intern_current, keyfile_new, TRUE)) + if (!_nm_keyfile_equal(keyfile_intern_current, keyfile_new, TRUE)) new_data = nm_config_data_new_update_keyfile_intern(priv->config_data, keyfile_new); _LOGD("set values(): %s", new_data ? "has changes" : "no changes"); @@ -2347,8 +2354,9 @@ _nm_config_state_set(NMConfig *self, gboolean allow_persist, gboolean force_pers "route-metric-default-aspired" #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE \ "route-metric-default-effective" -#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH "root-path" -#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NEXT_SERVER "next-server" +#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH "root-path" +#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NEXT_SERVER "next-server" +#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_DHCP_BOOTFILE "dhcp-bootfile" static NM_UTILS_LOOKUP_STR_DEFINE( _device_state_managed_type_to_str, @@ -2569,7 +2577,8 @@ nm_config_device_state_write(int ifindex, guint32 route_metric_default_aspired, guint32 route_metric_default_effective, const char * next_server, - const char * root_path) + const char * root_path, + const char * dhcp_bootfile) { char path[NM_STRLEN(NM_CONFIG_DEVICE_STATE_DIR "/") + DEVICE_STATE_FILENAME_LEN_MAX + 1]; GError *local = NULL; @@ -2636,6 +2645,12 @@ nm_config_device_state_write(int ifindex, DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH, root_path); } + if (dhcp_bootfile) { + g_key_file_set_string(kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_DHCP_BOOTFILE, + dhcp_bootfile); + } if (!g_key_file_save_to_file(kf, path, &local)) { _LOGW("device-state: write #%d (%s) failed: %s", ifindex, path, local->message); @@ -2643,7 +2658,9 @@ nm_config_device_state_write(int ifindex, return FALSE; } _LOGT("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, " - "route-metric-default=%" G_GUINT32_FORMAT "-%" G_GUINT32_FORMAT "%s%s%s%s%s%s", + "route-metric-default=%" G_GUINT32_FORMAT "-%" G_GUINT32_FORMAT "%s%s%s" + "%s%s%s" + "%s%s%s", ifindex, path, _device_state_managed_type_to_str(managed), @@ -2652,7 +2669,8 @@ nm_config_device_state_write(int ifindex, route_metric_default_aspired, route_metric_default_effective, NM_PRINT_FMT_QUOTED(next_server, ", next-server=", next_server, "", ""), - NM_PRINT_FMT_QUOTED(root_path, ", root-path=", root_path, "", "")); + NM_PRINT_FMT_QUOTED(root_path, ", root-path=", root_path, "", ""), + NM_PRINT_FMT_QUOTED(dhcp_bootfile, ", dhcp-bootfile=", dhcp_bootfile, "", "")); return TRUE; } @@ -3149,7 +3167,7 @@ nm_config_class_init(NMConfigClass *config_class) NM_TYPE_CONFIG_DATA); G_STATIC_ASSERT_EXPR(sizeof(guint) == sizeof(NMConfigChangeFlags)); - G_STATIC_ASSERT_EXPR(((gint64)((NMConfigChangeFlags) -1)) > ((gint64) 0)); + G_STATIC_ASSERT_EXPR(((gint64) ((NMConfigChangeFlags) -1)) > ((gint64) 0)); } static void diff --git a/src/core/nm-config.h b/src/core/nm-config.h index 6f3f514c..8279f4d2 100644 --- a/src/core/nm-config.h +++ b/src/core/nm-config.h @@ -9,6 +9,8 @@ #include "nm-config-data.h" +#include "libnm-base/nm-config-base.h" + #define NM_TYPE_CONFIG (nm_config_get_type()) #define NM_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_CONFIG, NMConfig)) #define NM_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_CONFIG, NMConfigClass)) @@ -26,84 +28,6 @@ #define NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL 300 #define NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE "NetworkManager is online" /* NOT LOCALIZED */ -#define NM_CONFIG_KEYFILE_LIST_SEPARATOR ',' - -#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN ".intern." -#define NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION "connection" -#define NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE "device" -#define NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN "global-dns-domain-" -#define NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST ".test-append-stringlist" - -#define NM_CONFIG_KEYFILE_GROUP_MAIN "main" -#define NM_CONFIG_KEYFILE_GROUP_LOGGING "logging" -#define NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY "connectivity" -#define NM_CONFIG_KEYFILE_GROUP_KEYFILE "keyfile" -#define NM_CONFIG_KEYFILE_GROUP_IFUPDOWN "ifupdown" -#define NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS "global-dns" -#define NM_CONFIG_KEYFILE_GROUP_CONFIG ".config" - -#define NM_CONFIG_KEYFILE_KEY_MAIN_ASSUME_IPV6LL_ONLY "assume-ipv6ll-only" -#define NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT "auth-polkit" -#define NM_CONFIG_KEYFILE_KEY_MAIN_AUTOCONNECT_RETRIES_DEFAULT "autoconnect-retries-default" -#define NM_CONFIG_KEYFILE_KEY_MAIN_CONFIGURE_AND_QUIT "configure-and-quit" -#define NM_CONFIG_KEYFILE_KEY_MAIN_DEBUG "debug" -#define NM_CONFIG_KEYFILE_KEY_MAIN_DHCP "dhcp" -#define NM_CONFIG_KEYFILE_KEY_MAIN_DNS "dns" -#define NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE "hostname-mode" -#define NM_CONFIG_KEYFILE_KEY_MAIN_IGNORE_CARRIER "ignore-carrier" -#define NM_CONFIG_KEYFILE_KEY_MAIN_MONITOR_CONNECTION_FILES "monitor-connection-files" -#define NM_CONFIG_KEYFILE_KEY_MAIN_NO_AUTO_DEFAULT "no-auto-default" -#define NM_CONFIG_KEYFILE_KEY_MAIN_PLUGINS "plugins" -#define NM_CONFIG_KEYFILE_KEY_MAIN_RC_MANAGER "rc-manager" -#define NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER "slaves-order" -#define NM_CONFIG_KEYFILE_KEY_MAIN_SYSTEMD_RESOLVED "systemd-resolved" - -#define NM_CONFIG_KEYFILE_KEY_LOGGING_AUDIT "audit" -#define NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND "backend" -#define NM_CONFIG_KEYFILE_KEY_LOGGING_DOMAINS "domains" -#define NM_CONFIG_KEYFILE_KEY_LOGGING_LEVEL "level" - -#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_ENABLED "enabled" -#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_INTERVAL "interval" -#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_RESPONSE "response" -#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_URI "uri" - -#define NM_CONFIG_KEYFILE_KEY_KEYFILE_PATH "path" -#define NM_CONFIG_KEYFILE_KEY_KEYFILE_UNMANAGED_DEVICES "unmanaged-devices" -#define NM_CONFIG_KEYFILE_KEY_KEYFILE_HOSTNAME "hostname" - -#define NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED "managed" - -#define NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_SEARCHES "searches" -#define NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_OPTIONS "options" - -#define NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_DOMAIN_SERVERS "servers" -#define NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_DOMAIN_OPTIONS "options" - -#define NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED "managed" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER "ignore-carrier" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS "sriov-num-vfs" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_BACKEND "wifi.backend" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_RAND_MAC_ADDRESS "wifi.scan-rand-mac-address" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_GENERATE_MAC_ADDRESS_MASK \ - "wifi.scan-generate-mac-address-mask" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT "carrier-wait-timeout" -#define NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_IWD_AUTOCONNECT "wifi.iwd.autoconnect" - -#define NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE "match-device" -#define NM_CONFIG_KEYFILE_KEY_STOP_MATCH "stop-match" - -#define NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS ".was" /* check-config-options skip */ -#define NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE "enable" /* check-config-options skip */ - -#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was." -#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set." - -#define NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS \ - NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS -#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN \ - NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN - typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; typedef enum { @@ -261,7 +185,8 @@ gboolean nm_config_device_state_write(int guint32 route_metric_default_aspired, guint32 route_metric_default_effective, const char * next_server, - const char * root_path); + const char * root_path, + const char * dhcp_bootfile); void nm_config_device_state_prune_stale(GHashTable *preserve_ifindexes, NMPlatform *preserve_in_platform); diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c index f847c8f4..85d41b49 100644 --- a/src/core/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -16,7 +16,7 @@ #include #include "c-list/src/c-list.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #include "NetworkManagerUtils.h" #include "nm-dbus-manager.h" @@ -572,7 +572,7 @@ easy_write_cb(void *buffer, size_t size, size_t nmemb, void *userdata) * Continue receiving... */ cb_data->concheck.response_good_cnt += len; - if (cb_data->concheck.response_good_cnt > (gsize)(100 * 1024)) { + if (cb_data->concheck.response_good_cnt > (gsize) (100 * 1024)) { /* we expect an empty response. We accept either * 1) status code 204 and any response * 2) status code 200 and an empty response. @@ -764,7 +764,7 @@ resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data) } #endif -#define SD_RESOLVED_DNS ((guint64)(1LL << 0)) +#define SD_RESOLVED_DNS ((guint64) (1LL << 0)) static NMConnectivityState check_platform_config(NMConnectivity *self, @@ -904,7 +904,7 @@ nm_connectivity_check_start(NMConnectivity * self, * This is relatively cumbersome to avoid, because we would have to go through * NMDnsSystemdResolved trying to asynchronously start the service, to ensure there * is only one attempt to start the service. */ - has_systemd_resolved = nm_dns_manager_has_systemd_resolved(nm_dns_manager_get()); + has_systemd_resolved = !!nm_dns_manager_get_systemd_resolved(nm_dns_manager_get()); if (has_systemd_resolved) { GDBusConnection *dbus_connection; diff --git a/src/core/nm-connectivity.h b/src/core/nm-connectivity.h index c67668ce..0985df97 100644 --- a/src/core/nm-connectivity.h +++ b/src/core/nm-connectivity.h @@ -8,6 +8,7 @@ #define __NETWORKMANAGER_CONNECTIVITY_H__ #include "nm-dbus-interface.h" +#include "libnm-platform/nmp-base.h" /*****************************************************************************/ diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index a27c50dc..8fdc7379 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -22,13 +22,16 @@ #include #include -#include "nm-std-aux/unaligned.h" -#include "nm-glib-aux/nm-random-utils.h" -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-glib-aux/nm-time-utils.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-platform/nmp-base.h" +#include "libnm-std-aux/unaligned.h" +#include "libnm-glib-aux/nm-random-utils.h" +#include "libnm-glib-aux/nm-io-utils.h" +#include "libnm-glib-aux/nm-secret-utils.h" +#include "libnm-glib-aux/nm-time-utils.h" +#include "libnm-glib-aux/nm-str-buf.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-connection.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" @@ -156,37 +159,6 @@ _nm_singleton_instance_register_destruction(GObject *instance) /*****************************************************************************/ -static double -_exp10(guint16 ex) -{ - double v; - - if (ex == 0) - return 1.0; - - v = _exp10(ex / 2); - v = v * v; - if (ex % 2) - v *= 10; - return v; -} - -/* - * nm_utils_exp10: - * @ex: the exponent - * - * Returns: 10^ex, or pow(10, ex), or exp10(ex). - */ -double -nm_utils_exp10(gint16 ex) -{ - if (ex >= 0) - return _exp10(ex); - return 1.0 / _exp10(-((gint32) ex)); -} - -/*****************************************************************************/ - gboolean nm_ether_addr_is_valid(const NMEtherAddr *addr) { @@ -304,85 +276,6 @@ nm_utils_array_remove_at_indexes(GArray *array, const guint *indexes_to_delete, g_array_set_size(array, res_length); } -static const char * -_trunk_first_line(char *str) -{ - char *s; - - s = strchr(str, '\n'); - if (s) - s[0] = '\0'; - return str; -} - -int -nm_utils_modprobe(GError **error, gboolean suppress_error_logging, const char *arg1, ...) -{ - gs_unref_ptrarray GPtrArray *argv = NULL; - int exit_status; - gs_free char * _log_str = NULL; -#define ARGV_TO_STR(argv) \ - (_log_str ? _log_str : (_log_str = g_strjoinv(" ", (char **) argv->pdata))) - GError * local = NULL; - va_list ap; - NMLogLevel llevel = suppress_error_logging ? LOGL_DEBUG : LOGL_ERR; - gs_free char *std_out = NULL, *std_err = NULL; - - g_return_val_if_fail(!error || !*error, -1); - g_return_val_if_fail(arg1, -1); - - /* construct the argument list */ - argv = g_ptr_array_sized_new(4); - g_ptr_array_add(argv, "/sbin/modprobe"); - g_ptr_array_add(argv, "--use-blacklist"); - g_ptr_array_add(argv, (char *) arg1); - - va_start(ap, arg1); - while ((arg1 = va_arg(ap, const char *))) - g_ptr_array_add(argv, (char *) arg1); - va_end(ap); - - g_ptr_array_add(argv, NULL); - - nm_log_dbg(LOGD_CORE, "modprobe: '%s'", ARGV_TO_STR(argv)); - if (!g_spawn_sync(NULL, - (char **) argv->pdata, - NULL, - 0, - NULL, - NULL, - &std_out, - &std_err, - &exit_status, - &local)) { - nm_log(llevel, - LOGD_CORE, - NULL, - NULL, - "modprobe: '%s' failed: %s", - ARGV_TO_STR(argv), - local->message); - g_propagate_error(error, local); - return -1; - } else if (exit_status != 0) { - nm_log(llevel, - LOGD_CORE, - NULL, - NULL, - "modprobe: '%s' exited with error %d%s%s%s%s%s%s", - ARGV_TO_STR(argv), - exit_status, - std_out && *std_out ? " (" : "", - std_out && *std_out ? _trunk_first_line(std_out) : "", - std_out && *std_out ? ")" : "", - std_err && *std_err ? " (" : "", - std_err && *std_err ? _trunk_first_line(std_err) : "", - std_err && *std_err ? ")" : ""); - } - - return exit_status; -} - /*****************************************************************************/ typedef struct { @@ -693,9 +586,10 @@ static gulong _sleep_duration_convert_ms_to_us(guint32 sleep_duration_msec) { if (sleep_duration_msec > 0) { - guint64 x = (gint64) sleep_duration_msec * (guint64) 1000L; + guint64 x = ((guint64) sleep_duration_msec) * 1000UL; - return x < G_MAXULONG ? (gulong) x : G_MAXULONG; + nm_assert(x < G_MAXULONG); + return x; } return G_USEC_PER_SEC / 20; } @@ -1269,7 +1163,7 @@ typedef struct { const char *value; gboolean is_parsed; guint len; - guint8 bin[NM_UTILS_HWADDR_LEN_MAX]; + guint8 bin[_NM_UTILS_HWADDR_LEN_MAX]; } hwaddr; struct { const char *value; @@ -1590,6 +1484,112 @@ nm_match_spec_device(const GSList *specs, return _match_result(has_except, has_not_except, has_match, has_match_except); } +typedef struct { + const char *uuid; + const char *id; + const char *origin; +} MatchConnectionData; + +static gboolean +match_connection_eval(const char *spec_str, const MatchConnectionData *match_data) +{ + if (spec_str[0] == '*' && spec_str[1] == '\0') + return TRUE; + + if (_MATCH_CHECK(spec_str, "id:")) + return nm_streq0(spec_str, match_data->id); + + if (_MATCH_CHECK(spec_str, "uuid:")) + return nm_streq0(spec_str, match_data->uuid); + + if (_MATCH_CHECK(spec_str, "origin:")) + return nm_streq0(spec_str, match_data->origin); + + return FALSE; +} + +static NMMatchSpecMatchType +match_spec_connection(const GSList *specs, const char *id, const char *uuid, const char *origin) +{ + const GSList * iter; + gboolean has_match = FALSE; + gboolean has_match_except = FALSE; + gboolean has_except = FALSE; + gboolean has_not_except = FALSE; + const char * spec_str; + const MatchConnectionData match_data = { + .id = nm_str_not_empty(id), + .uuid = nm_str_not_empty(uuid), + .origin = nm_str_not_empty(origin), + }; + + if (!specs) + return NM_MATCH_SPEC_NO_MATCH; + + for (iter = specs; iter; iter = iter->next) { + gboolean except; + + spec_str = iter->data; + + if (!spec_str || !*spec_str) + continue; + + spec_str = match_except(spec_str, &except); + + if (except) + has_except = TRUE; + else + has_not_except = TRUE; + + if ((except && has_match_except) || (!except && has_match)) { + /* evaluating the match does not give new information. Skip it. */ + continue; + } + + if (!match_connection_eval(spec_str, &match_data)) + continue; + + if (except) + has_match_except = TRUE; + else + has_match = TRUE; + } + + return _match_result(has_except, has_not_except, has_match, has_match_except); +} + +int +nm_utils_connection_match_spec_list(NMConnection *connection, + const GSList *specs, + int no_match_value) +{ + NMMatchSpecMatchType m; + NMSettingUser * s_user; + const char * origin = NULL; + + if (!specs) + return no_match_value; + + s_user = _nm_connection_get_setting(connection, NM_TYPE_SETTING_USER); + if (s_user) + origin = nm_setting_user_get_data(s_user, NM_USER_TAG_ORIGIN); + + m = match_spec_connection(specs, + nm_connection_get_id(connection), + nm_connection_get_uuid(connection), + origin); + switch (m) { + case NM_MATCH_SPEC_MATCH: + return TRUE; + case NM_MATCH_SPEC_NEG_MATCH: + return FALSE; + case NM_MATCH_SPEC_NO_MATCH: + return no_match_value; + } + nm_assert_not_reached(); + return no_match_value; +} + static gboolean match_config_eval(const char *str, const char *tag, guint cur_nm_version) { @@ -2052,65 +2052,6 @@ nm_utils_kernel_cmdline_match_check(const char *const *proc_cmdline, /*****************************************************************************/ -char * -nm_utils_new_vlan_name(const char *parent_iface, guint32 vlan_id) -{ - guint id_len; - gsize parent_len; - char *ifname; - - g_return_val_if_fail(parent_iface && *parent_iface, NULL); - - if (vlan_id < 10) - id_len = 2; - else if (vlan_id < 100) - id_len = 3; - else if (vlan_id < 1000) - id_len = 4; - else { - g_return_val_if_fail(vlan_id < 4095, NULL); - id_len = 5; - } - - ifname = g_new(char, IFNAMSIZ); - - parent_len = strlen(parent_iface); - parent_len = MIN(parent_len, IFNAMSIZ - 1 - id_len); - memcpy(ifname, parent_iface, parent_len); - g_snprintf(&ifname[parent_len], IFNAMSIZ - parent_len, ".%u", vlan_id); - - return ifname; -} - -/* nm_utils_new_infiniband_name: - * @name: the output-buffer where the value will be written. Must be - * not %NULL and point to a string buffer of at least IFNAMSIZ bytes. - * @parent_name: the parent interface name - * @p_key: the partition key. - * - * Returns: the infiniband name will be written to @name and @name - * is returned. - */ -const char * -nm_utils_new_infiniband_name(char *name, const char *parent_name, int p_key) -{ - g_return_val_if_fail(name, NULL); - g_return_val_if_fail(parent_name && parent_name[0], NULL); - g_return_val_if_fail(strlen(parent_name) < IFNAMSIZ, NULL); - - /* technically, p_key of 0x0000 and 0x8000 is not allowed either. But we don't - * want to assert against that in nm_utils_new_infiniband_name(). So be more - * resilient here, and accept those. */ - g_return_val_if_fail(p_key >= 0 && p_key <= 0xffff, NULL); - - /* If parent+suffix is too long, kernel would just truncate - * the name. We do the same. See ipoib_vlan_add(). */ - g_snprintf(name, IFNAMSIZ, "%s.%04x", parent_name, p_key); - return name; -} - -/*****************************************************************************/ - /** * nm_utils_cmp_connection_by_autoconnect_priority: * @a: @@ -2539,134 +2480,6 @@ out: g_array_free(sorted_hashes, TRUE); } -#define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/" -#define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/" -G_STATIC_ASSERT(sizeof(IPV4_PROPERTY_DIR) == sizeof(IPV6_PROPERTY_DIR)); -G_STATIC_ASSERT(NM_STRLEN(IPV6_PROPERTY_DIR) + IFNAMSIZ + 60 - == NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE); - -/** - * nm_utils_sysctl_ip_conf_path: - * @addr_family: either AF_INET or AF_INET6. - * @buf: the output buffer where to write the path. It - * must be at least NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE bytes - * long. - * @ifname: an interface name - * @property: a property name - * - * Returns: the path to IPv6 property @property on @ifname. Note that - * this returns the input argument @buf. - */ -const char * -nm_utils_sysctl_ip_conf_path(int addr_family, char *buf, const char *ifname, const char *property) -{ - int len; - - nm_assert(buf); - nm_assert_addr_family(addr_family); - - g_assert(nm_utils_ifname_valid_kernel(ifname, NULL)); - property = NM_ASSERT_VALID_PATH_COMPONENT(property); - - len = g_snprintf(buf, - NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE, - "%s%s/%s", - addr_family == AF_INET6 ? IPV6_PROPERTY_DIR : IPV4_PROPERTY_DIR, - ifname, - property); - g_assert(len < NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE - 1); - return buf; -} - -gboolean -nm_utils_sysctl_ip_conf_is_path(int addr_family, - const char *path, - const char *ifname, - const char *property) -{ - g_return_val_if_fail(path, FALSE); - NM_ASSERT_VALID_PATH_COMPONENT(property); - g_assert(!ifname || nm_utils_ifname_valid_kernel(ifname, NULL)); - - if (addr_family == AF_INET) { - if (!g_str_has_prefix(path, IPV4_PROPERTY_DIR)) - return FALSE; - path += NM_STRLEN(IPV4_PROPERTY_DIR); - } else if (addr_family == AF_INET6) { - if (!g_str_has_prefix(path, IPV6_PROPERTY_DIR)) - return FALSE; - path += NM_STRLEN(IPV6_PROPERTY_DIR); - } else - g_return_val_if_reached(FALSE); - - if (ifname) { - if (!g_str_has_prefix(path, ifname)) - return FALSE; - path += strlen(ifname); - if (path[0] != '/') - return FALSE; - path++; - } else { - const char *slash; - char buf[IFNAMSIZ]; - gsize l; - - slash = strchr(path, '/'); - if (!slash) - return FALSE; - l = slash - path; - if (l >= IFNAMSIZ) - return FALSE; - memcpy(buf, path, l); - buf[l] = '\0'; - if (!nm_utils_ifname_valid_kernel(buf, NULL)) - return FALSE; - path = slash + 1; - } - - if (!nm_streq(path, property)) - return FALSE; - - return TRUE; -} - -gboolean -nm_utils_is_valid_path_component(const char *name) -{ - const char *n; - - if (name == NULL || name[0] == '\0') - return FALSE; - - if (name[0] == '.') { - if (name[1] == '\0') - return FALSE; - if (name[1] == '.' && name[2] == '\0') - return FALSE; - } - n = name; - do { - if (*n == '/') - return FALSE; - } while (*(++n) != '\0'); - - return TRUE; -} - -const char * -NM_ASSERT_VALID_PATH_COMPONENT(const char *name) -{ - if (G_LIKELY(nm_utils_is_valid_path_component(name))) - return name; - - nm_log_err(LOGD_CORE, - "Failed asserting path component: %s%s%s", - NM_PRINT_FMT_QUOTED(name, "\"", name, "\"", "(null)")); - g_error("FATAL: Failed asserting path component: %s%s%s", - NM_PRINT_FMT_QUOTED(name, "\"", name, "\"", "(null)")); - g_assert_not_reached(); -} - /*****************************************************************************/ typedef struct { @@ -2698,7 +2511,7 @@ _uuid_data_init(UuidData *uuid_data, gboolean packed, gboolean is_fake, const NM nm_utils_bin2hexstr_full(uuid, sizeof(*uuid), '\0', FALSE, uuid_data->str); } else { G_STATIC_ASSERT_EXPR(sizeof(uuid_data->str) >= 37); - _nm_utils_uuid_unparse(uuid, uuid_data->str); + nm_uuid_unparse(uuid, uuid_data->str); } return uuid_data; } @@ -2751,7 +2564,7 @@ again: (guint8 *) &uuid, sizeof(uuid), NULL)) { - if (!nm_utils_uuid_is_null(&uuid)) { + if (!nm_uuid_is_null(&uuid)) { /* an all-zero machine-id is not valid. */ is_fake = FALSE; } @@ -2796,11 +2609,11 @@ again: /* the fake machine-id is based on secret-key/boot-id, but we hash it * again, so that they are not literally the same. */ - nm_utils_uuid_generate_from_string_bin(&uuid, - (const char *) seed_bin, - seed_len, - NM_UTILS_UUID_TYPE_VERSION5, - (gpointer) hash_seed); + nm_uuid_generate_from_string(&uuid, + (const char *) seed_bin, + seed_len, + NM_UUID_TYPE_VERSION5, + (gpointer) hash_seed); } if (!g_once_init_enter(&lock)) @@ -2885,7 +2698,7 @@ _host_id_read_timestamp(gboolean use_secret_key_file, now = time(NULL); *out_timestamp_ns = NM_MAX((gint64) 1, - (now * NM_UTILS_NSEC_PER_SEC) - ((gint64)(v % ((guint64)(EPOCH_TWO_YEARS))))); + (now * NM_UTILS_NSEC_PER_SEC) - ((gint64) (v % ((guint64) (EPOCH_TWO_YEARS))))); return FALSE; } @@ -3028,6 +2841,7 @@ _host_id_read(guint8 **out_host_id, gsize *out_host_id_len) len, 0600, NULL, + NULL, &error)) { nm_log_warn( LOGD_CORE, @@ -3149,10 +2963,10 @@ again: NULL, NULL, NULL); - if (!contents || !_nm_utils_uuid_parse(nm_strstrip(contents), &uuid)) { + if (!contents || !nm_uuid_parse(nm_strstrip(contents), &uuid)) { /* generate a random UUID instead. */ is_fake = TRUE; - _nm_utils_uuid_generate_random(&uuid); + nm_uuid_generate_random(&uuid); } if (!g_once_init_enter(&lock)) @@ -3408,89 +3222,6 @@ nm_utils_get_ipv6_interface_identifier(NMLinkType link_type, /*****************************************************************************/ -/** - * nm_utils_ipv6_addr_set_interface_identifier: - * @addr: output token encoded as %in6_addr - * @iid: %NMUtilsIPv6IfaceId interface identifier - * - * Converts the %NMUtilsIPv6IfaceId to an %in6_addr (suitable for use - * with Linux platform). This only copies the lower 8 bytes, ignoring - * the /64 network prefix which is expected to be all-zero for a valid - * token. - */ -void -nm_utils_ipv6_addr_set_interface_identifier(struct in6_addr *addr, const NMUtilsIPv6IfaceId iid) -{ - memcpy(addr->s6_addr + 8, &iid.id_u8, 8); -} - -/** - * nm_utils_ipv6_interface_identifier_get_from_addr: - * @iid: output %NMUtilsIPv6IfaceId interface identifier set from the token - * @addr: token encoded as %in6_addr - * - * Converts the %in6_addr encoded token (as used by Linux platform) to - * the interface identifier. - */ -void -nm_utils_ipv6_interface_identifier_get_from_addr(NMUtilsIPv6IfaceId * iid, - const struct in6_addr *addr) -{ - memcpy(iid, addr->s6_addr + 8, 8); -} - -/** - * nm_utils_ipv6_interface_identifier_get_from_token: - * @iid: output %NMUtilsIPv6IfaceId interface identifier set from the token - * @token: token encoded as string - * - * Converts the %in6_addr encoded token (as used in ip6 settings) to - * the interface identifier. - * - * Returns: %TRUE if the @token is a valid token, %FALSE otherwise - */ -gboolean -nm_utils_ipv6_interface_identifier_get_from_token(NMUtilsIPv6IfaceId *iid, const char *token) -{ - struct in6_addr i6_token; - - g_return_val_if_fail(token, FALSE); - - if (!inet_pton(AF_INET6, token, &i6_token)) - return FALSE; - - if (!_nm_utils_inet6_is_token(&i6_token)) - return FALSE; - - nm_utils_ipv6_interface_identifier_get_from_addr(iid, &i6_token); - return TRUE; -} - -/** - * nm_utils_inet6_interface_identifier_to_token: - * @iid: %NMUtilsIPv6IfaceId interface identifier - * @buf: the destination buffer of at least %NM_UTILS_INET_ADDRSTRLEN - * bytes. - * - * Converts the interface identifier to a string token. - * - * Returns: the input buffer filled with the id as string. - */ -const char * -nm_utils_inet6_interface_identifier_to_token(NMUtilsIPv6IfaceId iid, - char buf[static INET6_ADDRSTRLEN]) -{ - struct in6_addr i6_token = {.s6_addr = { - 0, - }}; - - nm_assert(buf); - nm_utils_ipv6_addr_set_interface_identifier(&i6_token, iid); - return _nm_utils_inet6_ntop(&i6_token, buf); -} - -/*****************************************************************************/ - char * nm_utils_stable_id_random(void) { @@ -4270,89 +4001,6 @@ nm_utils_g_value_set_strv(GValue *value, GPtrArray *strings) /*****************************************************************************/ -/** - * Takes a pair @timestamp and @duration, and returns the remaining duration based - * on the new timestamp @now. - */ -guint32 -nm_utils_lifetime_rebase_relative_time_on_now(guint32 timestamp, guint32 duration, gint32 now) -{ - gint64 t; - - nm_assert(now >= 0); - - if (duration == NM_PLATFORM_LIFETIME_PERMANENT) - return NM_PLATFORM_LIFETIME_PERMANENT; - - if (timestamp == 0) { - /* if the @timestamp is zero, assume it was just left unset and that the relative - * @duration starts counting from @now. This is convenient to construct an address - * and print it in nm_platform_ip4_address_to_string(). - * - * In general it does not make sense to set the @duration without anchoring at - * @timestamp because you don't know the absolute expiration time when looking - * at the address at a later moment. */ - timestamp = now; - } - - /* For timestamp > now, just accept it and calculate the expected(?) result. */ - t = (gint64) timestamp + (gint64) duration - (gint64) now; - - if (t <= 0) - return 0; - if (t >= NM_PLATFORM_LIFETIME_PERMANENT) - return NM_PLATFORM_LIFETIME_PERMANENT - 1; - return t; -} - -guint32 -nm_utils_lifetime_get(guint32 timestamp, - guint32 lifetime, - guint32 preferred, - gint32 now, - guint32 *out_preferred) -{ - guint32 t_lifetime, t_preferred; - - nm_assert(now >= 0); - - if (timestamp == 0 && lifetime == 0) { - /* We treat lifetime==0 && timestamp==0 addresses as permanent addresses to allow easy - * creation of such addresses (without requiring to set the lifetime fields to - * NM_PLATFORM_LIFETIME_PERMANENT). The real lifetime==0 addresses (E.g. DHCP6 telling us - * to drop an address will have timestamp set. - */ - NM_SET_OUT(out_preferred, NM_PLATFORM_LIFETIME_PERMANENT); - g_return_val_if_fail(preferred == 0, NM_PLATFORM_LIFETIME_PERMANENT); - return NM_PLATFORM_LIFETIME_PERMANENT; - } - - if (now <= 0) - now = nm_utils_get_monotonic_timestamp_sec(); - - t_lifetime = nm_utils_lifetime_rebase_relative_time_on_now(timestamp, lifetime, now); - if (!t_lifetime) { - NM_SET_OUT(out_preferred, 0); - return 0; - } - - t_preferred = nm_utils_lifetime_rebase_relative_time_on_now(timestamp, preferred, now); - - NM_SET_OUT(out_preferred, MIN(t_preferred, t_lifetime)); - - /* Assert that non-permanent addresses have a (positive) @timestamp. nm_utils_lifetime_rebase_relative_time_on_now() - * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always - * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. - */ - g_return_val_if_fail(timestamp != 0 - || (lifetime == NM_PLATFORM_LIFETIME_PERMANENT - && preferred == NM_PLATFORM_LIFETIME_PERMANENT), - t_lifetime); - g_return_val_if_fail(t_preferred <= t_lifetime, t_lifetime); - - return t_lifetime; -} - const char * nm_utils_dnsmasq_status_to_string(int status, char *dest, gsize size) { @@ -5106,16 +4754,329 @@ nm_wifi_utils_level_to_quality(int val) /*****************************************************************************/ -NM_UTILS_ENUM2STR_DEFINE(nm_icmpv6_router_pref_to_string, - NMIcmpv6RouterPref, - NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_LOW, "low"), - NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_MEDIUM, "medium"), - NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_HIGH, "high"), - NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_INVALID, "invalid"), ); - NM_UTILS_LOOKUP_STR_DEFINE(nm_activation_type_to_string, NMActivationType, NM_UTILS_LOOKUP_DEFAULT_WARN("(unknown)"), NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVATION_TYPE_MANAGED, "managed"), NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVATION_TYPE_ASSUME, "assume"), NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVATION_TYPE_EXTERNAL, "external"), ); + +/*****************************************************************************/ + +typedef struct { + GPid pid; + GTask * task; + gulong cancellable_id; + GSource *child_watch_source; + GSource *timeout_source; + + int child_stdin; + int child_stdout; + GSource *input_source; + GSource *output_source; + + NMStrBuf in_buffer; + NMStrBuf out_buffer; + gsize out_buffer_offset; +} HelperInfo; + +#define _NMLOG_PREFIX_NAME "helper" +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG2(level, info, ...) \ + G_STMT_START \ + { \ + if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \ + HelperInfo *_info = (info); \ + \ + _nm_log((level), \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ + _NMLOG_PREFIX_NAME "[" NM_HASH_OBFUSCATE_PTR_FMT \ + ",%d]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_HASH_OBFUSCATE_PTR(_info), \ + _info->pid _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +static void +helper_info_free(gpointer data) +{ + HelperInfo *info = data; + + nm_clear_g_source_inst(&info->child_watch_source); + nm_clear_g_source_inst(&info->timeout_source); + g_object_unref(info->task); + + nm_str_buf_destroy(&info->in_buffer); + nm_str_buf_destroy(&info->out_buffer); + nm_clear_g_source_inst(&info->input_source); + nm_clear_g_source_inst(&info->output_source); + + if (info->child_stdout != -1) + nm_close(info->child_stdout); + if (info->child_stdin != -1) + nm_close(info->child_stdin); + + if (info->pid != -1) { + nm_assert(info->pid > 1); + nm_utils_kill_child_async(info->pid, SIGKILL, LOGD_CORE, _NMLOG_PREFIX_NAME, 0, NULL, NULL); + } + + g_free(info); +} + +static void +helper_complete(HelperInfo *info, GError *error) +{ + if (error) { + nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task), + &info->cancellable_id); + g_task_return_error(info->task, error); + helper_info_free(info); + return; + } + + if (info->input_source || info->output_source || info->pid != -1) { + /* Wait that pipes are closed and process has terminated */ + return; + } + + nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task), &info->cancellable_id); + g_task_return_pointer(info->task, nm_str_buf_finalize(&info->in_buffer, NULL), g_free); + helper_info_free(info); +} + +static gboolean +helper_can_write(int fd, GIOCondition condition, gpointer user_data) +{ + HelperInfo *info = user_data; + gssize n_written; + int errsv; + + if (NM_FLAGS_HAS(condition, G_IO_ERR)) { + errsv = EIO; + goto out_error; + } else if (NM_FLAGS_HAS(condition, G_IO_HUP)) { + errsv = EPIPE; + goto out_error; + } + + n_written = write(info->child_stdin, + &((nm_str_buf_get_str_unsafe(&info->out_buffer))[info->out_buffer_offset]), + info->out_buffer.len - info->out_buffer_offset); + errsv = errno; + + if (n_written < 0 && errsv != EAGAIN) + goto out_error; + + if (n_written > 0) { + if ((gsize) n_written >= (info->out_buffer.len - info->out_buffer_offset)) { + nm_assert((gsize) n_written == (info->out_buffer.len - info->out_buffer_offset)); + nm_clear_g_source_inst(&info->output_source); + nm_close(info->child_stdin); + info->child_stdin = -1; + return G_SOURCE_CONTINUE; + } + info->out_buffer_offset += (gsize) n_written; + } + + return G_SOURCE_CONTINUE; + +out_error: + nm_clear_g_source_inst(&info->output_source); + helper_complete(info, + g_error_new(NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "error writing to helper: %d (%s)", + errsv, + nm_strerror_native(errsv))); + return G_SOURCE_CONTINUE; +} + +static gboolean +helper_have_data(int fd, GIOCondition condition, gpointer user_data) +{ + HelperInfo *info = user_data; + gssize n_read; + GError * error = NULL; + + n_read = nm_utils_fd_read(fd, &info->in_buffer); + _LOG2T(info, "read returns %ld", (long) n_read); + + if (n_read > 0) + return G_SOURCE_CONTINUE; + + nm_clear_g_source_inst(&info->input_source); + nm_close(info->child_stdout); + info->child_stdout = -1; + + _LOG2T(info, "stdout closed"); + + if (n_read < 0) { + error = g_error_new(NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "read from process returned %d (%s)", + (int) -n_read, + nm_strerror_native((int) -n_read)); + } + + helper_complete(info, error); + return G_SOURCE_CONTINUE; +} + +static void +helper_child_terminated(GPid pid, int status, gpointer user_data) +{ + HelperInfo * info = user_data; + GError * error = NULL; + gs_free char *status_desc = NULL; + + _LOG2D(info, "process %s", (status_desc = nm_utils_get_process_exit_status_desc(status))); + + info->pid = -1; + nm_clear_g_source_inst(&info->child_watch_source); + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + if (!status_desc) + status_desc = nm_utils_get_process_exit_status_desc(status); + error = + g_error_new(NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "helper process %s", status_desc); + } + + helper_complete(info, error); +} + +static gboolean +helper_timeout(gpointer user_data) +{ + HelperInfo *info = user_data; + + nm_clear_g_source_inst(&info->timeout_source); + helper_complete(info, g_error_new_literal(NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "timed out")); + + return G_SOURCE_CONTINUE; +} + +static void +helper_cancelled(GObject *object, gpointer user_data) +{ + HelperInfo *info = user_data; + GError * error = NULL; + + nm_clear_g_signal_handler(g_task_get_cancellable(info->task), &info->cancellable_id); + nm_utils_error_set_cancelled(&error, FALSE, NULL); + helper_complete(info, error); +} + +void +nm_utils_spawn_helper(const char *const * args, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer cb_data) +{ + gs_free_error GError *error = NULL; + gs_free char * commands = NULL; + HelperInfo * info; + int fd_flags; + const char *const * arg; + + nm_assert(args && args[0]); + + info = g_new(HelperInfo, 1); + *info = (HelperInfo){ + .task = nm_g_task_new(NULL, cancellable, nm_utils_spawn_helper, callback, cb_data), + .child_stdin = -1, + .child_stdout = -1, + .pid = -1, + }; + + if (!g_spawn_async_with_pipes("/", + (char **) NM_MAKE_STRV(LIBEXECDIR "/nm-daemon-helper"), + (char **) NM_MAKE_STRV(), + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, + NULL, + &info->pid, + &info->child_stdin, + &info->child_stdout, + NULL, + &error)) { + info->child_stdin = -1; + info->child_stdout = -1; + info->pid = -1; + g_task_return_error(info->task, + g_error_new(NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "error spawning nm-helper: %s", + error->message)); + helper_info_free(info); + return; + } + + _LOG2D(info, "spawned process with args: %s", (commands = g_strjoinv(" ", (char **) args))); + + info->child_watch_source = g_child_watch_source_new(info->pid); + g_source_set_callback(info->child_watch_source, + G_SOURCE_FUNC(helper_child_terminated), + info, + NULL); + g_source_attach(info->child_watch_source, g_main_context_get_thread_default()); + + info->timeout_source = + nm_g_timeout_source_new_seconds(20, G_PRIORITY_DEFAULT, helper_timeout, info, NULL); + g_source_attach(info->timeout_source, g_main_context_get_thread_default()); + + /* Set file descriptors as non-blocking */ + fd_flags = fcntl(info->child_stdin, F_GETFD, 0); + fcntl(info->child_stdin, F_SETFL, fd_flags | O_NONBLOCK); + fd_flags = fcntl(info->child_stdout, F_GETFD, 0); + fcntl(info->child_stdout, F_SETFL, fd_flags | O_NONBLOCK); + + /* Watch process stdin */ + nm_str_buf_init(&info->out_buffer, 32, TRUE); + for (arg = args; *arg; arg++) { + nm_str_buf_append(&info->out_buffer, *arg); + nm_str_buf_append_c(&info->out_buffer, '\0'); + } + info->output_source = nm_g_unix_fd_source_new(info->child_stdin, + G_IO_OUT | G_IO_ERR | G_IO_HUP, + G_PRIORITY_DEFAULT, + helper_can_write, + info, + NULL); + g_source_attach(info->output_source, g_main_context_get_thread_default()); + + /* Watch process stdout */ + nm_str_buf_init(&info->in_buffer, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE); + info->input_source = nm_g_unix_fd_source_new(info->child_stdout, + G_IO_IN | G_IO_ERR | G_IO_HUP, + G_PRIORITY_DEFAULT, + helper_have_data, + info, + NULL); + g_source_attach(info->input_source, g_main_context_get_thread_default()); + + if (cancellable) { + gulong signal_id; + + signal_id = g_cancellable_connect(cancellable, G_CALLBACK(helper_cancelled), info, NULL); + if (signal_id == 0) { + /* the request is already cancelled. Return. */ + return; + } + info->cancellable_id = signal_id; + } +} + +char * +nm_utils_spawn_helper_finish(GAsyncResult *result, GError **error) +{ + GTask *task = G_TASK(result); + + nm_assert(nm_g_task_is_valid(result, NULL, nm_utils_spawn_helper)); + + return g_task_propagate_pointer(task, error); +} diff --git a/src/core/nm-core-utils.h b/src/core/nm-core-utils.h index 5dc4d432..76c340d1 100644 --- a/src/core/nm-core-utils.h +++ b/src/core/nm-core-utils.h @@ -12,12 +12,10 @@ #include "nm-connection.h" -#include "nm-glib-aux/nm-time-utils.h" +#include "libnm-glib-aux/nm-time-utils.h" /*****************************************************************************/ -#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32 - #define NM_DEFINE_SINGLETON_INSTANCE(TYPE) static TYPE *singleton_instance #define NM_DEFINE_SINGLETON_REGISTER(TYPE) \ @@ -98,73 +96,6 @@ void _nm_singleton_instance_register_destruction(GObject *instance); gboolean nm_ether_addr_is_valid(const NMEtherAddr *addr); gboolean nm_ether_addr_is_valid_str(const char *str); -gconstpointer -nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint8 plen); -in_addr_t nm_utils_ip4_address_clear_host_address(in_addr_t addr, guint8 plen); -const struct in6_addr *nm_utils_ip6_address_clear_host_address(struct in6_addr * dst, - const struct in6_addr *src, - guint8 plen); - -static inline int -nm_utils_ip4_address_same_prefix_cmp(in_addr_t addr_a, in_addr_t addr_b, guint8 plen) -{ - NM_CMP_DIRECT(htonl(nm_utils_ip4_address_clear_host_address(addr_a, plen)), - htonl(nm_utils_ip4_address_clear_host_address(addr_b, plen))); - return 0; -} - -int nm_utils_ip6_address_same_prefix_cmp(const struct in6_addr *addr_a, - const struct in6_addr *addr_b, - guint8 plen); - -static inline int -nm_utils_ip_address_same_prefix_cmp(int addr_family, - gconstpointer addr_a, - gconstpointer addr_b, - guint8 plen) -{ - nm_assert_addr_family(addr_family); - - NM_CMP_SELF(addr_a, addr_b); - - if (NM_IS_IPv4(addr_family)) { - return nm_utils_ip4_address_same_prefix_cmp(*((const in_addr_t *) addr_a), - *((const in_addr_t *) addr_b), - plen); - } - - return nm_utils_ip6_address_same_prefix_cmp(addr_a, addr_b, plen); -} - -static inline gboolean -nm_utils_ip4_address_same_prefix(in_addr_t addr_a, in_addr_t addr_b, guint8 plen) -{ - return nm_utils_ip4_address_same_prefix_cmp(addr_a, addr_b, plen) == 0; -} - -static inline gboolean -nm_utils_ip6_address_same_prefix(const struct in6_addr *addr_a, - const struct in6_addr *addr_b, - guint8 plen) -{ - return nm_utils_ip6_address_same_prefix_cmp(addr_a, addr_b, plen) == 0; -} - -static inline gboolean -nm_utils_ip_address_same_prefix(int addr_family, - gconstpointer addr_a, - gconstpointer addr_b, - guint8 plen) -{ - return nm_utils_ip_address_same_prefix_cmp(addr_family, addr_a, addr_b, plen) == 0; -} - -#define NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a, b, plen) \ - NM_CMP_RETURN(nm_utils_ip4_address_same_prefix_cmp((a), (b), (plen))) - -#define NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(a, b, plen) \ - NM_CMP_RETURN(nm_utils_ip6_address_same_prefix_cmp((a), (b), (plen))) - static inline void nm_hash_update_in6addr(NMHashState *h, const struct in6_addr *addr) { @@ -185,8 +116,6 @@ nm_hash_update_in6addr_prefix(NMHashState *h, const struct in6_addr *addr, guint nm_hash_update_in6addr(h, &a); } -double nm_utils_exp10(gint16 e); - /** * nm_utils_ip6_route_metric_normalize: * @metric: the route metric @@ -221,9 +150,6 @@ nm_utils_ip_route_metric_penalize(guint32 metric, guint32 penalty) return G_MAXUINT32; } -int nm_utils_modprobe(GError **error, gboolean suppress_error_loggin, const char *arg1, ...) - G_GNUC_NULL_TERMINATED; - void nm_utils_kill_process_sync(pid_t pid, guint64 start_time, int sig, @@ -285,15 +211,16 @@ gboolean nm_utils_kernel_cmdline_match_check(const char *const *proc_cmdline, guint num_patterns, GError ** error); +int nm_utils_connection_match_spec_list(NMConnection *connection, + const GSList *specs, + int no_match_value); + /*****************************************************************************/ gboolean nm_utils_connection_has_default_route(NMConnection *connection, int addr_family, gboolean * out_is_never_default); -char * nm_utils_new_vlan_name(const char *parent_iface, guint32 vlan_id); -const char *nm_utils_new_infiniband_name(char *name, const char *parent_name, int p_key); - int nm_utils_cmp_connection_by_autoconnect_priority(NMConnection *a, NMConnection *b); void nm_utils_log_connection_diff(NMConnection *connection, @@ -304,19 +231,6 @@ void nm_utils_log_connection_diff(NMConnection *connection, const char * prefix, const char * dbus_path); -gboolean nm_utils_is_valid_path_component(const char *name); -const char *NM_ASSERT_VALID_PATH_COMPONENT(const char *name); - -#define NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE 100 - -const char * -nm_utils_sysctl_ip_conf_path(int addr_family, char *buf, const char *ifname, const char *property); - -gboolean nm_utils_sysctl_ip_conf_is_path(int addr_family, - const char *path, - const char *ifname, - const char *property); - gboolean nm_utils_is_specific_hostname(const char *name); struct _NMUuid; @@ -344,49 +258,6 @@ nm_utils_arp_type_get_hwaddr_relevant_part(int arp_type, const guint8 **hwaddr, /*****************************************************************************/ -/* IPv6 Interface Identifier helpers */ - -/** - * NMUtilsIPv6IfaceId: - * @id: convenience member for validity checking; never use directly - * @id_u8: the 64-bit Interface Identifier - * - * Holds a 64-bit IPv6 Interface Identifier. The IID is a sequence of bytes - * and should not normally be treated as a %guint64, but this is done for - * convenience of validity checking and initialization. - */ -struct _NMUtilsIPv6IfaceId { - union { - guint64 id; - guint8 id_u8[8]; - }; -}; - -#define NM_UTILS_IPV6_IFACE_ID_INIT \ - { \ - { \ - .id = 0 \ - } \ - } - -void nm_utils_ipv6_addr_set_interface_identifier(struct in6_addr * addr, - const NMUtilsIPv6IfaceId iid); - -void nm_utils_ipv6_interface_identifier_get_from_addr(NMUtilsIPv6IfaceId * iid, - const struct in6_addr *addr); - -gboolean nm_utils_ipv6_interface_identifier_get_from_token(NMUtilsIPv6IfaceId *iid, - const char * token); - -const char *nm_utils_inet6_interface_identifier_to_token(NMUtilsIPv6IfaceId iid, - char buf[static INET6_ADDRSTRLEN]); - -gboolean nm_utils_get_ipv6_interface_identifier(NMLinkType link_type, - const guint8 * hwaddr, - guint len, - guint dev_id, - NMUtilsIPv6IfaceId *out_iid); - typedef enum { /* The stable type. Note that this value is encoded in the * generated addresses, thus the numbers MUST not change. @@ -501,33 +372,6 @@ void _nm_utils_set_testing(NMUtilsTestFlags flags); void nm_utils_g_value_set_strv(GValue *value, GPtrArray *strings); -guint32 -nm_utils_lifetime_rebase_relative_time_on_now(guint32 timestamp, guint32 duration, gint32 now); - -guint32 nm_utils_lifetime_get(guint32 timestamp, - guint32 lifetime, - guint32 preferred, - gint32 now, - guint32 *out_preferred); - -/*****************************************************************************/ - -#define NM_IPV4LL_NETWORK ((in_addr_t)(htonl(0xA9FE0000lu))) -#define NM_IPV4LL_NETMASK ((in_addr_t)(htonl(0xFFFF0000lu))) - -static inline gboolean -nm_utils_ip4_address_is_link_local(in_addr_t addr) -{ - return (addr & NM_IPV4LL_NETMASK) == NM_IPV4LL_NETWORK; -} - -static inline gboolean -nm_utils_ip4_address_is_zeronet(in_addr_t network) -{ - /* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */ - return (network & htonl(0xFF000000u)) == htonl(0x00000000u); -} - /*****************************************************************************/ const char *nm_utils_dnsmasq_status_to_string(int status, char *dest, gsize size); @@ -556,20 +400,6 @@ char * nm_utils_format_con_diff_for_audit(GHashTable *diff); /*****************************************************************************/ -/* this enum is compatible with ICMPV6_ROUTER_PREF_* (from , - * the values for netlink attribute RTA_PREF) and "enum ndp_route_preference" - * from . */ -typedef enum _nm_packed { - NM_ICMPV6_ROUTER_PREF_MEDIUM = 0x0, /* ICMPV6_ROUTER_PREF_MEDIUM */ - NM_ICMPV6_ROUTER_PREF_LOW = 0x3, /* ICMPV6_ROUTER_PREF_LOW */ - NM_ICMPV6_ROUTER_PREF_HIGH = 0x1, /* ICMPV6_ROUTER_PREF_HIGH */ - NM_ICMPV6_ROUTER_PREF_INVALID = 0x2, /* ICMPV6_ROUTER_PREF_INVALID */ -} NMIcmpv6RouterPref; - -const char *nm_icmpv6_router_pref_to_string(NMIcmpv6RouterPref pref, char *buf, gsize len); - -/*****************************************************************************/ - const char *nm_activation_type_to_string(NMActivationType activation_type); /*****************************************************************************/ @@ -594,4 +424,13 @@ guint8 nm_wifi_utils_level_to_quality(int val); #define NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN "Unable to determine UID of the request" #define NM_UTILS_ERROR_MSG_INSUFF_PRIV "Insufficient privileges" +/*****************************************************************************/ + +void nm_utils_spawn_helper(const char *const * args, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer cb_data); + +char *nm_utils_spawn_helper_finish(GAsyncResult *result, GError **error); + #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/core/nm-dbus-manager.c b/src/core/nm-dbus-manager.c index 4f34ee52..c47d4dbf 100644 --- a/src/core/nm-dbus-manager.c +++ b/src/core/nm-dbus-manager.c @@ -13,13 +13,13 @@ #include #include "c-list/src/c-list.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-dbus-interface.h" -#include "nm-core-internal.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-dbus-object.h" #include "NetworkManagerUtils.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" /* The base path for our GDBusObjectManagerServers. They do not contain * "NetworkManager" because GDBusObjectManagerServer requires that all @@ -1139,10 +1139,6 @@ _nm_dbus_manager_obj_notify(NMDBusObject *obj, guint n_pspecs, const GParamSpec NMDBusManagerPrivate *priv; RegistrationData * reg_data; guint i, p; - gboolean any_legacy_signals = FALSE; - gboolean any_legacy_properties = FALSE; - GVariantBuilder legacy_builder; - GVariant * device_statistics_args = NULL; nm_assert(NM_IS_DBUS_OBJECT(obj)); nm_assert(obj->internal.path); @@ -1159,13 +1155,6 @@ _nm_dbus_manager_obj_notify(NMDBusObject *obj, guint n_pspecs, const GParamSpec if (G_UNLIKELY(!priv->started)) return; - c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) { - if (_reg_data_get_interface_info(reg_data)->legacy_property_changed) { - any_legacy_signals = TRUE; - break; - } - } - /* do a naive search for the matching NMDBusPropertyInfoExtended infos. Since the number of * (interfaces x properties) is static and possibly small, this naive search is effectively * O(1). We might wanna introduce some index to lookup the properties in question faster. @@ -1196,18 +1185,6 @@ _nm_dbus_manager_obj_notify(NMDBusObject *obj, guint n_pspecs, const GParamSpec value = _obj_get_property(reg_data, i, TRUE); - if (property_info->include_in_legacy_property_changed && any_legacy_signals) { - /* also track the value in the legacy_builder to emit legacy signals below. */ - if (!any_legacy_properties) { - any_legacy_properties = TRUE; - g_variant_builder_init(&legacy_builder, G_VARIANT_TYPE("a{sv}")); - } - g_variant_builder_add(&legacy_builder, - "{sv}", - property_info->parent.name, - value); - } - if (!has_properties) { has_properties = TRUE; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); @@ -1221,74 +1198,16 @@ _nm_dbus_manager_obj_notify(NMDBusObject *obj, guint n_pspecs, const GParamSpec args = g_variant_builder_end(&builder); - if (G_UNLIKELY(interface_info == &nm_interface_info_device_statistics)) { - /* we treat the Device.Statistics signal special, because we need to - * emit a signal also for it (below). */ - nm_assert(!device_statistics_args); - device_statistics_args = g_variant_ref_sink(args); - } - g_variant_builder_init(&invalidated_builder, G_VARIANT_TYPE("as")); g_dbus_connection_emit_signal( priv->main_dbus_connection, NULL, obj->internal.path, - "org.freedesktop.DBus.Properties", + DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", g_variant_new("(s@a{sv}as)", interface_info->parent.name, args, &invalidated_builder), NULL); } - - if (G_UNLIKELY(device_statistics_args)) { - /* this is a special interface: it has a legacy PropertiesChanged signal, - * however, contrary to other interfaces with ~regular~ legacy signals, - * we only notify about properties that actually belong to this interface. */ - g_dbus_connection_emit_signal(priv->main_dbus_connection, - NULL, - obj->internal.path, - nm_interface_info_device_statistics.parent.name, - "PropertiesChanged", - g_variant_new("(@a{sv})", device_statistics_args), - NULL); - g_variant_unref(device_statistics_args); - } - - if (any_legacy_properties) { - gs_unref_variant GVariant *args = NULL; - - /* The legacy PropertyChanged signal on the NetworkManager D-Bus interface is - * deprecated for the standard signal on org.freedesktop.DBus.Properties. However, - * for backward compatibility, we still need to emit it. - * - * Due to a bug in dbus-glib in NetworkManager <= 1.0, the signal would - * not only notify about properties that were actually on the corresponding - * D-Bus interface. Instead, it would notify about all relevant properties - * on all interfaces that had such a signal. - * - * For example, "HwAddress" gets emitted both on "fdo.NM.Device.Ethernet" - * and "fdo.NM.Device.Veth" for veth interfaces, although only the former - * actually has such a property. - * Also note that "fdo.NM.Device" interface has no legacy signal. All notifications - * about its properties are instead emitted on the interfaces of the subtypes. - * - * See bgo#770629 and commit bef26a2e69f51259095fa080221db73de09fd38d. - */ - args = g_variant_ref_sink(g_variant_new("(a{sv})", &legacy_builder)); - c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) { - const NMDBusInterfaceInfoExtended *interface_info = - _reg_data_get_interface_info(reg_data); - - if (interface_info->legacy_property_changed) { - g_dbus_connection_emit_signal(priv->main_dbus_connection, - NULL, - obj->internal.path, - interface_info->parent.name, - "PropertiesChanged", - args, - NULL); - } - } - } } void diff --git a/src/core/nm-dbus-object.c b/src/core/nm-dbus-object.c index 6f294fe2..04149739 100644 --- a/src/core/nm-dbus-object.c +++ b/src/core/nm-dbus-object.c @@ -183,23 +183,25 @@ nm_dbus_object_unexport_on_idle(gpointer /* (NMDBusObject *) */ self_take) /*****************************************************************************/ -void +gboolean _nm_dbus_object_clear_and_unexport(NMDBusObject **location) { NMDBusObject *self; - g_return_if_fail(location); + g_return_val_if_fail(location, FALSE); + if (!*location) - return; + return FALSE; self = g_steal_pointer(location); - g_return_if_fail(NM_IS_DBUS_OBJECT(self)); + g_return_val_if_fail(NM_IS_DBUS_OBJECT(self), FALSE); if (self->internal.path) nm_dbus_object_unexport(self); g_object_unref(self); + return TRUE; } /*****************************************************************************/ diff --git a/src/core/nm-dbus-object.h b/src/core/nm-dbus-object.h index d94bd5df..ae089dd3 100644 --- a/src/core/nm-dbus-object.h +++ b/src/core/nm-dbus-object.h @@ -45,17 +45,6 @@ typedef struct { /*****************************************************************************/ -/* "org.freedesktop.NetworkManager.Device.Statistics" is a special interface, - * because although it has a legacy PropertiesChanged signal, it only notifies - * about properties that actually exist on that interface. That is, because it - * was added with 1.4.0 release, and thus didn't have the broken behavior like - * other legacy interfaces. Those notify about *all* properties, even if they - * are not part of that D-Bus interface. See also "include_in_legacy_property_changed" - * and "legacy_property_changed". */ -extern const NMDBusInterfaceInfoExtended nm_interface_info_device_statistics; - -/*****************************************************************************/ - #define NM_TYPE_DBUS_OBJECT (nm_dbus_object_get_type()) #define NM_DBUS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DBUS_OBJECT, NMDBusObject)) #define NM_DBUS_OBJECT_CLASS(klass) \ @@ -166,9 +155,9 @@ void nm_dbus_object_unexport(gpointer /* (NMDBusObject *) */ self); void nm_dbus_object_unexport_on_idle(gpointer /* (NMDBusObject *) */ self_take); -void _nm_dbus_object_clear_and_unexport(NMDBusObject **location); +gboolean _nm_dbus_object_clear_and_unexport(NMDBusObject **location); #define nm_dbus_object_clear_and_unexport(location) \ - _nm_dbus_object_clear_and_unexport((NMDBusObject **) (location)) + _nm_dbus_object_clear_and_unexport(NM_CAST_PPTR(NMDBusObject, (location))) void nm_dbus_object_emit_signal_variant(NMDBusObject * self, const NMDBusInterfaceInfoExtended *interface_info, diff --git a/src/core/nm-dbus-utils.c b/src/core/nm-dbus-utils.c index 5890bdf2..d3e5612d 100644 --- a/src/core/nm-dbus-utils.c +++ b/src/core/nm-dbus-utils.c @@ -11,10 +11,6 @@ /*****************************************************************************/ -const GDBusSignalInfo nm_signal_info_property_changed_legacy = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT( - "PropertiesChanged", - .args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("properties", "a{sv}"), ), ); - GDBusPropertyInfo * nm_dbus_utils_interface_info_lookup_property(const GDBusInterfaceInfo *interface_info, const char * property_name, diff --git a/src/core/nm-dbus-utils.h b/src/core/nm-dbus-utils.h index 501e1996..6585d43d 100644 --- a/src/core/nm-dbus-utils.h +++ b/src/core/nm-dbus-utils.h @@ -14,11 +14,6 @@ struct _NMDBusMethodInfoExtended; struct _NMDBusPropertyInfoExtendedBase { GDBusPropertyInfo _parent; const char * property_name; - - /* Whether the properties needs to be notified on the legacy - * PropertyChanged signal. This is only to preserve API, new - * properties should not use this. */ - bool include_in_legacy_property_changed; }; struct _NMDBusPropertyInfoExtendedReadWritable { @@ -43,93 +38,46 @@ typedef struct { struct { GDBusPropertyInfo parent; const char * property_name; - - /* Whether the properties needs to be notified on the legacy - * PropertyChanged signal. This is only to preserve API, new - * properties should not use this. */ - bool include_in_legacy_property_changed; }; }; } NMDBusPropertyInfoExtended; G_STATIC_ASSERT(G_STRUCT_OFFSET(NMDBusPropertyInfoExtended, property_name) == G_STRUCT_OFFSET(struct _NMDBusPropertyInfoExtendedBase, property_name)); -G_STATIC_ASSERT(G_STRUCT_OFFSET(NMDBusPropertyInfoExtended, include_in_legacy_property_changed) - == G_STRUCT_OFFSET(struct _NMDBusPropertyInfoExtendedBase, - include_in_legacy_property_changed)); - -#define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_FULL(m_name, \ - m_signature, \ - m_property_name, \ - m_include_in_legacy_property_changed) \ - ((GDBusPropertyInfo *) &((const struct _NMDBusPropertyInfoExtendedBase){ \ - ._parent = \ - { \ - .ref_count = -1, \ - .name = m_name, \ - .signature = m_signature, \ - .flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE, \ - }, \ - .property_name = m_property_name, \ - .include_in_legacy_property_changed = m_include_in_legacy_property_changed, \ - })) #define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(m_name, m_signature, m_property_name) \ - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_FULL(m_name, m_signature, m_property_name, FALSE) - -/* define a legacy property. Do not use for new code. */ -#define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L(m_name, m_signature, m_property_name) \ - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_FULL(m_name, m_signature, m_property_name, TRUE) - -#define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_FULL( \ - m_name, \ - m_signature, \ - m_property_name, \ - m_permission, \ - m_audit_op, \ - m_include_in_legacy_property_changed) \ - ((GDBusPropertyInfo *) &((const struct _NMDBusPropertyInfoExtendedReadWritable){ \ - ._base = \ - { \ - ._parent = \ - { \ - .ref_count = -1, \ - .name = m_name, \ - .signature = m_signature, \ - .flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE \ - | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE, \ - }, \ - .property_name = m_property_name, \ - .include_in_legacy_property_changed = m_include_in_legacy_property_changed, \ - }, \ - .permission = m_permission, \ - .audit_op = m_audit_op, \ + ((GDBusPropertyInfo *) &((const struct _NMDBusPropertyInfoExtendedBase){ \ + ._parent = \ + { \ + .ref_count = -1, \ + .name = m_name, \ + .signature = m_signature, \ + .flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE, \ + }, \ + .property_name = m_property_name, \ })) -#define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE(m_name, \ - m_signature, \ - m_property_name, \ - m_permission, \ - m_audit_op) \ - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_FULL(m_name, \ - m_signature, \ - m_property_name, \ - m_permission, \ - m_audit_op, \ - FALSE) - -/* define a legacy property. Do not use for new code. */ -#define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L(m_name, \ - m_signature, \ - m_property_name, \ - m_permission, \ - m_audit_op) \ - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_FULL(m_name, \ - m_signature, \ - m_property_name, \ - m_permission, \ - m_audit_op, \ - TRUE) +#define NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE(m_name, \ + m_signature, \ + m_property_name, \ + m_permission, \ + m_audit_op) \ + ((GDBusPropertyInfo *) &((const struct _NMDBusPropertyInfoExtendedReadWritable){ \ + ._base = \ + { \ + ._parent = \ + { \ + .ref_count = -1, \ + .name = m_name, \ + .signature = m_signature, \ + .flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE \ + | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE, \ + }, \ + .property_name = m_property_name, \ + }, \ + .permission = m_permission, \ + .audit_op = m_audit_op, \ + })) typedef struct _NMDBusMethodInfoExtended { GDBusMethodInfo parent; @@ -148,14 +96,8 @@ typedef struct _NMDBusMethodInfoExtended { typedef struct _NMDBusInterfaceInfoExtended { GDBusInterfaceInfo parent; - - /* Whether the interface has a legacy property changed signal (@nm_signal_info_property_changed_legacy). - * New interfaces should not use this. */ - bool legacy_property_changed : 1; } NMDBusInterfaceInfoExtended; -extern const GDBusSignalInfo nm_signal_info_property_changed_legacy; - #define NM_DBUS_INTERFACE_INFOS(...) \ ({ \ static const NMDBusInterfaceInfoExtended *const _interface_infos[] = { \ diff --git a/src/core/nm-dcb.c b/src/core/nm-dcb.c index b3958caa..930a1023 100644 --- a/src/core/nm-dcb.c +++ b/src/core/nm-dcb.c @@ -8,7 +8,7 @@ #include #include "nm-dcb.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "NetworkManagerUtils.h" static const char *helper_names[] = {"dcbtool", "fcoeadm"}; diff --git a/src/core/nm-default-daemon.h b/src/core/nm-default-daemon.h index 65ca4b54..57d4c6af 100644 --- a/src/core/nm-default-daemon.h +++ b/src/core/nm-default-daemon.h @@ -8,7 +8,7 @@ /*****************************************************************************/ -#include "nm-glib-aux/nm-default-glib-i18n-prog.h" +#include "libnm-glib-aux/nm-default-glib-i18n-prog.h" #undef NETWORKMANAGER_COMPILATION #define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_DAEMON @@ -19,7 +19,7 @@ #include "nm-core-types.h" #include "nm-types.h" -#include "nm-log-core/nm-logging.h" +#include "libnm-log-core/nm-logging.h" /*****************************************************************************/ diff --git a/src/core/nm-dhcp-config.c b/src/core/nm-dhcp-config.c index 718d3c90..1cbad49e 100644 --- a/src/core/nm-dhcp-config.c +++ b/src/core/nm-dhcp-config.c @@ -59,6 +59,7 @@ struct _NMDhcpConfig { struct _NMDhcpConfigClass { NMDBusObjectClass parent; + int addr_family; }; G_DEFINE_ABSTRACT_TYPE(NMDhcpConfig, nm_dhcp_config, NM_TYPE_DBUS_OBJECT) @@ -67,6 +68,14 @@ G_DEFINE_ABSTRACT_TYPE(NMDhcpConfig, nm_dhcp_config, NM_TYPE_DBUS_OBJECT) /*****************************************************************************/ +int +nm_dhcp_config_get_addr_family(NMDhcpConfig *self) +{ + return NM_DHCP_CONFIG_GET_CLASS(self)->addr_family; +} + +/*****************************************************************************/ + void nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options) { @@ -116,8 +125,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) switch (prop_id) { case PROP_OPTIONS: - g_value_set_variant(value, - priv->options ?: g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0)); + g_value_set_variant(value, priv->options ?: nm_g_variant_singleton_aLsvI()); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -186,22 +194,23 @@ nm_dhcp4_config_init(NMDhcp4Config *self) static const NMDBusInterfaceInfoExtended interface_info_dhcp4_config = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DHCP4_CONFIG, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Options", - "a{sv}", - NM_DHCP_CONFIG_OPTIONS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Options", + "a{sv}", + NM_DHCP_CONFIG_OPTIONS), ), ), }; static void nm_dhcp4_config_class_init(NMDhcp4ConfigClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); + NMDhcpConfigClass *dhcp_config_class = NM_DHCP_CONFIG_CLASS(klass); dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/DHCP4Config"); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_dhcp4_config); dbus_object_class->export_on_construction = TRUE; + + dhcp_config_class->addr_family = AF_INET; } /*****************************************************************************/ @@ -223,20 +232,21 @@ nm_dhcp6_config_init(NMDhcp6Config *self) static const NMDBusInterfaceInfoExtended interface_info_dhcp6_config = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_DHCP6_CONFIG, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Options", - "a{sv}", - NM_DHCP_CONFIG_OPTIONS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Options", + "a{sv}", + NM_DHCP_CONFIG_OPTIONS), ), ), }; static void nm_dhcp6_config_class_init(NMDhcp6ConfigClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); + NMDhcpConfigClass *dhcp_config_class = NM_DHCP_CONFIG_CLASS(klass); dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/DHCP6Config"); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_dhcp6_config); dbus_object_class->export_on_construction = TRUE; + + dhcp_config_class->addr_family = AF_INET6; } diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c index 0ab409f5..32c9db62 100644 --- a/src/core/nm-dispatcher.c +++ b/src/core/nm-dispatcher.c @@ -8,7 +8,7 @@ #include "nm-dispatcher.h" -#include "nm-libnm-core-aux/nm-dispatcher-api.h" +#include "libnm-core-aux-extern/nm-dispatcher-api.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-connectivity.h" @@ -20,8 +20,8 @@ #include "nm-ip6-config.h" #include "nm-manager.h" #include "settings/nm-settings-connection.h" -#include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-core-intern/nm-core-internal.h" #define CALL_TIMEOUT (1000 * 60 * 10) /* 10 minutes for all scripts */ @@ -206,10 +206,7 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder) array[0] = addr->a4.address; array[1] = addr->a4.plen; array[2] = gw; - g_variant_builder_add( - &int_builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 3, sizeof(guint32))); + g_variant_builder_add(&int_builder, "@au", nm_g_variant_new_au(array, 3)); } else { const struct in6_addr *gw = &in6addr_any; @@ -278,10 +275,7 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder) array[1] = route->r4.plen; array[2] = route->r4.gateway; array[3] = route->r4.metric; - g_variant_builder_add( - &int_builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 4, sizeof(guint32))); + g_variant_builder_add(&int_builder, "@au", nm_g_variant_new_au(array, 4)); } else { var1 = nm_g_variant_new_ay_in6addr(&route->r6.network); var2 = nm_g_variant_new_ay_in6addr(&route->r6.gateway); @@ -550,9 +544,9 @@ _dispatcher_call(NMDispatcherAction action, if (applied_connection) connection_dict = - nm_connection_to_dbus(applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); + nm_connection_to_dbus(applied_connection, NM_CONNECTION_SERIALIZE_WITH_NON_SECRET); else - connection_dict = g_variant_new_array(G_VARIANT_TYPE("{sa{sv}}"), NULL, 0); + connection_dict = nm_g_variant_singleton_aLsaLsvII(); g_variant_builder_init(&connection_props, G_VARIANT_TYPE_VARDICT); if (settings_connection) { @@ -620,8 +614,8 @@ _dispatcher_call(NMDispatcherAction action, &device_proxy_props, &device_ip4_props, &device_ip6_props, - device_dhcp4_props ?: g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0), - device_dhcp6_props ?: g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0), + device_dhcp4_props ?: nm_g_variant_singleton_aLsvI(), + device_dhcp6_props ?: nm_g_variant_singleton_aLsvI(), connectivity_state_string, vpn_iface ?: "", &vpn_proxy_props, diff --git a/src/core/nm-firewall-manager.c b/src/core/nm-firewall-manager.c deleted file mode 100644 index 8f476e51..00000000 --- a/src/core/nm-firewall-manager.c +++ /dev/null @@ -1,623 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2011 - 2015 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-firewall-manager.h" - -#include "nm-glib-aux/nm-dbus-aux.h" -#include "c-list/src/c-list.h" - -#include "NetworkManagerUtils.h" -#include "nm-dbus-manager.h" - -#define FIREWALL_DBUS_SERVICE "org.fedoraproject.FirewallD1" -#define FIREWALL_DBUS_PATH "/org/fedoraproject/FirewallD1" -#define FIREWALL_DBUS_INTERFACE_ZONE "org.fedoraproject.FirewallD1.zone" - -/*****************************************************************************/ - -enum { STATE_CHANGED, LAST_SIGNAL }; - -static guint signals[LAST_SIGNAL] = {0}; - -typedef struct { - GDBusConnection *dbus_connection; - - GCancellable *get_name_owner_cancellable; - - CList pending_calls; - - guint name_owner_changed_id; - - bool dbus_inited : 1; - bool running : 1; -} NMFirewallManagerPrivate; - -struct _NMFirewallManager { - GObject parent; - NMFirewallManagerPrivate _priv; -}; - -struct _NMFirewallManagerClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE(NMFirewallManager, nm_firewall_manager, G_TYPE_OBJECT) - -#define NM_FIREWALL_MANAGER_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMFirewallManager, NM_IS_FIREWALL_MANAGER) - -/*****************************************************************************/ - -NM_DEFINE_SINGLETON_GETTER(NMFirewallManager, nm_firewall_manager_get, NM_TYPE_FIREWALL_MANAGER); - -/*****************************************************************************/ - -typedef enum { - OPS_TYPE_ADD = 1, - OPS_TYPE_CHANGE, - OPS_TYPE_REMOVE, -} OpsType; - -struct _NMFirewallManagerCallId { - CList lst; - - NMFirewallManager *self; - - char *iface; - - NMFirewallManagerAddRemoveCallback callback; - gpointer user_data; - - union { - struct { - GCancellable *cancellable; - GVariant * arg; - } dbus; - struct { - guint id; - } idle; - }; - - OpsType ops_type; - - bool is_idle : 1; -}; - -/*****************************************************************************/ - -static const char * -_ops_type_to_string(OpsType ops_type) -{ - switch (ops_type) { - case OPS_TYPE_ADD: - return "add"; - case OPS_TYPE_REMOVE: - return "remove"; - case OPS_TYPE_CHANGE: - return "change"; - } - nm_assert_not_reached(); - return NULL; -} - -#define _NMLOG_DOMAIN LOGD_FIREWALL -#define _NMLOG_PREFIX_NAME "firewall" -#define _NMLOG(level, call_id, ...) \ - G_STMT_START \ - { \ - if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \ - NMFirewallManagerCallId *_call_id = (call_id); \ - char _prefix_name[30]; \ - char _prefix_info[100]; \ - \ - _nm_log((level), \ - (_NMLOG_DOMAIN), \ - 0, \ - NULL, \ - NULL, \ - "%s: %s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (self) != singleton_instance ? ({ \ - g_snprintf(_prefix_name, \ - sizeof(_prefix_name), \ - "%s[" NM_HASH_OBFUSCATE_PTR_FMT "]", \ - ""_NMLOG_PREFIX_NAME, \ - NM_HASH_OBFUSCATE_PTR(self)); \ - _prefix_name; \ - }) \ - : _NMLOG_PREFIX_NAME, \ - _call_id ? ({ \ - g_snprintf(_prefix_info, \ - sizeof(_prefix_info), \ - "[" NM_HASH_OBFUSCATE_PTR_FMT ",%s%s:%s%s%s]: ", \ - NM_HASH_OBFUSCATE_PTR(_call_id), \ - _ops_type_to_string(_call_id->ops_type), \ - _call_id->is_idle ? "*" : "", \ - NM_PRINT_FMT_QUOTE_STRING(_call_id->iface)); \ - _prefix_info; \ - }) \ - : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static gboolean -_get_running(NMFirewallManagerPrivate *priv) -{ - /* when starting, we need to asynchronously check whether there is - * a name owner. During that time we optimistically assume that the - * service is indeed running. That is the time when we queue the - * requests, and they will be started once the get-name-owner call - * returns. */ - return priv->running || (priv->dbus_connection && !priv->dbus_inited); -} - -gboolean -nm_firewall_manager_get_running(NMFirewallManager *self) -{ - g_return_val_if_fail(NM_IS_FIREWALL_MANAGER(self), FALSE); - - return _get_running(NM_FIREWALL_MANAGER_GET_PRIVATE(self)); -} - -/*****************************************************************************/ - -static NMFirewallManagerCallId * -_cb_info_create(NMFirewallManager * self, - OpsType ops_type, - const char * iface, - const char * zone, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data) -{ - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - NMFirewallManagerCallId * call_id; - - call_id = g_slice_new0(NMFirewallManagerCallId); - - call_id->self = g_object_ref(self); - call_id->ops_type = ops_type; - call_id->iface = g_strdup(iface); - call_id->callback = callback; - call_id->user_data = user_data; - - if (_get_running(priv)) { - call_id->is_idle = FALSE; - call_id->dbus.arg = g_variant_new("(ss)", zone ?: "", iface); - } else - call_id->is_idle = TRUE; - - c_list_link_tail(&priv->pending_calls, &call_id->lst); - - return call_id; -} - -static void -_cb_info_complete(NMFirewallManagerCallId *call_id, GError *error) -{ - c_list_unlink(&call_id->lst); - - if (call_id->callback) - call_id->callback(call_id->self, call_id, error, call_id->user_data); - - if (call_id->is_idle) - nm_clear_g_source(&call_id->idle.id); - else { - nm_g_variant_unref(call_id->dbus.arg); - nm_clear_g_cancellable(&call_id->dbus.cancellable); - } - g_free(call_id->iface); - g_object_unref(call_id->self); - nm_g_slice_free(call_id); -} - -static gboolean -_handle_idle_cb(gpointer user_data) -{ - NMFirewallManager * self; - NMFirewallManagerCallId *call_id = user_data; - - nm_assert(call_id); - nm_assert(NM_IS_FIREWALL_MANAGER(call_id->self)); - nm_assert(call_id->is_idle); - nm_assert(c_list_contains(&NM_FIREWALL_MANAGER_GET_PRIVATE(call_id->self)->pending_calls, - &call_id->lst)); - - self = call_id->self; - - _LOGD(call_id, "complete: fake success"); - - call_id->idle.id = 0; - - _cb_info_complete(call_id, NULL); - return G_SOURCE_REMOVE; -} - -static gboolean -_handle_idle_start(NMFirewallManager *self, NMFirewallManagerCallId *call_id) -{ - if (!call_id->callback) { - /* if the user did not provide a callback and firewalld is not running, - * there is no point in scheduling an idle-request to fake success. Just - * return right away. */ - _LOGD(call_id, "complete: drop request simulating success"); - _cb_info_complete(call_id, NULL); - return FALSE; - } - call_id->idle.id = g_idle_add(_handle_idle_cb, call_id); - return TRUE; -} - -static void -_handle_dbus_cb(GObject *source, GAsyncResult *result, gpointer user_data) -{ - NMFirewallManager * self; - NMFirewallManagerCallId *call_id; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *ret = NULL; - - ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error); - - if (!ret && nm_utils_error_is_cancelled(error)) - return; - - call_id = user_data; - - nm_assert(call_id); - nm_assert(NM_IS_FIREWALL_MANAGER(call_id->self)); - nm_assert(!call_id->is_idle); - nm_assert(c_list_contains(&NM_FIREWALL_MANAGER_GET_PRIVATE(call_id->self)->pending_calls, - &call_id->lst)); - - self = call_id->self; - - if (error) { - const char *non_error = NULL; - - g_dbus_error_strip_remote_error(error); - - switch (call_id->ops_type) { - case OPS_TYPE_ADD: - case OPS_TYPE_CHANGE: - non_error = "ZONE_ALREADY_SET"; - break; - case OPS_TYPE_REMOVE: - non_error = "UNKNOWN_INTERFACE"; - break; - } - if (error->message && non_error && g_str_has_prefix(error->message, non_error) - && NM_IN_SET(error->message[strlen(non_error)], '\0', ':')) { - _LOGD(call_id, "complete: request failed with a non-error (%s)", error->message); - - /* The operation failed with an error reason that we don't want - * to propagate. Instead, signal success. */ - g_clear_error(&error); - } else - _LOGW(call_id, "complete: request failed (%s)", error->message); - } else - _LOGD(call_id, "complete: success"); - - g_clear_object(&call_id->dbus.cancellable); - - _cb_info_complete(call_id, error); -} - -static void -_handle_dbus_start(NMFirewallManager *self, NMFirewallManagerCallId *call_id) -{ - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - const char * dbus_method = NULL; - GVariant * arg; - - nm_assert(call_id); - nm_assert(priv->running); - nm_assert(!call_id->is_idle); - nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst)); - - switch (call_id->ops_type) { - case OPS_TYPE_ADD: - dbus_method = "addInterface"; - break; - case OPS_TYPE_CHANGE: - dbus_method = "changeZone"; - break; - case OPS_TYPE_REMOVE: - dbus_method = "removeInterface"; - break; - } - nm_assert(dbus_method); - - arg = g_steal_pointer(&call_id->dbus.arg); - - nm_assert(arg && g_variant_is_floating(arg)); - - nm_assert(!call_id->dbus.cancellable); - - call_id->dbus.cancellable = g_cancellable_new(); - - g_dbus_connection_call(priv->dbus_connection, - FIREWALL_DBUS_SERVICE, - FIREWALL_DBUS_PATH, - FIREWALL_DBUS_INTERFACE_ZONE, - dbus_method, - arg, - NULL, - G_DBUS_CALL_FLAGS_NONE, - 10000, - call_id->dbus.cancellable, - _handle_dbus_cb, - call_id); -} - -static NMFirewallManagerCallId * -_start_request(NMFirewallManager * self, - OpsType ops_type, - const char * iface, - const char * zone, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data) -{ - NMFirewallManagerPrivate *priv; - NMFirewallManagerCallId * call_id; - - g_return_val_if_fail(NM_IS_FIREWALL_MANAGER(self), NULL); - g_return_val_if_fail(iface && *iface, NULL); - - priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - - call_id = _cb_info_create(self, ops_type, iface, zone, callback, user_data); - - _LOGD(call_id, - "firewall zone %s %s:%s%s%s%s", - _ops_type_to_string(call_id->ops_type), - iface, - NM_PRINT_FMT_QUOTED(zone, "\"", zone, "\"", "default"), - call_id->is_idle ? " (not running, simulate success)" - : (!priv->running ? " (waiting to initialize)" : "")); - - if (!call_id->is_idle) { - if (priv->running) - _handle_dbus_start(self, call_id); - if (!call_id->callback) { - /* if the user did not provide a callback, the call_id is useless. - * Especially, the user cannot use the call-id to cancel the request, - * because he cannot know whether the request is still pending. - * - * Hence, returning %NULL doesn't mean that the request could not be started - * (this function never fails and always starts a request). */ - return NULL; - } - } else { - if (!_handle_idle_start(self, call_id)) { - /* if the user did not provide a callback and firewalld is not running, - * there is no point in scheduling an idle-request to fake success. Just - * return right away. */ - return NULL; - } - } - - return call_id; -} - -NMFirewallManagerCallId * -nm_firewall_manager_add_or_change_zone(NMFirewallManager *self, - const char * iface, - const char * zone, - gboolean add, /* TRUE == add, FALSE == change */ - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data) -{ - return _start_request(self, - add ? OPS_TYPE_ADD : OPS_TYPE_CHANGE, - iface, - zone, - callback, - user_data); -} - -NMFirewallManagerCallId * -nm_firewall_manager_remove_from_zone(NMFirewallManager * self, - const char * iface, - const char * zone, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data) -{ - return _start_request(self, OPS_TYPE_REMOVE, iface, zone, callback, user_data); -} - -void -nm_firewall_manager_cancel_call(NMFirewallManagerCallId *call_id) -{ - NMFirewallManager * self; - NMFirewallManagerPrivate *priv; - gs_free_error GError *error = NULL; - - g_return_if_fail(call_id); - g_return_if_fail(NM_IS_FIREWALL_MANAGER(call_id->self)); - g_return_if_fail(!c_list_is_empty(&call_id->lst)); - - self = call_id->self; - priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - - nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst)); - - nm_utils_error_set_cancelled(&error, FALSE, "NMFirewallManager"); - - _LOGD(call_id, "complete: cancel (%s)", error->message); - - _cb_info_complete(call_id, error); -} - -/*****************************************************************************/ - -static void -name_owner_changed(NMFirewallManager *self, const char *owner) -{ - _nm_unused gs_unref_object NMFirewallManager *self_keep_alive = g_object_ref(self); - NMFirewallManagerPrivate * priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - gboolean was_running; - gboolean now_running; - gboolean just_initied; - - owner = nm_str_not_empty(owner); - - if (!owner) - _LOGT(NULL, "D-Bus name for firewalld has no owner (firewall stopped)"); - else - _LOGT(NULL, "D-Bus name for firewalld has owner %s (firewall started)", owner); - - was_running = _get_running(priv); - just_initied = !priv->dbus_inited; - - priv->dbus_inited = TRUE; - priv->running = !!owner; - - now_running = _get_running(priv); - - if (just_initied) { - NMFirewallManagerCallId *call_id_safe; - NMFirewallManagerCallId *call_id; - - /* We kick of the requests that we have pending. Note that this is - * entirely asynchronous and also we don't invoke any callbacks for - * the user. - * Even _handle_idle_start() just schedules an idle handler. That is, - * because we don't want to callback to the user before emitting the - * DISCONNECTED signal below. Also, emitting callbacks means the user - * can call back to modify the list of pending-calls and we'd have - * to handle reentrancy. */ - c_list_for_each_entry_safe (call_id, call_id_safe, &priv->pending_calls, lst) { - nm_assert(!call_id->is_idle); - nm_assert(call_id->dbus.arg); - - if (priv->running) { - _LOGD(call_id, "initalizing: make D-Bus call"); - _handle_dbus_start(self, call_id); - } else { - /* we don't want to invoke callbacks to the user right away. That is because - * the user might schedule/cancel more calls, which messes up the order. - * - * Instead, convert the pending calls to idle requests... */ - nm_clear_pointer(&call_id->dbus.arg, g_variant_unref); - call_id->is_idle = TRUE; - _LOGD(call_id, "initializing: fake success on idle"); - _handle_idle_start(self, call_id); - } - } - } - - if (was_running != now_running) - g_signal_emit(self, signals[STATE_CHANGED], 0, FALSE); -} - -static void -name_owner_changed_cb(GDBusConnection *connection, - const char * sender_name, - const char * object_path, - const char * interface_name, - const char * signal_name, - GVariant * parameters, - gpointer user_data) -{ - NMFirewallManager *self = user_data; - const char * new_owner; - - if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) - return; - - g_variant_get(parameters, "(&s&s&s)", NULL, NULL, &new_owner); - - name_owner_changed(self, new_owner); -} - -static void -get_name_owner_cb(const char *name_owner, GError *error, gpointer user_data) -{ - NMFirewallManager * self; - NMFirewallManagerPrivate *priv; - - if (!name_owner && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = user_data; - priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - - g_clear_object(&priv->get_name_owner_cancellable); - - name_owner_changed(self, name_owner); -} - -/*****************************************************************************/ - -static void -nm_firewall_manager_init(NMFirewallManager *self) -{ - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - - c_list_init(&priv->pending_calls); - - priv->dbus_connection = nm_g_object_ref(NM_MAIN_DBUS_CONNECTION_GET); - - if (!priv->dbus_connection) { - _LOGD(NULL, "no D-Bus connection"); - return; - } - - priv->name_owner_changed_id = - nm_dbus_connection_signal_subscribe_name_owner_changed(priv->dbus_connection, - FIREWALL_DBUS_SERVICE, - name_owner_changed_cb, - self, - NULL); - - priv->get_name_owner_cancellable = g_cancellable_new(); - nm_dbus_connection_call_get_name_owner(priv->dbus_connection, - FIREWALL_DBUS_SERVICE, - -1, - priv->get_name_owner_cancellable, - get_name_owner_cb, - self); -} - -static void -dispose(GObject *object) -{ - NMFirewallManager * self = NM_FIREWALL_MANAGER(object); - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE(self); - - /* as every pending operation takes a reference to the manager, - * we don't expect pending operations at this point. */ - nm_assert(c_list_is_empty(&priv->pending_calls)); - - nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id); - - nm_clear_g_cancellable(&priv->get_name_owner_cancellable); - - G_OBJECT_CLASS(nm_firewall_manager_parent_class)->dispose(object); - - g_clear_object(&priv->dbus_connection); -} - -static void -nm_firewall_manager_class_init(NMFirewallManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - object_class->dispose = dispose; - - signals[STATE_CHANGED] = g_signal_new(NM_FIREWALL_MANAGER_STATE_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, - 1, - G_TYPE_BOOLEAN /* initialized_now */); -} diff --git a/src/core/nm-firewall-manager.h b/src/core/nm-firewall-manager.h deleted file mode 100644 index 1ce802b2..00000000 --- a/src/core/nm-firewall-manager.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2011 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_FIREWALL_MANAGER_H__ -#define __NETWORKMANAGER_FIREWALL_MANAGER_H__ - -#define NM_TYPE_FIREWALL_MANAGER (nm_firewall_manager_get_type()) -#define NM_FIREWALL_MANAGER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_FIREWALL_MANAGER, NMFirewallManager)) -#define NM_FIREWALL_MANAGER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_FIREWALL_MANAGER, NMFirewallManagerClass)) -#define NM_IS_FIREWALL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_FIREWALL_MANAGER)) -#define NM_IS_FIREWALL_MANAGER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_FIREWALL_MANAGER)) -#define NM_FIREWALL_MANAGER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_FIREWALL_MANAGER, NMFirewallManagerClass)) - -#define NM_FIREWALL_MANAGER_STATE_CHANGED "state-changed" - -typedef struct _NMFirewallManagerCallId NMFirewallManagerCallId; - -typedef struct _NMFirewallManager NMFirewallManager; -typedef struct _NMFirewallManagerClass NMFirewallManagerClass; - -GType nm_firewall_manager_get_type(void); - -NMFirewallManager *nm_firewall_manager_get(void); - -gboolean nm_firewall_manager_get_running(NMFirewallManager *self); - -typedef void (*NMFirewallManagerAddRemoveCallback)(NMFirewallManager * self, - NMFirewallManagerCallId *call_id, - GError * error, - gpointer user_data); - -NMFirewallManagerCallId * -nm_firewall_manager_add_or_change_zone(NMFirewallManager * mgr, - const char * iface, - const char * zone, - gboolean add, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data); -NMFirewallManagerCallId * -nm_firewall_manager_remove_from_zone(NMFirewallManager * mgr, - const char * iface, - const char * zone, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data); - -void nm_firewall_manager_cancel_call(NMFirewallManagerCallId *call_id); - -#endif /* __NETWORKMANAGER_FIREWALL_MANAGER_H__ */ diff --git a/src/core/nm-firewall-utils.c b/src/core/nm-firewall-utils.c new file mode 100644 index 00000000..a2446553 --- /dev/null +++ b/src/core/nm-firewall-utils.c @@ -0,0 +1,816 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2004 - 2016 Red Hat, Inc. + * Copyright (C) 2005 - 2008 Novell, Inc. + */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-firewall-utils.h" + +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-io-utils.h" +#include "libnm-platform/nm-platform.h" + +#include "nm-config.h" +#include "NetworkManagerUtils.h" + +/*****************************************************************************/ + +static const struct { + const char *name; + const char *path; +} FirewallBackends[] = { + [NM_FIREWALL_BACKEND_NONE - 1] = + { + .name = "none", + }, + [NM_FIREWALL_BACKEND_NFTABLES - 1] = + { + .name = "nftables", + .path = NFT_PATH, + }, + [NM_FIREWALL_BACKEND_IPTABLES - 1] = + { + .name = "iptables", + .path = IPTABLES_PATH, + }, +}; + +/*****************************************************************************/ + +#define _SHARE_IPTABLES_SUBNET_TO_STR_LEN (INET_ADDRSTRLEN + 1 + 2 + 1) + +static const char * +_share_iptables_subnet_to_str(char buf[static _SHARE_IPTABLES_SUBNET_TO_STR_LEN], + in_addr_t addr, + guint8 plen) +{ + char buf_addr[INET_ADDRSTRLEN]; + in_addr_t netmask; + int l; + + netmask = _nm_utils_ip4_prefix_to_netmask(plen); + + l = g_snprintf(buf, + _SHARE_IPTABLES_SUBNET_TO_STR_LEN, + "%s/%u", + _nm_utils_inet4_ntop(addr & netmask, buf_addr), + plen); + nm_assert(l < _SHARE_IPTABLES_SUBNET_TO_STR_LEN); + return buf; +} + +static char * +_share_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const char *ip_iface) +{ + NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE); + gsize ip_iface_len; + + nm_assert(prefix); + nm_assert(ip_iface); + + /* This function is used to generate iptables chain names and comments. + * Chain names must be shorter than 29 chars. Comments don't have this + * limitation. + * + * Below we sanitize the ip_iface. If it's all benign, we use + * - either "-$IP_IFACE" (at most 16 chars) + * - otherwise, we base64 encode the name as "$(base64 $IP_IFACE)", at + * most 20 chars. + * + * Since for benign names we already add a '-', prefix probably should not + * contain a '-'. The '-' is necessary to distinguish between base64 encoding + * an plain name. + * + * That means, for chain names the prefix must be at most 8 chars long. */ + nm_assert(!is_iptables_chain || (strlen(prefix) <= 8)); + + nm_str_buf_append(&strbuf, prefix); + + ip_iface_len = strlen(ip_iface); + G_STATIC_ASSERT_EXPR(NMP_IFNAMSIZ == 16); + if (ip_iface_len >= NMP_IFNAMSIZ) { + nm_assert_not_reached(); + ip_iface_len = NMP_IFNAMSIZ - 1; + } + + if (NM_STRCHAR_ALL(ip_iface, + ch, + (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') || NM_IN_SET(ch, '.', '_', '-', '+'))) { + nm_str_buf_append_c(&strbuf, '-'); + nm_str_buf_append(&strbuf, ip_iface); + } else { + gs_free char *s = NULL; + + s = g_base64_encode((const guchar *) ip_iface, ip_iface_len); + nm_str_buf_append(&strbuf, s); + } + + return nm_str_buf_finalize(&strbuf, NULL); +} + +static gboolean +_share_iptables_call_v(const char *const *argv) +{ + gs_free_error GError *error = NULL; + gs_free char * argv_str = NULL; + int status; + + nm_log_dbg(LOGD_SHARING, "iptables: %s", (argv_str = g_strjoinv(" ", (char **) argv))); + + if (!g_spawn_sync("/", + (char **) argv, + (char **) NM_PTRARRAY_EMPTY(const char *), + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, + NULL, + NULL, + NULL, + &status, + &error)) { + nm_log_warn(LOGD_SHARING, + "iptables: error executing command %s: %s", + argv[0], + error->message); + return FALSE; + } + + if (!g_spawn_check_exit_status(status, &error)) { + nm_log_warn(LOGD_SHARING, "iptables: command %s failed: %s", argv[0], error->message); + return FALSE; + } + + return TRUE; +} + +#define _share_iptables_call(...) _share_iptables_call_v(NM_MAKE_STRV(__VA_ARGS__)) + +static gboolean +_share_iptables_chain_op(const char *table, const char *chain, const char *op) +{ + return _share_iptables_call("" IPTABLES_PATH "", "--table", table, op, chain); +} + +static gboolean +_share_iptables_chain_delete(const char *table, const char *chain) +{ + _share_iptables_chain_op(table, chain, "--flush"); + return _share_iptables_chain_op(table, chain, "--delete-chain"); +} + +static gboolean +_share_iptables_chain_add(const char *table, const char *chain) +{ + if (_share_iptables_chain_op(table, chain, "--new-chain")) + return TRUE; + + _share_iptables_chain_delete(table, chain); + return _share_iptables_chain_op(table, chain, "--new-chain"); +} + +static void +_share_iptables_set_masquerade(gboolean add, 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; + + comment_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface); + + _share_iptables_subnet_to_str(str_subnet, addr, plen); + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "nat", + add ? "--insert" : "--delete", + "POSTROUTING", + "--source", + str_subnet, + "!", + "--destination", + str_subnet, + "--jump", + "MASQUERADE", + "-m", + "comment", + "--comment", + comment_name); +} + +static void +_share_iptables_set_shared_chains_add(const char *chain_input, + const char *chain_forward, + const char *ip_iface, + in_addr_t addr, + guint plen) +{ + const char *const input_params[][2] = { + { + "tcp", + "67", + }, + { + "udp", + "67", + }, + { + "tcp", + "53", + }, + { + "udp", + "53", + }, + }; + char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN]; + int i; + + _share_iptables_subnet_to_str(str_subnet, addr, plen); + + _share_iptables_chain_add("filter", chain_input); + + for (i = 0; i < (int) G_N_ELEMENTS(input_params); i++) { + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + "--append", + chain_input, + "--protocol", + input_params[i][0], + "--destination-port", + input_params[i][1], + "--jump", + "ACCEPT"); + } + + _share_iptables_chain_add("filter", chain_forward); + + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + "--append", + chain_forward, + "--destination", + str_subnet, + "--out-interface", + ip_iface, + "--match", + "state", + "--state", + "ESTABLISHED,RELATED", + "--jump", + "ACCEPT"); + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + "--append", + chain_forward, + "--source", + str_subnet, + "--in-interface", + ip_iface, + "--jump", + "ACCEPT"); + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + "--append", + chain_forward, + "--in-interface", + ip_iface, + "--out-interface", + ip_iface, + "--jump", + "ACCEPT"); + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + "--append", + chain_forward, + "--out-interface", + ip_iface, + "--jump", + "REJECT"); + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + "--append", + chain_forward, + "--in-interface", + ip_iface, + "--jump", + "REJECT"); +} + +static void +_share_iptables_set_shared_chains_delete(const char *chain_input, const char *chain_forward) +{ + _share_iptables_chain_delete("filter", chain_input); + _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) +{ + gs_free char *comment_name = NULL; + gs_free char *chain_input = NULL; + gs_free char *chain_forward = NULL; + + comment_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface); + 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) + _share_iptables_set_shared_chains_add(chain_input, chain_forward, ip_iface, addr, plen); + + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + add ? "--insert" : "--delete", + "INPUT", + "--in-interface", + ip_iface, + "--jump", + chain_input, + "-m", + "comment", + "--comment", + comment_name); + + _share_iptables_call("" IPTABLES_PATH "", + "--table", + "filter", + add ? "--insert" : "--delete", + "FORWARD", + "--jump", + chain_forward, + "-m", + "comment", + "--comment", + comment_name); + + if (!add) + _share_iptables_set_shared_chains_delete(chain_input, chain_forward); +} + +/*****************************************************************************/ + +typedef struct { + GTask * task; + GSubprocess * subprocess; + GSource * timeout_source; + GCancellable *intern_cancellable; + char * identifier; + gulong cancellable_id; +} FwNftCallData; + +static void +_fw_nft_call_data_free(FwNftCallData *call_data, GError *error_take) +{ + nm_clear_g_signal_handler(g_task_get_cancellable(call_data->task), &call_data->cancellable_id); + nm_clear_g_cancellable(&call_data->intern_cancellable); + nm_clear_g_source_inst(&call_data->timeout_source); + + if (error_take) + g_task_return_error(call_data->task, error_take); + else + g_task_return_boolean(call_data->task, TRUE); + + g_object_unref(call_data->task); + nm_g_object_unref(call_data->subprocess); + g_free(call_data->identifier); + + nm_g_slice_free(call_data); +} + +static void +_fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + FwNftCallData *call_data = user_data; + gs_free_error GError *error = NULL; + gs_unref_bytes GBytes *stdout_buf = NULL; + gs_unref_bytes GBytes *stderr_buf = NULL; + + nm_assert(source == (gpointer) call_data->subprocess); + + if (!g_subprocess_communicate_finish(G_SUBPROCESS(source), + result, + &stdout_buf, + &stderr_buf, + &error)) { + /* on any error, the process might still be running. We need to abort it in + * the background... */ + if (!nm_utils_error_is_cancelled(error)) { + nm_log_dbg(LOGD_SHARING, + "firewall: nft[%s]: communication failed: %s. Kill process", + call_data->identifier, + error->message); + } else if (!call_data->timeout_source) { + nm_log_dbg(LOGD_SHARING, + "firewall: ntf[%s]: communication timed out. Kill process", + call_data->identifier); + nm_clear_error(&error); + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "timeout communicating with nft"); + } else { + nm_log_dbg(LOGD_SHARING, + "firewall: ntf[%s]: communication cancelled. Kill process", + call_data->identifier); + } + + { + _nm_unused nm_auto_pop_gmaincontext GMainContext *main_context = + nm_g_main_context_push_thread_default_if_necessary(NULL); + + nm_shutdown_wait_obj_register_object(call_data->subprocess, "nft-terminate"); + G_STATIC_ASSERT_EXPR(200 < NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG * 2 / 3); + nm_g_subprocess_terminate_in_background(call_data->subprocess, 200); + } + } else if (g_subprocess_get_successful(call_data->subprocess)) { + nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: command successful", call_data->identifier); + } else { + 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); + + nm_log_warn(LOGD_SHARING, + "firewall: nft[%s]: command failed:%s%s%s%s%s%s%s", + call_data->identifier, + print_stdout || print_stderr ? "" : " unknown reason", + NM_PRINT_FMT_QUOTED( + print_stdout, + " (stdout: \"", + nm_utils_buf_utf8safe_escape_bytes(stdout_buf, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &ss_stdout), + "\")", + ""), + NM_PRINT_FMT_QUOTED( + print_stderr, + " (stderr: \"", + nm_utils_buf_utf8safe_escape_bytes(stderr_buf, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &ss_stderr), + "\")", + "")); + } + + _fw_nft_call_data_free(call_data, g_steal_pointer(&error)); +} + +static void +_fw_nft_call_cancelled_cb(GCancellable *cancellable, gpointer user_data) +{ + FwNftCallData *call_data = user_data; + + if (call_data->cancellable_id == 0) + return; + + nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: operation cancelled", call_data->identifier); + + nm_clear_g_signal_handler(g_task_get_cancellable(call_data->task), &call_data->cancellable_id); + nm_clear_g_cancellable(&call_data->intern_cancellable); +} + +static gboolean +_fw_nft_call_timeout_cb(gpointer user_data) +{ + FwNftCallData *call_data = user_data; + + nm_clear_g_source_inst(&call_data->timeout_source); + nm_log_dbg(LOGD_SHARING, + "firewall: nft[%s]: cancel operation after timeout", + call_data->identifier); + + nm_clear_g_cancellable(&call_data->intern_cancellable); + return G_SOURCE_CONTINUE; +} + +static void +_fw_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; + + 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, + .timeout_source = NULL, + }; + + if (cancellable) { + call_data->cancellable_id = g_cancellable_connect(cancellable, + G_CALLBACK(_fw_nft_call_cancelled_cb), + call_data, + NULL); + if (call_data->cancellable_id == 0) { + nm_log_dbg(LOGD_SHARING, "firewall: nft: already cancelled"); + nm_utils_error_set_cancelled(&error, FALSE, NULL); + _fw_nft_call_data_free(call_data, g_steal_pointer(&error)); + return; + } + } + + subprocess_launcher = + g_subprocess_launcher_new(G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE + | G_SUBPROCESS_FLAGS_STDERR_PIPE); + g_subprocess_launcher_set_environ(subprocess_launcher, NM_STRV_EMPTY()); + + call_data->subprocess = g_subprocess_launcher_spawnv(subprocess_launcher, + NM_MAKE_STRV(NFT_PATH, "-f", "-"), + &error); + + if (!call_data->subprocess) { + nm_log_dbg(LOGD_SHARING, "firewall: nft: spawning nft failed: %s", error->message); + _fw_nft_call_data_free(call_data, g_steal_pointer(&error)); + return; + } + + call_data->identifier = g_strdup(g_subprocess_get_identifier(call_data->subprocess)); + + nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: communicate with nft", call_data->identifier); + + nm_shutdown_wait_obj_register_object(call_data->task, "nft-call"); + + call_data->intern_cancellable = g_cancellable_new(), + + g_subprocess_communicate_async(call_data->subprocess, + stdin_buf, + call_data->intern_cancellable, + _fw_nft_call_communicate_cb, + call_data); + + call_data->timeout_source = + nm_g_source_attach(nm_g_timeout_source_new((NM_SHUTDOWN_TIMEOUT_MS * 2) / 3, + G_PRIORITY_DEFAULT, + _fw_nft_call_timeout_cb, + call_data, + NULL), + g_task_get_context(call_data->task)); +} + +static gboolean +_fw_nft_call_finish(GAsyncResult *result, GError **error) +{ + g_return_val_if_fail(nm_g_task_is_valid(result, NULL, _fw_nft_call), FALSE); + + return g_task_propagate_boolean(G_TASK(result), error); +} + +/*****************************************************************************/ + +typedef struct { + GMainLoop *loop; + GError ** error; + gboolean success; +} FwNftCallSyncData; + +static void +_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); + g_main_loop_quit(data->loop); +} + +static gboolean +_fw_nft_call_sync(GBytes *stdin_buf, GError **error) +{ + nm_auto_pop_and_unref_gmaincontext GMainContext *main_context = + nm_g_main_context_push_thread_default(g_main_context_new()); + nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(main_context, FALSE); + FwNftCallSyncData data = (FwNftCallSyncData){ + .loop = main_loop, + .error = error, + }; + + _fw_nft_call(stdin_buf, NULL, _fw_nft_call_sync_done, &data); + + g_main_loop_run(main_loop); + return data.success; +} + +/*****************************************************************************/ + +static void +_fw_nft_set(gboolean add, 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); + + if (add) { + _append(&strbuf, + "add chain ip %s nat_postrouting {" + " type nat hook postrouting priority 100; policy accept; " + "};", + table_name); + _append(&strbuf, + "add rule ip %s nat_postrouting ip saddr %s ip daddr != %s masquerade;", + table_name, + str_subnet, + str_subnet); + + /* 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_forward {" + " type filter hook forward priority 0; policy accept; " + "};", + table_name); + _append(&strbuf, + "add rule ip %s filter_forward ip daddr %s oifname \"%s\" " + " ct state { established, related } accept;", + table_name, + str_subnet, + ip_iface); + _append(&strbuf, + "add rule ip %s filter_forward ip saddr %s iifname \"%s\" accept;", + table_name, + str_subnet, + ip_iface); + _append(&strbuf, + "add rule ip %s filter_forward iifname \"%s\" oifname \"%s\" accept;", + table_name, + ip_iface, + ip_iface); + _append(&strbuf, + "add rule ip %s filter_forward iifname \"%s\" reject;", + table_name, + ip_iface); + _append(&strbuf, + "add rule ip %s filter_forward oifname \"%s\" reject;", + table_name, + 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 = g_bytes_new_static(nm_str_buf_get_str(&strbuf), strbuf.len); + + _fw_nft_call_sync(stdin_buf, NULL); +} + +/*****************************************************************************/ + +struct _NMFirewallConfig { + char * ip_iface; + in_addr_t addr; + guint8 plen; +}; + +NMFirewallConfig * +nm_firewall_config_new(const char *ip_iface, in_addr_t addr, guint8 plen) +{ + NMFirewallConfig *self; + + nm_assert(ip_iface); + nm_assert(addr != 0u); + nm_assert(plen <= 32); + + self = g_slice_new(NMFirewallConfig); + *self = (NMFirewallConfig){ + .ip_iface = g_strdup(ip_iface), + .addr = addr, + .plen = plen, + }; + return self; +} + +void +nm_firewall_config_free(NMFirewallConfig *self) +{ + if (!self) + return; + + g_free(self->ip_iface); + nm_g_slice_free(self); +} + +void +nm_firewall_config_apply(NMFirewallConfig *self, gboolean shared) +{ + 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); + break; + case NM_FIREWALL_BACKEND_NFTABLES: + _fw_nft_set(shared, self->ip_iface, self->addr, self->plen); + break; + case NM_FIREWALL_BACKEND_NONE: + break; + default: + nm_assert_not_reached(); + break; + } +} + +/*****************************************************************************/ + +static NMFirewallBackend +_firewall_backend_detect(void) +{ + if (g_file_test(NFT_PATH, G_FILE_TEST_IS_EXECUTABLE)) + return NM_FIREWALL_BACKEND_NFTABLES; + if (g_file_test(IPTABLES_PATH, G_FILE_TEST_IS_EXECUTABLE)) + return NM_FIREWALL_BACKEND_IPTABLES; + + return NM_FIREWALL_BACKEND_NFTABLES; +} + +NMFirewallBackend +nm_firewall_utils_get_backend(void) +{ + static int backend = NM_FIREWALL_BACKEND_UNKNOWN; + int b; + +again: + b = g_atomic_int_get(&backend); + if (b == NM_FIREWALL_BACKEND_UNKNOWN) { + gs_free char *conf_value = NULL; + gboolean detect; + int i; + + conf_value = + nm_config_data_get_value(NM_CONFIG_GET_DATA_ORIG, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_FIREWALL_BACKEND, + NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); + + if (conf_value) { + for (i = 0; i < (int) G_N_ELEMENTS(FirewallBackends); i++) { + if (!g_ascii_strcasecmp(conf_value, FirewallBackends[i].name)) { + b = (i + 1); + break; + } + } + } + + detect = (b == NM_FIREWALL_BACKEND_UNKNOWN); + if (detect) + b = _firewall_backend_detect(); + + nm_assert(NM_IN_SET(b, + NM_FIREWALL_BACKEND_NONE, + NM_FIREWALL_BACKEND_IPTABLES, + NM_FIREWALL_BACKEND_NFTABLES)); + + if (!g_atomic_int_compare_and_exchange(&backend, NM_FIREWALL_BACKEND_UNKNOWN, b)) + goto again; + + nm_log_dbg(LOGD_SHARING, + "firewall: use %s backend%s%s%s%s%s%s%s", + FirewallBackends[b - 1].name, + NM_PRINT_FMT_QUOTED(FirewallBackends[b - 1].path, + " (", + FirewallBackends[b - 1].path, + ")", + ""), + detect ? " (detected)" : "", + NM_PRINT_FMT_QUOTED(detect && conf_value, + " (invalid setting \"", + conf_value, + "\")", + "")); + } + + nm_assert(NM_IN_SET(b, + NM_FIREWALL_BACKEND_NONE, + NM_FIREWALL_BACKEND_IPTABLES, + NM_FIREWALL_BACKEND_NFTABLES)); + return b; +} diff --git a/src/core/nm-firewall-utils.h b/src/core/nm-firewall-utils.h new file mode 100644 index 00000000..3d6c8a69 --- /dev/null +++ b/src/core/nm-firewall-utils.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2004 - 2016 Red Hat, Inc. + * Copyright (C) 2005 - 2008 Novell, Inc. + */ + +#ifndef __NM_FIREWALL_UTILS_H__ +#define __NM_FIREWALL_UTILS_H__ + +typedef enum { + NM_FIREWALL_BACKEND_UNKNOWN, + NM_FIREWALL_BACKEND_NONE, + NM_FIREWALL_BACKEND_IPTABLES, + NM_FIREWALL_BACKEND_NFTABLES, +} NMFirewallBackend; + +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); + +void nm_firewall_config_free(NMFirewallConfig *self); + +void nm_firewall_config_apply(NMFirewallConfig *self, gboolean shared); + +#endif /* __NM_FIREWALL_UTILS_H__ */ diff --git a/src/core/nm-firewalld-manager.c b/src/core/nm-firewalld-manager.c new file mode 100644 index 00000000..7866894a --- /dev/null +++ b/src/core/nm-firewalld-manager.c @@ -0,0 +1,669 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2011 - 2015 Red Hat, Inc. + */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-firewalld-manager.h" + +#include "libnm-glib-aux/nm-dbus-aux.h" +#include "c-list/src/c-list.h" + +#include "NetworkManagerUtils.h" +#include "nm-dbus-manager.h" + +#define FIREWALL_DBUS_SERVICE "org.fedoraproject.FirewallD1" +#define FIREWALL_DBUS_PATH "/org/fedoraproject/FirewallD1" +#define FIREWALL_DBUS_INTERFACE "org.fedoraproject.FirewallD1" +#define FIREWALL_DBUS_INTERFACE_ZONE "org.fedoraproject.FirewallD1.zone" + +/*****************************************************************************/ + +enum { STATE_CHANGED, LAST_SIGNAL }; + +static guint signals[LAST_SIGNAL] = {0}; + +typedef struct { + GDBusConnection *dbus_connection; + + GCancellable *get_name_owner_cancellable; + + CList pending_calls; + + char *name_owner; + + guint reloaded_id; + guint name_owner_changed_id; + + bool dbus_inited : 1; +} NMFirewalldManagerPrivate; + +struct _NMFirewalldManager { + GObject parent; + NMFirewalldManagerPrivate _priv; +}; + +struct _NMFirewalldManagerClass { + GObjectClass parent; +}; + +G_DEFINE_TYPE(NMFirewalldManager, nm_firewalld_manager, G_TYPE_OBJECT) + +#define NM_FIREWALLD_MANAGER_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMFirewalldManager, NM_IS_FIREWALLD_MANAGER) + +/*****************************************************************************/ + +NM_DEFINE_SINGLETON_GETTER(NMFirewalldManager, nm_firewalld_manager_get, NM_TYPE_FIREWALLD_MANAGER); + +/*****************************************************************************/ + +typedef enum { + OPS_TYPE_ADD = 1, + OPS_TYPE_CHANGE, + OPS_TYPE_REMOVE, +} OpsType; + +struct _NMFirewalldManagerCallId { + CList lst; + + NMFirewalldManager *self; + + char *iface; + + NMFirewalldManagerAddRemoveCallback callback; + gpointer user_data; + + union { + struct { + GCancellable *cancellable; + GVariant * arg; + } dbus; + struct { + guint id; + } idle; + }; + + OpsType ops_type; + + bool is_idle : 1; +}; + +/*****************************************************************************/ + +static const char * +_ops_type_to_string(OpsType ops_type) +{ + switch (ops_type) { + case OPS_TYPE_ADD: + return "add"; + case OPS_TYPE_REMOVE: + return "remove"; + case OPS_TYPE_CHANGE: + return "change"; + } + nm_assert_not_reached(); + return NULL; +} + +#define _NMLOG_DOMAIN LOGD_FIREWALL +#define _NMLOG_PREFIX_NAME "firewalld" +#define _NMLOG(level, call_id, ...) \ + G_STMT_START \ + { \ + if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \ + NMFirewalldManagerCallId *_call_id = (call_id); \ + char _prefix_name[30]; \ + char _prefix_info[100]; \ + \ + _nm_log((level), \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ + "%s: %s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + (self) != singleton_instance ? ({ \ + g_snprintf(_prefix_name, \ + sizeof(_prefix_name), \ + "%s[" NM_HASH_OBFUSCATE_PTR_FMT "]", \ + ""_NMLOG_PREFIX_NAME, \ + NM_HASH_OBFUSCATE_PTR(self)); \ + _prefix_name; \ + }) \ + : _NMLOG_PREFIX_NAME, \ + _call_id ? ({ \ + g_snprintf(_prefix_info, \ + sizeof(_prefix_info), \ + "[" NM_HASH_OBFUSCATE_PTR_FMT ",%s%s:%s%s%s]: ", \ + NM_HASH_OBFUSCATE_PTR(_call_id), \ + _ops_type_to_string(_call_id->ops_type), \ + _call_id->is_idle ? "*" : "", \ + NM_PRINT_FMT_QUOTE_STRING(_call_id->iface)); \ + _prefix_info; \ + }) \ + : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +/*****************************************************************************/ + +static void +_signal_emit_state_changed(NMFirewalldManager *self, NMFirewalldManagerStateChangedType signal_type) +{ + g_signal_emit(self, signals[STATE_CHANGED], 0, (int) signal_type); +} + +/*****************************************************************************/ + +static gboolean +_get_running(NMFirewalldManagerPrivate *priv) +{ + /* when starting, we need to asynchronously check whether there is + * a name owner. During that time we optimistically assume that the + * service is indeed running. That is the time when we queue the + * requests, and they will be started once the get-name-owner call + * returns. */ + return priv->name_owner || (priv->dbus_connection && !priv->dbus_inited); +} + +gboolean +nm_firewalld_manager_get_running(NMFirewalldManager *self) +{ + g_return_val_if_fail(NM_IS_FIREWALLD_MANAGER(self), FALSE); + + return _get_running(NM_FIREWALLD_MANAGER_GET_PRIVATE(self)); +} + +/*****************************************************************************/ + +static NMFirewalldManagerCallId * +_cb_info_create(NMFirewalldManager * self, + OpsType ops_type, + const char * iface, + const char * zone, + NMFirewalldManagerAddRemoveCallback callback, + gpointer user_data) +{ + NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + NMFirewalldManagerCallId * call_id; + + call_id = g_slice_new0(NMFirewalldManagerCallId); + + call_id->self = g_object_ref(self); + call_id->ops_type = ops_type; + call_id->iface = g_strdup(iface); + call_id->callback = callback; + call_id->user_data = user_data; + + if (_get_running(priv)) { + call_id->is_idle = FALSE; + call_id->dbus.arg = g_variant_new("(ss)", zone ?: "", iface); + } else + call_id->is_idle = TRUE; + + c_list_link_tail(&priv->pending_calls, &call_id->lst); + + return call_id; +} + +static void +_cb_info_complete(NMFirewalldManagerCallId *call_id, GError *error) +{ + c_list_unlink(&call_id->lst); + + if (call_id->callback) + call_id->callback(call_id->self, call_id, error, call_id->user_data); + + if (call_id->is_idle) + nm_clear_g_source(&call_id->idle.id); + else { + nm_g_variant_unref(call_id->dbus.arg); + nm_clear_g_cancellable(&call_id->dbus.cancellable); + } + g_free(call_id->iface); + g_object_unref(call_id->self); + nm_g_slice_free(call_id); +} + +static gboolean +_handle_idle_cb(gpointer user_data) +{ + NMFirewalldManager * self; + NMFirewalldManagerCallId *call_id = user_data; + + nm_assert(call_id); + nm_assert(NM_IS_FIREWALLD_MANAGER(call_id->self)); + nm_assert(call_id->is_idle); + nm_assert(c_list_contains(&NM_FIREWALLD_MANAGER_GET_PRIVATE(call_id->self)->pending_calls, + &call_id->lst)); + + self = call_id->self; + + _LOGD(call_id, "complete: fake success"); + + call_id->idle.id = 0; + + _cb_info_complete(call_id, NULL); + return G_SOURCE_REMOVE; +} + +static gboolean +_handle_idle_start(NMFirewalldManager *self, NMFirewalldManagerCallId *call_id) +{ + if (!call_id->callback) { + /* if the user did not provide a callback and firewalld is not running, + * there is no point in scheduling an idle-request to fake success. Just + * return right away. */ + _LOGD(call_id, "complete: drop request simulating success"); + _cb_info_complete(call_id, NULL); + return FALSE; + } + call_id->idle.id = g_idle_add(_handle_idle_cb, call_id); + return TRUE; +} + +static void +_handle_dbus_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMFirewalldManager * self; + NMFirewalldManagerCallId *call_id; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *ret = NULL; + + ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error); + + if (!ret && nm_utils_error_is_cancelled(error)) + return; + + call_id = user_data; + + nm_assert(call_id); + nm_assert(NM_IS_FIREWALLD_MANAGER(call_id->self)); + nm_assert(!call_id->is_idle); + nm_assert(c_list_contains(&NM_FIREWALLD_MANAGER_GET_PRIVATE(call_id->self)->pending_calls, + &call_id->lst)); + + self = call_id->self; + + if (error) { + const char *non_error = NULL; + + g_dbus_error_strip_remote_error(error); + + switch (call_id->ops_type) { + case OPS_TYPE_ADD: + case OPS_TYPE_CHANGE: + non_error = "ZONE_ALREADY_SET"; + break; + case OPS_TYPE_REMOVE: + non_error = "UNKNOWN_INTERFACE"; + break; + } + if (error->message && non_error && g_str_has_prefix(error->message, non_error) + && NM_IN_SET(error->message[strlen(non_error)], '\0', ':')) { + _LOGD(call_id, "complete: request failed with a non-error (%s)", error->message); + + /* The operation failed with an error reason that we don't want + * to propagate. Instead, signal success. */ + g_clear_error(&error); + } else + _LOGW(call_id, "complete: request failed (%s)", error->message); + } else + _LOGD(call_id, "complete: success"); + + g_clear_object(&call_id->dbus.cancellable); + + _cb_info_complete(call_id, error); +} + +static void +_handle_dbus_start(NMFirewalldManager *self, NMFirewalldManagerCallId *call_id) +{ + NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + const char * dbus_method = NULL; + GVariant * arg; + + nm_assert(call_id); + nm_assert(priv->name_owner); + nm_assert(!call_id->is_idle); + nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst)); + + switch (call_id->ops_type) { + case OPS_TYPE_ADD: + dbus_method = "addInterface"; + break; + case OPS_TYPE_CHANGE: + dbus_method = "changeZoneOfInterface"; + break; + case OPS_TYPE_REMOVE: + dbus_method = "removeInterface"; + break; + } + nm_assert(dbus_method); + + arg = g_steal_pointer(&call_id->dbus.arg); + + nm_assert(arg && g_variant_is_floating(arg)); + + nm_assert(!call_id->dbus.cancellable); + + call_id->dbus.cancellable = g_cancellable_new(); + + g_dbus_connection_call(priv->dbus_connection, + priv->name_owner, + FIREWALL_DBUS_PATH, + FIREWALL_DBUS_INTERFACE_ZONE, + dbus_method, + arg, + NULL, + G_DBUS_CALL_FLAGS_NONE, + 10000, + call_id->dbus.cancellable, + _handle_dbus_cb, + call_id); +} + +static NMFirewalldManagerCallId * +_start_request(NMFirewalldManager * self, + OpsType ops_type, + const char * iface, + const char * zone, + NMFirewalldManagerAddRemoveCallback callback, + gpointer user_data) +{ + NMFirewalldManagerPrivate *priv; + NMFirewalldManagerCallId * call_id; + + g_return_val_if_fail(NM_IS_FIREWALLD_MANAGER(self), NULL); + g_return_val_if_fail(iface && *iface, NULL); + + priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + + call_id = _cb_info_create(self, ops_type, iface, zone, callback, user_data); + + _LOGD(call_id, + "firewall zone %s %s:%s%s%s%s", + _ops_type_to_string(call_id->ops_type), + iface, + NM_PRINT_FMT_QUOTED(zone, "\"", zone, "\"", "default"), + call_id->is_idle ? " (not running, simulate success)" + : (!priv->name_owner ? " (waiting to initialize)" : "")); + + if (!call_id->is_idle) { + if (priv->name_owner) + _handle_dbus_start(self, call_id); + if (!call_id->callback) { + /* if the user did not provide a callback, the call_id is useless. + * Especially, the user cannot use the call-id to cancel the request, + * because he cannot know whether the request is still pending. + * + * Hence, returning %NULL doesn't mean that the request could not be started + * (this function never fails and always starts a request). */ + return NULL; + } + } else { + if (!_handle_idle_start(self, call_id)) { + /* if the user did not provide a callback and firewalld is not running, + * there is no point in scheduling an idle-request to fake success. Just + * return right away. */ + return NULL; + } + } + + return call_id; +} + +NMFirewalldManagerCallId * +nm_firewalld_manager_add_or_change_zone(NMFirewalldManager *self, + const char * iface, + const char * zone, + gboolean add, /* TRUE == add, FALSE == change */ + NMFirewalldManagerAddRemoveCallback callback, + gpointer user_data) +{ + return _start_request(self, + add ? OPS_TYPE_ADD : OPS_TYPE_CHANGE, + iface, + zone, + callback, + user_data); +} + +NMFirewalldManagerCallId * +nm_firewalld_manager_remove_from_zone(NMFirewalldManager * self, + const char * iface, + const char * zone, + NMFirewalldManagerAddRemoveCallback callback, + gpointer user_data) +{ + return _start_request(self, OPS_TYPE_REMOVE, iface, zone, callback, user_data); +} + +void +nm_firewalld_manager_cancel_call(NMFirewalldManagerCallId *call_id) +{ + NMFirewalldManager * self; + NMFirewalldManagerPrivate *priv; + gs_free_error GError *error = NULL; + + g_return_if_fail(call_id); + g_return_if_fail(NM_IS_FIREWALLD_MANAGER(call_id->self)); + g_return_if_fail(!c_list_is_empty(&call_id->lst)); + + self = call_id->self; + priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + + nm_assert(c_list_contains(&priv->pending_calls, &call_id->lst)); + + nm_utils_error_set_cancelled(&error, FALSE, "NMFirewalldManager"); + + _LOGD(call_id, "complete: cancel (%s)", error->message); + + _cb_info_complete(call_id, error); +} + +/*****************************************************************************/ + +static void +name_owner_changed(NMFirewalldManager *self, const char *owner) +{ + _nm_unused gs_unref_object NMFirewalldManager *self_keep_alive = g_object_ref(self); + NMFirewalldManagerPrivate * priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + gboolean was_running; + gboolean now_running; + gboolean just_initied; + gboolean name_owner_changed; + + owner = nm_str_not_empty(owner); + + if (!owner) + _LOGT(NULL, "D-Bus name for firewalld has no owner (firewall stopped)"); + else + _LOGT(NULL, "D-Bus name for firewalld has owner %s (firewall started)", owner); + + was_running = _get_running(priv); + just_initied = !priv->dbus_inited; + + priv->dbus_inited = TRUE; + name_owner_changed = nm_utils_strdup_reset(&priv->name_owner, owner); + + now_running = _get_running(priv); + + if (just_initied) { + NMFirewalldManagerCallId *call_id_safe; + NMFirewalldManagerCallId *call_id; + + /* We kick of the requests that we have pending. Note that this is + * entirely asynchronous and also we don't invoke any callbacks for + * the user. + * Even _handle_idle_start() just schedules an idle handler. That is, + * because we don't want to callback to the user before emitting the + * DISCONNECTED signal below. Also, emitting callbacks means the user + * can call back to modify the list of pending-calls and we'd have + * to handle reentrancy. */ + c_list_for_each_entry_safe (call_id, call_id_safe, &priv->pending_calls, lst) { + nm_assert(!call_id->is_idle); + nm_assert(call_id->dbus.arg); + + if (priv->name_owner) { + _LOGD(call_id, "initalizing: make D-Bus call"); + _handle_dbus_start(self, call_id); + } else { + /* we don't want to invoke callbacks to the user right away. That is because + * the user might schedule/cancel more calls, which messes up the order. + * + * Instead, convert the pending calls to idle requests... */ + nm_clear_pointer(&call_id->dbus.arg, g_variant_unref); + call_id->is_idle = TRUE; + _LOGD(call_id, "initializing: fake success on idle"); + _handle_idle_start(self, call_id); + } + } + } + + if (just_initied) + _signal_emit_state_changed(self, NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_INITIALIZED); + else if (was_running != now_running || name_owner_changed) + _signal_emit_state_changed(self, + NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_NAME_OWNER_CHANGED); +} + +static void +reloaded_cb(GDBusConnection *connection, + const char * sender_name, + const char * object_path, + const char * interface_name, + const char * signal_name, + GVariant * parameters, + gpointer user_data) +{ + NMFirewalldManager * self = user_data; + NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + + if (!nm_streq0(sender_name, priv->name_owner)) + return; + + _LOGT(NULL, "reloaded signal received"); + _signal_emit_state_changed(self, NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_RELOADED); +} + +static void +name_owner_changed_cb(GDBusConnection *connection, + const char * sender_name, + const char * object_path, + const char * interface_name, + const char * signal_name, + GVariant * parameters, + gpointer user_data) +{ + NMFirewalldManager *self = user_data; + const char * new_owner; + + if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) + return; + + g_variant_get(parameters, "(&s&s&s)", NULL, NULL, &new_owner); + + name_owner_changed(self, new_owner); +} + +static void +get_name_owner_cb(const char *name_owner, GError *error, gpointer user_data) +{ + NMFirewalldManager * self; + NMFirewalldManagerPrivate *priv; + + if (nm_utils_error_is_cancelled(error)) + return; + + self = user_data; + priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + + g_clear_object(&priv->get_name_owner_cancellable); + + name_owner_changed(self, name_owner); +} + +/*****************************************************************************/ + +static void +nm_firewalld_manager_init(NMFirewalldManager *self) +{ + NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + + c_list_init(&priv->pending_calls); + + priv->dbus_connection = nm_g_object_ref(NM_MAIN_DBUS_CONNECTION_GET); + + if (!priv->dbus_connection) { + _LOGD(NULL, "no D-Bus connection"); + return; + } + + priv->reloaded_id = g_dbus_connection_signal_subscribe(priv->dbus_connection, + FIREWALL_DBUS_SERVICE, + FIREWALL_DBUS_INTERFACE, + "Reloaded", + FIREWALL_DBUS_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + reloaded_cb, + self, + NULL); + + priv->name_owner_changed_id = + nm_dbus_connection_signal_subscribe_name_owner_changed(priv->dbus_connection, + FIREWALL_DBUS_SERVICE, + name_owner_changed_cb, + self, + NULL); + + priv->get_name_owner_cancellable = g_cancellable_new(); + nm_dbus_connection_call_get_name_owner(priv->dbus_connection, + FIREWALL_DBUS_SERVICE, + -1, + priv->get_name_owner_cancellable, + get_name_owner_cb, + self); +} + +static void +dispose(GObject *object) +{ + NMFirewalldManager * self = NM_FIREWALLD_MANAGER(object); + NMFirewalldManagerPrivate *priv = NM_FIREWALLD_MANAGER_GET_PRIVATE(self); + + /* as every pending operation takes a reference to the manager, + * we don't expect pending operations at this point. */ + nm_assert(c_list_is_empty(&priv->pending_calls)); + + nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->reloaded_id); + nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id); + + nm_clear_g_cancellable(&priv->get_name_owner_cancellable); + + G_OBJECT_CLASS(nm_firewalld_manager_parent_class)->dispose(object); + + g_clear_object(&priv->dbus_connection); +} + +static void +nm_firewalld_manager_class_init(NMFirewalldManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->dispose = dispose; + + signals[STATE_CHANGED] = g_signal_new(NM_FIREWALLD_MANAGER_STATE_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT /* signal-type */); +} diff --git a/src/core/nm-firewalld-manager.h b/src/core/nm-firewalld-manager.h new file mode 100644 index 00000000..1f76beba --- /dev/null +++ b/src/core/nm-firewalld-manager.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2011 Red Hat, Inc. + */ + +#ifndef __NM_FIREWALLD_MANAGER_H__ +#define __NM_FIREWALLD_MANAGER_H__ + +#define NM_TYPE_FIREWALLD_MANAGER (nm_firewalld_manager_get_type()) +#define NM_FIREWALLD_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_FIREWALLD_MANAGER, NMFirewalldManager)) +#define NM_FIREWALLD_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_FIREWALLD_MANAGER, NMFirewalldManagerClass)) +#define NM_IS_FIREWALLD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_FIREWALLD_MANAGER)) +#define NM_IS_FIREWALLD_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_FIREWALLD_MANAGER)) +#define NM_FIREWALLD_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_FIREWALLD_MANAGER, NMFirewalldManagerClass)) + +#define NM_FIREWALLD_MANAGER_STATE_CHANGED "state-changed" + +typedef enum { + NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_INITIALIZED, + NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_NAME_OWNER_CHANGED, + NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_RELOADED, +} NMFirewalldManagerStateChangedType; + +typedef struct _NMFirewalldManagerCallId NMFirewalldManagerCallId; + +typedef struct _NMFirewalldManager NMFirewalldManager; +typedef struct _NMFirewalldManagerClass NMFirewalldManagerClass; + +GType nm_firewalld_manager_get_type(void); + +NMFirewalldManager *nm_firewalld_manager_get(void); + +gboolean nm_firewalld_manager_get_running(NMFirewalldManager *self); + +typedef void (*NMFirewalldManagerAddRemoveCallback)(NMFirewalldManager * self, + NMFirewalldManagerCallId *call_id, + GError * error, + gpointer user_data); + +NMFirewalldManagerCallId * +nm_firewalld_manager_add_or_change_zone(NMFirewalldManager * mgr, + const char * iface, + const char * zone, + gboolean add, + NMFirewalldManagerAddRemoveCallback callback, + gpointer user_data); +NMFirewalldManagerCallId * +nm_firewalld_manager_remove_from_zone(NMFirewalldManager * mgr, + const char * iface, + const char * zone, + NMFirewalldManagerAddRemoveCallback callback, + gpointer user_data); + +void nm_firewalld_manager_cancel_call(NMFirewalldManagerCallId *call_id); + +#endif /* __NM_FIREWALLD_MANAGER_H__ */ diff --git a/src/core/nm-hostname-manager.c b/src/core/nm-hostname-manager.c index c99c8326..91e9baaa 100644 --- a/src/core/nm-hostname-manager.c +++ b/src/core/nm-hostname-manager.c @@ -14,11 +14,11 @@ #include #endif -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" @@ -182,7 +182,7 @@ nm_hostname_manager_read_hostname(NMHostnameManager *self) #if defined(HOSTNAME_PERSIST_GENTOO) hostname = read_hostname_gentoo(HOSTNAME_FILE); #elif defined(HOSTNAME_PERSIST_SLACKWARE) - hostname = read_hostname_slackware(HOSTNAME_FILE); + hostname = read_hostname_slackware(HOSTNAME_FILE); #else if (g_file_get_contents(HOSTNAME_FILE, &hostname, NULL, NULL)) g_strchomp(hostname); diff --git a/src/core/nm-iface-helper.c b/src/core/nm-iface-helper.c index b6e9981d..296bf091 100644 --- a/src/core/nm-iface-helper.c +++ b/src/core/nm-iface-helper.c @@ -16,19 +16,19 @@ #include #include -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-c-list.h" #include "main-utils.h" #include "NetworkManagerUtils.h" -#include "platform/nm-linux-platform.h" -#include "nm-platform/nm-platform-utils.h" +#include "libnm-platform/nm-linux-platform.h" +#include "libnm-platform/nm-platform-utils.h" #include "dhcp/nm-dhcp-manager.h" #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-ip6-config.h" -#include "systemd/nm-sd.h" +#include "libnm-systemd-core/nm-sd.h" #if !defined(NM_DIST_VERSION) #define NM_DIST_VERSION VERSION @@ -668,6 +668,7 @@ main(int argc, char *argv[]) global_opt.uuid, RT_TABLE_MAIN, global_opt.priority_v4, + NM_DHCP_CLIENT_FLAGS_NONE, !!global_opt.dhcp4_hostname, global_opt.dhcp4_hostname, global_opt.dhcp4_fqdn, diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c index 608b7fc8..52a8faa7 100644 --- a/src/core/nm-ip4-config.c +++ b/src/core/nm-ip4-config.c @@ -12,14 +12,14 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-utils.h" -#include "platform/nmp-object.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nm-platform-utils.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-object.h" /*****************************************************************************/ @@ -163,6 +163,11 @@ _nm_ip_config_add_obj(NMDedupMultiIndex * multi_idx, obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source; modified = TRUE; } + if (!obj_new->ip_route.is_external && obj_old->ip_route.is_external) { + obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); + obj_new_stackinit.ip_route.is_external = FALSE; + modified = TRUE; + } break; default: nm_assert_not_reached(); @@ -507,22 +512,6 @@ _notify_routes(NMIP4Config *self) /*****************************************************************************/ -static int -sort_captured_addresses(const CList *lst_a, const CList *lst_b, gconstpointer user_data) -{ - const NMPlatformIP4Address *addr_a = - NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_a, NMDedupMultiEntry, lst_entries)->obj); - const NMPlatformIP4Address *addr_b = - NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_b, NMDedupMultiEntry, lst_entries)->obj); - - nm_assert(addr_a); - nm_assert(addr_b); - - /* Primary addresses first */ - return NM_FLAGS_HAS(addr_a->n_ifa_flags, IFA_F_SECONDARY) - - NM_FLAGS_HAS(addr_b->n_ifa_flags, IFA_F_SECONDARY); -} - NMIP4Config * nm_ip4_config_clone(const NMIP4Config *self) { @@ -566,9 +555,6 @@ nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int if NULL)) nm_assert_not_reached(); } - head_entry = nm_ip4_config_lookup_addresses(self); - nm_assert(head_entry); - nm_dedup_multi_head_entry_sort(head_entry, sort_captured_addresses, NULL); _notify_addresses(self); } @@ -1977,6 +1963,26 @@ nm_ip_config_dump(const NMIPConfig *self, const char *detail, NMLogLevel level, /*****************************************************************************/ +gconstpointer +nm_ip_config_find_first_address(const NMIPConfig *self, NMPlatformMatchFlags match_flag) +{ + NMDedupMultiIter iter; + const NMPlatformIPAddress *address; + + g_return_val_if_fail(NM_IS_IP_CONFIG(self), NULL); + + nm_assert(!NM_FLAGS_ANY( + match_flag, + ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))); + + nm_ip_config_iter_ip_address_for_each (&iter, self, &address) { + if (nm_platform_ip_address_match(nm_ip_config_get_addr_family(self), address, match_flag)) + return address; + } + + return NULL; +} + void nm_ip4_config_reset_addresses(NMIP4Config *self) { @@ -3016,11 +3022,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_take_variant(value, g_variant_builder_end(&builder_data)); break; case PROP_NAMESERVERS: - g_value_take_variant(value, - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - priv->nameservers->data, - priv->nameservers->len, - sizeof(guint32))); + g_value_take_variant( + value, + nm_g_variant_new_au((const guint32 *) priv->nameservers->data, priv->nameservers->len)); break; case PROP_DOMAINS: nm_utils_g_value_set_strv(value, priv->domains); @@ -3045,11 +3049,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_take_variant(value, g_variant_builder_end(&builder_data)); break; case PROP_WINS_SERVERS: - g_value_take_variant(value, - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - priv->wins->data, - priv->wins->len, - sizeof(guint32))); + g_value_take_variant( + value, + nm_g_variant_new_au((const guint32 *) priv->wins->data, priv->wins->len)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -3147,44 +3149,40 @@ finalize(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_ip4_config = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_IP4_CONFIG, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Addresses", - "aau", - NM_IP4_CONFIG_ADDRESSES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AddressData", - "aa{sv}", - NM_IP4_CONFIG_ADDRESS_DATA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Gateway", "s", NM_IP4_CONFIG_GATEWAY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Routes", "aau", NM_IP4_CONFIG_ROUTES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("RouteData", - "aa{sv}", - NM_IP4_CONFIG_ROUTE_DATA), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses", + "aau", + NM_IP4_CONFIG_ADDRESSES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData", + "aa{sv}", + NM_IP4_CONFIG_ADDRESS_DATA), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP4_CONFIG_GATEWAY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes", "aau", NM_IP4_CONFIG_ROUTES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData", + "aa{sv}", + NM_IP4_CONFIG_ROUTE_DATA), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NameserverData", "aa{sv}", NM_IP4_CONFIG_NAMESERVER_DATA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Nameservers", - "au", - NM_IP4_CONFIG_NAMESERVERS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Domains", - "as", - NM_IP4_CONFIG_DOMAINS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Searches", - "as", - NM_IP4_CONFIG_SEARCHES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DnsOptions", - "as", - NM_IP4_CONFIG_DNS_OPTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DnsPriority", - "i", - NM_IP4_CONFIG_DNS_PRIORITY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers", + "au", + NM_IP4_CONFIG_NAMESERVERS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP4_CONFIG_DOMAINS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches", + "as", + NM_IP4_CONFIG_SEARCHES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions", + "as", + NM_IP4_CONFIG_DNS_OPTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority", + "i", + NM_IP4_CONFIG_DNS_PRIORITY), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServerData", "as", NM_IP4_CONFIG_WINS_SERVER_DATA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WinsServers", - "au", - NM_IP4_CONFIG_WINS_SERVERS), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServers", + "au", + NM_IP4_CONFIG_WINS_SERVERS), ), ), }; static void diff --git a/src/core/nm-ip4-config.h b/src/core/nm-ip4-config.h index a795e152..fdaa6d46 100644 --- a/src/core/nm-ip4-config.h +++ b/src/core/nm-ip4-config.h @@ -10,8 +10,8 @@ #include "nm-setting-ip4-config.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "platform/nmp-object.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-platform/nmp-object.h" #include "nm-ip-config.h" /*****************************************************************************/ @@ -664,4 +664,7 @@ nm_ip_config_intersect_alloc(const NMIPConfig *a, } } +gconstpointer nm_ip_config_find_first_address(const NMIPConfig * self, + NMPlatformMatchFlags match_flag); + #endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */ diff --git a/src/core/nm-ip6-config.c b/src/core/nm-ip6-config.c index 1e36050d..65e84737 100644 --- a/src/core/nm-ip6-config.c +++ b/src/core/nm-ip6-config.c @@ -13,13 +13,13 @@ #include #include -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-utils.h" -#include "platform/nmp-object.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" -#include "nm-core-internal.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-ip4-config.h" #include "ndisc/nm-ndisc.h" @@ -316,7 +316,7 @@ nm_ip6_config_capture(NMDedupMultiIndex * multi_idx, head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex); if (head_entry) { - nmp_cache_iter_for_each (&iter, head_entry, &plobj) { + nmp_cache_iter_for_each_reverse (&iter, head_entry, &plobj) { if (!_nm_ip_config_add_obj(priv->multi_idx, &priv->idx_ip6_addresses_, ifindex, @@ -328,11 +328,6 @@ nm_ip6_config_capture(NMDedupMultiIndex * multi_idx, NULL)) nm_assert_not_reached(); } - head_entry = nm_ip6_config_lookup_addresses(self); - nm_assert(head_entry); - nm_dedup_multi_head_entry_sort(head_entry, - sort_captured_addresses, - GINT_TO_POINTER(use_temporary)); _notify_addresses(self); } @@ -1628,28 +1623,6 @@ nm_ip6_config_lookup_address(const NMIP6Config *self, const struct in6_addr *add return entry ? NMP_OBJECT_CAST_IP6_ADDRESS(entry->obj) : NULL; } -const NMPlatformIP6Address * -nm_ip6_config_find_first_address(const NMIP6Config *self, NMPlatformMatchFlags match_flag) -{ - const NMPlatformIP6Address *addr; - NMDedupMultiIter iter; - - g_return_val_if_fail(NM_IS_IP6_CONFIG(self), NULL); - - nm_assert(!NM_FLAGS_ANY( - match_flag, - ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))); - - nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY)); - nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)); - - nm_ip_config_iter_ip6_address_for_each (&iter, self, &addr) { - if (nm_platform_ip6_address_match(addr, match_flag)) - return addr; - } - return NULL; -} - /** * nm_ip6_config_has_dad_pending_addresses * @self: configuration containing the addresses to check @@ -2409,9 +2382,7 @@ nameservers_to_gvalue(GArray *array, GValue *value) struct in6_addr *addr; addr = &g_array_index(array, struct in6_addr, i++); - g_variant_builder_add(&builder, - "@ay", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, addr, 16, 1)); + g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(addr)); } g_value_take_variant(value, g_variant_builder_end(&builder)); @@ -2587,37 +2558,33 @@ finalize(GObject *object) static const NMDBusInterfaceInfoExtended interface_info_ip6_config = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_IP6_CONFIG, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Addresses", - "a(ayuay)", - NM_IP6_CONFIG_ADDRESSES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AddressData", - "aa{sv}", - NM_IP6_CONFIG_ADDRESS_DATA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Gateway", "s", NM_IP6_CONFIG_GATEWAY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Routes", - "a(ayuayu)", - NM_IP6_CONFIG_ROUTES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("RouteData", - "aa{sv}", - NM_IP6_CONFIG_ROUTE_DATA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Nameservers", - "aay", - NM_IP6_CONFIG_NAMESERVERS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Domains", - "as", - NM_IP6_CONFIG_DOMAINS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Searches", - "as", - NM_IP6_CONFIG_SEARCHES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DnsOptions", - "as", - NM_IP6_CONFIG_DNS_OPTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DnsPriority", - "i", - NM_IP6_CONFIG_DNS_PRIORITY), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses", + "a(ayuay)", + NM_IP6_CONFIG_ADDRESSES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData", + "aa{sv}", + NM_IP6_CONFIG_ADDRESS_DATA), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP6_CONFIG_GATEWAY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes", + "a(ayuayu)", + NM_IP6_CONFIG_ROUTES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData", + "aa{sv}", + NM_IP6_CONFIG_ROUTE_DATA), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers", + "aay", + NM_IP6_CONFIG_NAMESERVERS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP6_CONFIG_DOMAINS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches", + "as", + NM_IP6_CONFIG_SEARCHES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions", + "as", + NM_IP6_CONFIG_DNS_OPTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority", + "i", + NM_IP6_CONFIG_DNS_PRIORITY), ), ), }; static void diff --git a/src/core/nm-ip6-config.h b/src/core/nm-ip6-config.h index 398186da..8694ab0c 100644 --- a/src/core/nm-ip6-config.h +++ b/src/core/nm-ip6-config.h @@ -10,8 +10,8 @@ #include "nm-setting-ip6-config.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "platform/nmp-object.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-platform/nmp-object.h" #include "nm-ip-config.h" /*****************************************************************************/ @@ -125,8 +125,6 @@ void _nmtst_ip6_config_del_address(NMIP6Config *self, guint i); guint nm_ip6_config_get_num_addresses(const NMIP6Config *self); const NMPlatformIP6Address *nm_ip6_config_get_first_address(const NMIP6Config *self); const NMPlatformIP6Address *_nmtst_ip6_config_get_address(const NMIP6Config *self, guint i); -const NMPlatformIP6Address *nm_ip6_config_find_first_address(const NMIP6Config * self, - NMPlatformMatchFlags match_flag); gboolean nm_ip6_config_address_exists(const NMIP6Config *self, const NMPlatformIP6Address *address); const NMPlatformIP6Address *nm_ip6_config_lookup_address(const NMIP6Config * self, const struct in6_addr *addr); diff --git a/src/core/nm-keep-alive.c b/src/core/nm-keep-alive.c index 197e30ea..6275544c 100644 --- a/src/core/nm-keep-alive.c +++ b/src/core/nm-keep-alive.c @@ -8,7 +8,7 @@ #include "nm-keep-alive.h" #include "settings/nm-settings-connection.h" -#include "nm-glib-aux/nm-dbus-aux.h" +#include "libnm-glib-aux/nm-dbus-aux.h" /*****************************************************************************/ diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 5f9af7ac..f2ec040b 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -8,11 +8,12 @@ #include #include -#include "nm-glib-aux/nm-enum-utils.h" -#include "nm-core-internal.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" -#include "platform/nmp-object.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-enum-utils.h" +#include "libnm-glib-aux/nm-ref-string.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #include "NetworkManagerUtils.h" /*****************************************************************************/ @@ -52,7 +53,9 @@ struct _NML3ConfigData { GArray *wins; GArray *nis_servers; - char *nis_domain; + NMRefString *nis_domain; + NMRefString *proxy_pac_url; + NMRefString *proxy_pac_script; union { struct { @@ -130,6 +133,10 @@ struct _NML3ConfigData { NMTernary metered : 3; + NMTernary proxy_browser_only : 3; + + NMProxyConfigMethod proxy_method : 4; + NMSettingIP6ConfigPrivacy ip6_privacy : 4; bool is_sealed : 1; @@ -251,7 +258,7 @@ _garray_inaddr_get(GArray *arr, guint *out_len) } static gconstpointer -_garray_inaddr_at(GArray *arr, guint idx, gboolean IS_IPv4) +_garray_inaddr_at(GArray *arr, gboolean IS_IPv4, guint idx) { nm_assert(arr); nm_assert(idx < arr->len); @@ -507,7 +514,7 @@ nm_l3_config_data_log(const NML3ConfigData *self, _nm_utils_inet4_ntop(g_array_index(self->nis_servers, in_addr_t, i), sbuf_addr)); } if (self->nis_domain) - _L("nis-domain: %s", self->nis_domain); + _L("nis-domain: %s", self->nis_domain->str); } if (self->dhcp_lease_x[IS_IPv4]) { @@ -556,10 +563,20 @@ nm_l3_config_data_log(const NML3ConfigData *self, NULL))); } - if (self->metered != NM_TERNARY_DEFAULT) { + if (self->metered != NM_TERNARY_DEFAULT) _L("metered: %s", self->metered ? "yes" : "no"); - } + if (self->proxy_browser_only != NM_TERNARY_DEFAULT) + _L("proxy-browser-only: %s", self->proxy_browser_only ? "yes" : "no"); + + if (self->proxy_method != NM_PROXY_CONFIG_METHOD_UNKNOWN) + _L("proxy-method: %s", self->proxy_method == NM_PROXY_CONFIG_METHOD_AUTO ? "auto" : "none"); + + if (self->proxy_pac_url) + _L("proxy-pac-url: %s", self->proxy_pac_url->str); + + if (self->proxy_pac_script) + _L("proxy-pac-script: %s", self->proxy_pac_script->str); #undef _L } @@ -642,6 +659,8 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex) .llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT, .flags = NM_L3_CONFIG_DAT_FLAGS_NONE, .metered = NM_TERNARY_DEFAULT, + .proxy_browser_only = NM_TERNARY_DEFAULT, + .proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN, .route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, .route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, .source = NM_IP_CONFIG_SOURCE_UNKNOWN, @@ -742,7 +761,9 @@ nm_l3_config_data_unref(const NML3ConfigData *self) nm_dedup_multi_index_unref(mutable->multi_idx); - g_free(mutable->nis_domain); + nm_ref_string_unref(mutable->nis_domain); + nm_ref_string_unref(mutable->proxy_pac_url); + nm_ref_string_unref(mutable->proxy_pac_script); nm_g_slice_free(mutable); } @@ -796,8 +817,8 @@ nm_l3_config_data_lookup_route(const NML3ConfigData * self, int addr_family, const NMPlatformIPRoute *needle) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); - NMPObject obj_stack; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMPObject obj_stack; nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); @@ -895,7 +916,7 @@ nmtst_l3_config_data_get_obj_at(const NML3ConfigData *self, NMPObjectType obj_ty gboolean nm_l3_config_data_has_routes_with_type_local(const NML3ConfigData *self, int addr_family) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NML3ConfigData * self_mutable; NMDedupMultiIter iter; const NMPObject *obj; @@ -1178,7 +1199,7 @@ _l3_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObj return c < 0 ? obj_cur : obj_cmp; /* as last resort, compare pointers. */ - if (((uintptr_t)((void *) (obj_cmp))) < ((uintptr_t)((void *) (obj_cur)))) + if (((uintptr_t) ((void *) (obj_cmp))) < ((uintptr_t) ((void *) (obj_cur)))) return obj_cmp; } } @@ -1230,7 +1251,7 @@ nm_l3_config_data_add_route_full(NML3ConfigData * self, const NMPObject ** out_obj_new, gboolean * out_changed_best_default_route) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); nm_auto_nmpobj const NMPObject *obj_old = NULL; const NMPObject * obj_new_2; gboolean changed = FALSE; @@ -1364,6 +1385,14 @@ nm_l3_config_data_add_wins(NML3ConfigData *self, in_addr_t wins) return _garray_inaddr_add(&self->wins, AF_INET, &wins); } +const in_addr_t * +nm_l3_config_data_get_nis_servers(const NML3ConfigData *self, guint *out_len) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return _garray_inaddr_get(self->nis_servers, out_len); +} + gboolean nm_l3_config_data_add_nis_server(NML3ConfigData *self, in_addr_t nis_server) { @@ -1372,18 +1401,26 @@ nm_l3_config_data_add_nis_server(NML3ConfigData *self, in_addr_t nis_server) return _garray_inaddr_add(&self->nis_servers, AF_INET, &nis_server); } +const char * +nm_l3_config_data_get_nis_domain(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return nm_ref_string_get_str(self->nis_domain); +} + gboolean nm_l3_config_data_set_nis_domain(NML3ConfigData *self, const char *nis_domain) { nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - return nm_utils_strdup_reset(&self->nis_domain, nis_domain); + return nm_ref_string_reset_str(&self->nis_domain, nis_domain); } const char *const * nm_l3_config_data_get_domains(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); @@ -1452,10 +1489,57 @@ nm_l3_config_data_add_dns_option(NML3ConfigData *self, int addr_family, const ch return TRUE; } +const char *const * +nm_l3_config_data_get_dns_options(const NML3ConfigData *self, int addr_family, guint *out_len) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert_addr_family(addr_family); + nm_assert(out_len); + + return nm_strv_ptrarray_get_unsafe(self->dns_options_x[NM_IS_IPv4(addr_family)], out_len); +} + +gboolean +nm_l3_config_data_get_dns_priority(const NML3ConfigData *self, int addr_family, int *out_prio) +{ + switch (addr_family) { + case AF_UNSPEC: + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_4)) { + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)) { + NM_SET_OUT(out_prio, MIN(self->dns_priority_4, self->dns_priority_6)); + return TRUE; + } + NM_SET_OUT(out_prio, self->dns_priority_4); + return TRUE; + } + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)) { + NM_SET_OUT(out_prio, self->dns_priority_6); + return TRUE; + } + break; + case AF_INET: + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_4)) { + NM_SET_OUT(out_prio, self->dns_priority_4); + return TRUE; + } + break; + case AF_INET6: + if (NM_FLAGS_ANY(self->flags, NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY_6)) { + NM_SET_OUT(out_prio, self->dns_priority_6); + return TRUE; + } + break; + default: + nm_assert_not_reached(); + } + NM_SET_OUT(out_prio, 0); + return FALSE; +} + gboolean nm_l3_config_data_set_dns_priority(NML3ConfigData *self, int addr_family, int dns_priority) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NML3ConfigDatFlags has_dns_priority_flag = NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(IS_IPv4); @@ -1471,6 +1555,14 @@ nm_l3_config_data_set_dns_priority(NML3ConfigData *self, int addr_family, int dn return TRUE; } +NMSettingConnectionMdns +nm_l3_config_data_get_mdns(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->mdns; +} + gboolean nm_l3_config_data_set_mdns(NML3ConfigData *self, NMSettingConnectionMdns mdns) { @@ -1483,6 +1575,14 @@ nm_l3_config_data_set_mdns(NML3ConfigData *self, NMSettingConnectionMdns mdns) return TRUE; } +NMSettingConnectionLlmnr +nm_l3_config_data_get_llmnr(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->llmnr; +} + gboolean nm_l3_config_data_set_llmnr(NML3ConfigData *self, NMSettingConnectionLlmnr llmnr) { @@ -1509,7 +1609,7 @@ nm_l3_config_data_set_route_table_sync(NML3ConfigData * self, int addr_family, NMIPRouteTableSyncMode route_table_sync) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); nm_assert_addr_family(addr_family); @@ -1533,7 +1633,7 @@ gboolean nm_l3_config_data_set_metered(NML3ConfigData *self, NMTernary metered) { nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - nm_assert(NM_IN_SET(metered, NM_TERNARY_DEFAULT, NM_TERNARY_FALSE, NM_TERNARY_TRUE)); + nm_assert_is_ternary(metered); if (self->metered == metered) return FALSE; @@ -1619,6 +1719,83 @@ nm_l3_config_data_set_ip6_privacy(NML3ConfigData *self, NMSettingIP6ConfigPrivac return TRUE; } +NMProxyConfigMethod +nm_l3_config_data_get_proxy_method(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->proxy_method; +} + +gboolean +nm_l3_config_data_set_proxy_method(NML3ConfigData *self, NMProxyConfigMethod value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(NM_IN_SET(value, + NM_PROXY_CONFIG_METHOD_UNKNOWN, + NM_PROXY_CONFIG_METHOD_NONE, + NM_PROXY_CONFIG_METHOD_AUTO)); + + if (self->proxy_method == value) + return FALSE; + + self->proxy_method = value; + return TRUE; +} + +NMTernary +nm_l3_config_data_get_proxy_browser_only(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return self->proxy_browser_only; +} + +gboolean +nm_l3_config_data_set_proxy_browser_only(NML3ConfigData *self, NMTernary value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert_is_ternary(value); + + if (value == self->proxy_browser_only) + return FALSE; + + self->proxy_browser_only = value; + return TRUE; +} + +const char * +nm_l3_config_data_get_proxy_pac_url(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return nm_ref_string_get_str(self->proxy_pac_url); +} + +gboolean +nm_l3_config_data_set_proxy_pac_url(NML3ConfigData *self, const char *value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + + return nm_ref_string_reset_str(&self->proxy_pac_url, value); +} + +const char * +nm_l3_config_data_get_proxy_pac_script(const NML3ConfigData *self) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return nm_ref_string_get_str(self->proxy_pac_script); +} + +gboolean +nm_l3_config_data_set_proxy_pac_script(NML3ConfigData *self, const char *value) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + + return nm_ref_string_reset_str(&self->proxy_pac_script, value); +} + gboolean nm_l3_config_data_get_ndisc_hop_limit(const NML3ConfigData *self, int *out_val) { @@ -1780,13 +1957,16 @@ _dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObje } int -nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b) +nm_l3_config_data_cmp_full(const NML3ConfigData *a, + const NML3ConfigData *b, + NML3ConfigCmpFlags cmp_flags) { int IS_IPv4; NM_CMP_SELF(a, b); - NM_CMP_DIRECT(a->ifindex, b->ifindex); + if (!NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX)) + NM_CMP_DIRECT(a->ifindex, b->ifindex); NM_CMP_DIRECT(a->flags, b->flags); @@ -1823,12 +2003,16 @@ nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b) NM_CMP_RETURN(_garray_inaddr_cmp(a->wins, b->wins, AF_INET)); NM_CMP_RETURN(_garray_inaddr_cmp(a->nis_servers, b->nis_servers, AF_INET)); - NM_CMP_FIELD_STR0(a, b, nis_domain); + NM_CMP_DIRECT_REF_STRING(a->nis_domain, b->nis_domain); NM_CMP_DIRECT(a->mdns, b->mdns); NM_CMP_DIRECT(a->llmnr, b->llmnr); NM_CMP_DIRECT(a->mtu, b->mtu); NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu); NM_CMP_DIRECT_UNSAFE(a->metered, b->metered); + NM_CMP_DIRECT_UNSAFE(a->proxy_browser_only, b->proxy_browser_only); + NM_CMP_DIRECT_UNSAFE(a->proxy_method, b->proxy_method); + NM_CMP_DIRECT_REF_STRING(a->proxy_pac_url, b->proxy_pac_url); + NM_CMP_DIRECT_REF_STRING(a->proxy_pac_script, b->proxy_pac_script); NM_CMP_DIRECT_UNSAFE(a->ip6_privacy, b->ip6_privacy); NM_CMP_DIRECT_UNSAFE(a->ndisc_hop_limit_set, b->ndisc_hop_limit_set); @@ -1863,7 +2047,7 @@ _data_get_direct_route_for_host(const NML3ConfigData *self, gconstpointer host, guint32 route_table) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMPObject * best_route_obj = NULL; const NMPlatformIPXRoute *best_route = NULL; const NMPObject * item_obj; @@ -1998,7 +2182,7 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, guint32 route_metric, gboolean is_vrf) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); gs_unref_ptrarray GPtrArray *extra_onlink_routes = NULL; const NMPObject * my_addr_obj; const NMPObject * my_route_obj; @@ -2209,7 +2393,7 @@ _init_from_connection_ip(NML3ConfigData *self, guint32 route_table, guint32 route_metric) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; guint naddresses; guint nroutes; @@ -2388,11 +2572,28 @@ nm_l3_config_data_new_from_connection(NMDedupMultiIndex *multi_idx, guint32 route_metric_6) { NML3ConfigData *self; + NMSettingProxy *s_proxy; self = nm_l3_config_data_new(multi_idx, ifindex); _init_from_connection_ip(self, AF_INET, connection, route_table_4, route_metric_4); _init_from_connection_ip(self, AF_INET6, connection, route_table_6, route_metric_6); + + s_proxy = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PROXY); + if (s_proxy) { + switch (nm_setting_proxy_get_method(s_proxy)) { + case NM_SETTING_PROXY_METHOD_NONE: + self->proxy_method = NM_PROXY_CONFIG_METHOD_NONE; + break; + case NM_SETTING_PROXY_METHOD_AUTO: + self->proxy_method = NM_PROXY_CONFIG_METHOD_AUTO; + self->proxy_pac_url = nm_ref_string_new(nm_setting_proxy_get_pac_url(s_proxy)); + self->proxy_pac_script = nm_ref_string_new(nm_setting_proxy_get_pac_script(s_proxy)); + break; + } + self->proxy_browser_only = (!!nm_setting_proxy_get_browser_only(s_proxy)); + } + return self; } @@ -2433,7 +2634,7 @@ _init_from_platform(NML3ConfigData * self, NMPlatform * platform, NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMDedupMultiHeadEntry *head_entry; const NMPObject * plobj = NULL; NMDedupMultiIter iter; @@ -2534,6 +2735,9 @@ nm_l3_config_data_merge(NML3ConfigData * self, nm_assert(default_route_table_x[1] != 0); nm_assert(default_route_metric_x[0] != 0); /* IPv6 route metric cannot be zero. */ + nm_assert(!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE) + || nm_utils_is_power_of_two(merge_flags)); + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; const NML3ConfigDatFlags has_dns_priority_flag = @@ -2588,28 +2792,31 @@ nm_l3_config_data_merge(NML3ConfigData * self, } \ G_STMT_END - if (r_src->table_any) { - _ensure_r(); - r.rx.table_any = FALSE; - r.rx.table_coerced = default_route_table_x[IS_IPv4]; - } - - if (r_src->metric_any) { - _ensure_r(); - r.rx.metric_any = FALSE; - r.rx.metric = nm_add_clamped_u32(r.rx.metric, default_route_metric_x[IS_IPv4]); - } + if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) { + if (r_src->table_any) { + _ensure_r(); + r.rx.table_any = FALSE; + r.rx.table_coerced = default_route_table_x[IS_IPv4]; + } - if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) { - if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES) - && !NM_FLAGS_HAS(src->flags, - NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES)) - continue; - if (default_route_penalty_x && default_route_penalty_x[IS_IPv4] > 0) { + if (r_src->metric_any) { _ensure_r(); + r.rx.metric_any = FALSE; r.rx.metric = - nm_utils_ip_route_metric_penalize(r.rx.metric, - default_route_penalty_x[IS_IPv4]); + nm_add_clamped_u32(r.rx.metric, default_route_metric_x[IS_IPv4]); + } + + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) { + if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES) + && !NM_FLAGS_HAS(src->flags, + NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES)) + continue; + if (default_route_penalty_x && default_route_penalty_x[IS_IPv4] > 0) { + _ensure_r(); + r.rx.metric = + nm_utils_ip_route_metric_penalize(r.rx.metric, + default_route_penalty_x[IS_IPv4]); + } } } @@ -2653,8 +2860,8 @@ nm_l3_config_data_merge(NML3ConfigData * self, _garray_inaddr_merge(&self->wins, src->wins, AF_INET); _garray_inaddr_merge(&self->nis_servers, src->nis_servers, AF_INET); - if (!self->nis_domain && src->nis_domain) - self->nis_domain = g_strdup(src->nis_domain); + if (!self->nis_domain) + self->nis_domain = nm_ref_string_ref(src->nis_domain); } if (self->mdns == NM_SETTING_CONNECTION_MDNS_DEFAULT) @@ -2665,6 +2872,18 @@ nm_l3_config_data_merge(NML3ConfigData * self, self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered); + if (self->proxy_method == NM_PROXY_CONFIG_METHOD_UNKNOWN) + self->proxy_method = src->proxy_method; + + if (self->proxy_browser_only == NM_TERNARY_DEFAULT) + self->proxy_browser_only = src->proxy_browser_only; + + if (!self->proxy_pac_url) + self->proxy_pac_url = nm_ref_string_ref(src->proxy_pac_url); + + if (!self->proxy_pac_script) + self->proxy_pac_script = nm_ref_string_ref(src->proxy_pac_script); + if (self->ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) self->ip6_privacy = src->ip6_privacy; @@ -2689,8 +2908,16 @@ nm_l3_config_data_merge(NML3ConfigData * self, if (self->ip6_mtu == 0u) self->ip6_mtu = src->ip6_mtu; - /* self->source does not get merged. */ - /* self->dhcp_lease_x does not get merged. */ + if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) { + _nm_unused nm_auto_unref_dhcplease NMDhcpLease *dhcp_lease_6 = + g_steal_pointer(&self->dhcp_lease_x[0]); + _nm_unused nm_auto_unref_dhcplease NMDhcpLease *dhcp_lease_4 = + g_steal_pointer(&self->dhcp_lease_x[1]); + + self->source = src->source; + self->dhcp_lease_x[0] = nm_dhcp_lease_ref(self->dhcp_lease_x[0]); + self->dhcp_lease_x[1] = nm_dhcp_lease_ref(self->dhcp_lease_x[1]); + } } NML3ConfigData * @@ -2707,6 +2934,17 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) ifindex = src->ifindex; self = nm_l3_config_data_new(src->multi_idx, ifindex); - nm_l3_config_data_merge(self, src, NM_L3_CONFIG_MERGE_FLAGS_NONE, NULL, NULL, NULL, NULL, NULL); + nm_l3_config_data_merge(self, + src, + NM_L3_CONFIG_MERGE_FLAGS_CLONE, + NULL, + NULL, + NULL, + NULL, + NULL); + + nm_assert(nm_l3_config_data_cmp_full(src, self, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX) == 0); + nm_assert(nm_l3_config_data_get_ifindex(self) == ifindex); + return self; } diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index b3d9cd32..9bed47e0 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -3,11 +3,17 @@ #ifndef __NM_L3_CONFIG_DATA_H__ #define __NM_L3_CONFIG_DATA_H__ -#include "nm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" #include "nm-setting-connection.h" #include "nm-setting-ip6-config.h" -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" + +typedef enum { + NM_PROXY_CONFIG_METHOD_UNKNOWN, + NM_PROXY_CONFIG_METHOD_NONE, + NM_PROXY_CONFIG_METHOD_AUTO, +} NMProxyConfigMethod; typedef enum { NM_L3_CONFIG_DAT_FLAGS_NONE = 0, @@ -60,6 +66,8 @@ typedef enum { * Note that if the respective NML3ConfigData has NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES * set, this flag gets ignored during merge. * @NM_L3_CONFIG_MERGE_FLAGS_NO_DNS: don't merge DNS information + * @NM_L3_CONFIG_MERGE_FLAGS_CLONE: clone is also implemented via "merge". + * In that case, it takes all settings. */ typedef enum _nm_packed { NM_L3_CONFIG_MERGE_FLAGS_NONE = 0, @@ -67,6 +75,7 @@ typedef enum _nm_packed { NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES = (1LL << 1), NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES = (1LL << 2), NM_L3_CONFIG_MERGE_FLAGS_NO_DNS = (1LL << 3), + NM_L3_CONFIG_MERGE_FLAGS_CLONE = (1LL << 4), } NML3ConfigMergeFlags; /*****************************************************************************/ @@ -191,7 +200,20 @@ NMDedupMultiIndex *nm_l3_config_data_get_multi_idx(const NML3ConfigData *self); /*****************************************************************************/ -int nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b); +typedef enum { + NM_L3_CONFIG_CMP_FLAGS_NONE, + NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX = (1LL << 0), +} NML3ConfigCmpFlags; + +int nm_l3_config_data_cmp_full(const NML3ConfigData *a, + const NML3ConfigData *b, + NML3ConfigCmpFlags cmp_flags); + +static inline int +nm_l3_config_data_cmp(const NML3ConfigData *a, const NML3ConfigData *b) +{ + return nm_l3_config_data_cmp_full(a, b, NM_L3_CONFIG_CMP_FLAGS_NONE); +} static inline gboolean nm_l3_config_data_equal(const NML3ConfigData *a, const NML3ConfigData *b) @@ -236,6 +258,11 @@ nm_l3_config_data_lookup_routes(const NML3ConfigData *self, int addr_family) for (nm_dedup_multi_iter_init((iter), nm_l3_config_data_lookup_objs((self), (type))); \ nm_platform_dedup_multi_iter_next_obj((iter), (obj), (type));) +#define nm_l3_config_data_iter_ip_address_for_each(iter, self, addr_family, address) \ + for (nm_dedup_multi_iter_init((iter), \ + nm_l3_config_data_lookup_addresses((self), (addr_family))); \ + nm_platform_dedup_multi_iter_next_ip_address((iter), (address));) + #define nm_l3_config_data_iter_ip4_address_for_each(iter, self, address) \ for (nm_dedup_multi_iter_init((iter), nm_l3_config_data_lookup_addresses((self), AF_INET)); \ nm_platform_dedup_multi_iter_next_ip4_address((iter), (address));) @@ -244,6 +271,10 @@ nm_l3_config_data_lookup_routes(const NML3ConfigData *self, int addr_family) for (nm_dedup_multi_iter_init((iter), nm_l3_config_data_lookup_addresses((self), AF_INET6)); \ nm_platform_dedup_multi_iter_next_ip6_address((iter), (address));) +#define nm_l3_config_data_iter_ip_route_for_each(iter, self, addr_family, route) \ + for (nm_dedup_multi_iter_init((iter), nm_l3_config_data_lookup_routes((self), (addr_family))); \ + nm_platform_dedup_multi_iter_next_ip_route((iter), (route));) + #define nm_l3_config_data_iter_ip4_route_for_each(iter, self, route) \ for (nm_dedup_multi_iter_init((iter), nm_l3_config_data_lookup_routes((self), AF_INET)); \ nm_platform_dedup_multi_iter_next_ip4_route((iter), (route));) @@ -409,8 +440,12 @@ nm_l3_config_data_add_route_6(NML3ConfigData *self, const NMPlatformIP6Route *rt const NMPObject *nm_l3_config_data_get_best_default_route(const NML3ConfigData *self, int addr_family); +NMSettingConnectionMdns nm_l3_config_data_get_mdns(const NML3ConfigData *self); + gboolean nm_l3_config_data_set_mdns(NML3ConfigData *self, NMSettingConnectionMdns mdns); +NMSettingConnectionLlmnr nm_l3_config_data_get_llmnr(const NML3ConfigData *self); + gboolean nm_l3_config_data_set_llmnr(NML3ConfigData *self, NMSettingConnectionLlmnr llmnr); NMIPRouteTableSyncMode nm_l3_config_data_get_route_table_sync(const NML3ConfigData *self, @@ -445,13 +480,17 @@ gboolean nm_l3_config_data_add_nameserver(NML3ConfigData * gboolean nm_l3_config_data_clear_nameservers(NML3ConfigData *self, int addr_family); +const in_addr_t *nm_l3_config_data_get_nis_servers(const NML3ConfigData *self, guint *out_len); + gboolean nm_l3_config_data_add_nis_server(NML3ConfigData *self, in_addr_t nis_server); -const char *const * -nm_l3_config_data_get_domains(const NML3ConfigData *self, int addr_family, guint *out_len); +const char *nm_l3_config_data_get_nis_domain(const NML3ConfigData *self); gboolean nm_l3_config_data_set_nis_domain(NML3ConfigData *self, const char *nis_domain); +const char *const * +nm_l3_config_data_get_domains(const NML3ConfigData *self, int addr_family, guint *out_len); + gboolean nm_l3_config_data_add_domain(NML3ConfigData *self, int addr_family, const char *domain); const char *const * @@ -464,6 +503,12 @@ gboolean nm_l3_config_data_add_search(NML3ConfigData *self, int addr_family, con gboolean nm_l3_config_data_add_dns_option(NML3ConfigData *self, int addr_family, const char *dns_option); +const char *const * +nm_l3_config_data_get_dns_options(const NML3ConfigData *self, int addr_family, guint *out_len); + +gboolean +nm_l3_config_data_get_dns_priority(const NML3ConfigData *self, int addr_family, int *out_prio); + gboolean nm_l3_config_data_set_dns_priority(NML3ConfigData *self, int addr_family, int dns_priority); @@ -472,6 +517,22 @@ NMSettingIP6ConfigPrivacy nm_l3_config_data_get_ip6_privacy(const NML3ConfigData gboolean nm_l3_config_data_set_ip6_privacy(NML3ConfigData * self, NMSettingIP6ConfigPrivacy ip6_privacy); +NMProxyConfigMethod nm_l3_config_data_get_proxy_method(const NML3ConfigData *self); + +gboolean nm_l3_config_data_set_proxy_method(NML3ConfigData *self, NMProxyConfigMethod value); + +NMTernary nm_l3_config_data_get_proxy_browser_only(const NML3ConfigData *self); + +gboolean nm_l3_config_data_set_proxy_browser_only(NML3ConfigData *self, NMTernary value); + +const char *nm_l3_config_data_get_proxy_pac_url(const NML3ConfigData *self); + +gboolean nm_l3_config_data_set_proxy_pac_url(NML3ConfigData *self, const char *value); + +const char *nm_l3_config_data_get_proxy_pac_script(const NML3ConfigData *self); + +gboolean nm_l3_config_data_set_proxy_pac_script(NML3ConfigData *self, const char *value); + gboolean nm_l3_config_data_get_ndisc_hop_limit(const NML3ConfigData *self, int *out_val); gboolean nm_l3_config_data_set_ndisc_hop_limit(NML3ConfigData *self, int val); diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index 839213ad..93e92673 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -9,8 +9,9 @@ #include #include -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" +#include "libnm-glib-aux/nm-time-utils.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #include "nm-netns.h" #include "n-acd/src/n-acd.h" #include "nm-l3-ipv4ll.h" @@ -21,7 +22,7 @@ G_STATIC_ASSERT(NM_ACD_TIMEOUT_RFC5227_MSEC == N_ACD_TIMEOUT_RFC5227); #define ACD_SUPPORTED_ETH_ALEN ETH_ALEN #define ACD_ENSURE_RATELIMIT_MSEC ((guint32) 4000u) -#define ACD_WAIT_PROBING_EXTRA_TIME_MSEC ((guint32)(1000u + ACD_ENSURE_RATELIMIT_MSEC)) +#define ACD_WAIT_PROBING_EXTRA_TIME_MSEC ((guint32) (1000u + ACD_ENSURE_RATELIMIT_MSEC)) #define ACD_WAIT_PROBING_EXTRA_TIME2_MSEC ((guint32) 1000u) #define ACD_MAX_TIMEOUT_MSEC ((guint32) 30000u) #define ACD_WAIT_TIME_PROBING_FULL_RESTART_MSEC ((guint32) 30000u) @@ -301,6 +302,7 @@ static NM_UTILS_ENUM2STR_DEFINE( NML3ConfigNotifyType, NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT, "acd-event"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT, "ipv4ll-event"), + NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED, "l3cd-changed"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, "platform-change"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, "platform-change-on-idle"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, "post-commit"), @@ -347,6 +349,7 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, { char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; char sbuf100[100]; + char sbufobf[NM_HASH_OBFUSCATE_PTR_STR_BUF_SIZE]; char * s = sbuf; gsize l = sbuf_size; in_addr_t addr4; @@ -358,6 +361,19 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, nm_utils_strbuf_seek_end(&s, &l); switch (notify_data->notify_type) { + case NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED: + nm_utils_strbuf_append( + &s, + &l, + ", l3cd-old=%s", + NM_HASH_OBFUSCATE_PTR_STR(notify_data->l3cd_changed.l3cd_old, sbufobf)); + nm_utils_strbuf_append( + &s, + &l, + ", l3cd-new=%s", + NM_HASH_OBFUSCATE_PTR_STR(notify_data->l3cd_changed.l3cd_new, sbufobf)); + nm_utils_strbuf_append(&s, &l, ", commited=%d", notify_data->l3cd_changed.commited); + break; case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT: nm_utils_strbuf_append(&s, &l, @@ -423,6 +439,23 @@ _nm_l3cfg_emit_signal_notify_simple(NML3Cfg *self, NML3ConfigNotifyType notify_t _nm_l3cfg_emit_signal_notify(self, ¬ify_data); } +static void +_nm_l3cfg_emit_signal_notify_l3cd_changed(NML3Cfg * self, + const NML3ConfigData *l3cd_old, + const NML3ConfigData *l3cd_new, + gboolean commited) +{ + NML3ConfigNotifyData notify_data; + + notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED; + notify_data.l3cd_changed = (typeof(notify_data.l3cd_changed)){ + .l3cd_old = l3cd_old, + .l3cd_new = l3cd_new, + .commited = commited, + }; + _nm_l3cfg_emit_signal_notify(self, ¬ify_data); +} + /*****************************************************************************/ static void @@ -1478,7 +1511,7 @@ _l3_acd_data_add(NML3Cfg * self, if (!acd_data) { if (G_UNLIKELY(!self->priv.p->acd_lst_hash)) { G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(AcdData, info.addr) == 0); - self->priv.p->acd_lst_hash = g_hash_table_new(nm_puint32_hash, nm_puint32_equals); + self->priv.p->acd_lst_hash = g_hash_table_new(nm_puint32_hash, nm_puint32_equal); } acd_data = g_slice_new(AcdData); @@ -2549,18 +2582,19 @@ _l3_commit_on_idle_cb(gpointer user_data) return G_SOURCE_REMOVE; } -void +gboolean nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self) { nm_assert(NM_IS_L3CFG(self)); if (self->priv.p->commit_on_idle_source) - return; + return FALSE; _LOGT("commit on idle (scheduled)"); self->priv.p->commit_on_idle_source = nm_g_idle_source_new(G_PRIORITY_DEFAULT, _l3_commit_on_idle_cb, self, NULL); g_source_attach(self->priv.p->commit_on_idle_source, NULL); + return TRUE; } /*****************************************************************************/ @@ -3008,6 +3042,12 @@ _l3cfg_update_combined_config(NML3Cfg * self, l3cd_old = g_steal_pointer(&self->priv.p->combined_l3cd_merged); self->priv.p->combined_l3cd_merged = nm_l3_config_data_seal(g_steal_pointer(&l3cd)); merged_changed = TRUE; + + _nm_l3cfg_emit_signal_notify_l3cd_changed(self, + l3cd_old, + self->priv.p->combined_l3cd_merged, + FALSE); + if (!to_commit) { NM_SET_OUT(out_old, g_steal_pointer(&l3cd_old)); NM_SET_OUT(out_changed_combined_l3cd, TRUE); @@ -3019,6 +3059,12 @@ out: self->priv.p->combined_l3cd_commited = nm_l3_config_data_ref(self->priv.p->combined_l3cd_merged); commited_changed = TRUE; + + _nm_l3cfg_emit_signal_notify_l3cd_changed(self, + l3cd_commited_old, + self->priv.p->combined_l3cd_commited, + TRUE); + NM_SET_OUT(out_old, g_steal_pointer(&l3cd_commited_old)); NM_SET_OUT(out_changed_combined_l3cd, TRUE); } @@ -3652,6 +3698,23 @@ _nm_l3cfg_unregister_ipv4ll(NML3Cfg *self) /*****************************************************************************/ +gboolean +nm_l3cfg_is_ready(NML3Cfg *self) +{ + g_return_val_if_fail(NM_IS_L3CFG(self), FALSE); + + if (self->priv.p->changed_configs_configs) + return FALSE; + if (self->priv.p->changed_configs_acd_state) + return FALSE; + if (self->priv.p->commit_on_idle_source) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { diff --git a/src/core/nm-l3cfg.h b/src/core/nm-l3cfg.h index 5cfc93f6..037f2178 100644 --- a/src/core/nm-l3cfg.h +++ b/src/core/nm-l3cfg.h @@ -3,7 +3,7 @@ #ifndef __NM_L3CFG_H__ #define __NM_L3CFG_H__ -#include "platform/nmp-object.h" +#include "libnm-platform/nmp-object.h" #include "nm-l3-config-data.h" #define NM_L3CFG_CONFIG_PRIORITY_IPV4LL 0 @@ -88,11 +88,18 @@ nm_l3_acd_addr_info_find_track_info(const NML3AcdAddrInfo *addr_info, } typedef enum { + /* emitted when the merged/commited NML3ConfigData instance changes. + * Note that this gets emitted "under unsafe circumstances". That means, + * you should not perform complex operations inside this callback, + * and neither should you call into NML3Cfg again (reentrancy). */ + NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED, + NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED, NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT, - /* emitted at the end of nm_l3cfg_platform_commit(). */ + /* emitted at the end of nm_l3cfg_platform_commit(). This signals also that + * nm_l3cfg_is_ready() might have switched to TRUE. */ NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, /* NML3Cfg hooks to the NMPlatform signals for link, addresses and routes. @@ -117,6 +124,12 @@ struct _NML3IPv4LL; typedef struct { NML3ConfigNotifyType notify_type; union { + struct { + const NML3ConfigData *l3cd_old; + const NML3ConfigData *l3cd_new; + bool commited; + } l3cd_changed; + struct { NML3AcdAddrInfo info; } acd_event; @@ -158,6 +171,8 @@ NML3Cfg *nm_l3cfg_new(NMNetns *netns, int ifindex); /*****************************************************************************/ +gboolean nm_l3cfg_is_ready(NML3Cfg *self); + void _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags); void _nm_l3cfg_notify_platform_change(NML3Cfg * self, @@ -173,6 +188,8 @@ struct _NMDedupMultiIndex *nm_netns_get_multi_idx(NMNetns *self); static inline struct _NMDedupMultiIndex * nm_l3cfg_get_multi_idx(const NML3Cfg *self) { + g_return_val_if_fail(NM_IS_L3CFG(self), NULL); + return nm_netns_get_multi_idx(self->priv.netns); } @@ -181,7 +198,7 @@ nm_l3cfg_get_multi_idx(const NML3Cfg *self) static inline int nm_l3cfg_get_ifindex(const NML3Cfg *self) { - nm_assert(NM_IS_L3CFG(self)); + g_return_val_if_fail(NM_IS_L3CFG(self), 0); return self->priv.ifindex; } @@ -314,7 +331,7 @@ typedef enum _nm_packed { void nm_l3cfg_commit(NML3Cfg *self, NML3CfgCommitType commit_type); -void nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self); +gboolean nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self); /*****************************************************************************/ diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index f44306e1..d859c1ea 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -16,15 +16,15 @@ #include #include -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-c-list.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-manager.h" #include "vpn/nm-vpn-manager.h" #include "devices/nm-device.h" #include "devices/nm-device-generic.h" -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #include "nm-hostname-manager.h" #include "nm-keep-alive.h" #include "nm-rfkill-manager.h" @@ -40,10 +40,10 @@ #include "nm-policy.h" #include "nm-session-monitor.h" #include "nm-act-request.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #include "nm-audit-manager.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-checkpoint.h" #include "nm-checkpoint-manager.h" #include "nm-dbus-object.h" @@ -1313,7 +1313,7 @@ find_device_by_permanent_hw_addr(NMManager *self, const char *hwaddr) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); NMDevice * device; const char * device_addr; - guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX]; + guint8 hwaddr_bin[_NM_UTILS_HWADDR_LEN_MAX]; gsize hwaddr_len; g_return_val_if_fail(hwaddr != NULL, NULL); @@ -1999,16 +1999,16 @@ nm_manager_remove_device(NMManager *self, const char *ifname, NMDeviceType devic static NMDevice * system_create_virtual_device(NMManager *self, NMConnection *connection) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - NMDeviceFactory * factory; - gs_free NMSettingsConnection **connections = NULL; - guint i; - gs_free char * iface = NULL; - const char * parent_spec; - NMDevice * device = NULL, *parent = NULL; - NMDevice * dev_candidate; - GError * error = NULL; - NMLogLevel log_level; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMDeviceFactory * factory; + NMSettingsConnection *const *connections; + guint i; + gs_free char * iface = NULL; + const char * parent_spec; + NMDevice * device = NULL, *parent = NULL; + NMDevice * dev_candidate; + GError * error = NULL; + NMLogLevel log_level; g_return_val_if_fail(NM_IS_MANAGER(self), NULL); g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); @@ -2091,13 +2091,7 @@ system_create_virtual_device(NMManager *self, NMConnection *connection) } /* Create backing resources if the device has any autoconnect connections */ - connections = nm_settings_get_connections_clone( - priv->settings, - NULL, - NULL, - NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, - NULL); + connections = nm_settings_get_connections_sorted_by_autoconnect_priority(priv->settings, NULL); for (i = 0; connections[i]; i++) { NMConnection * candidate = nm_settings_connection_get_connection(connections[i]); NMSettingConnection *s_con; @@ -2136,19 +2130,13 @@ system_create_virtual_device(NMManager *self, NMConnection *connection) static void retry_connections_for_parent_device(NMManager *self, NMDevice *device) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - gs_free NMSettingsConnection **connections = NULL; - guint i; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSettingsConnection *const *connections; + guint i; g_return_if_fail(device); - connections = nm_settings_get_connections_clone( - priv->settings, - NULL, - NULL, - NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, - NULL); + connections = nm_settings_get_connections_sorted_by_autoconnect_priority(priv->settings, NULL); for (i = 0; connections[i]; i++) { NMSettingsConnection *sett_conn = connections[i]; NMConnection * connection = nm_settings_connection_get_connection(sett_conn); @@ -2607,6 +2595,12 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat nm_device_capture_initial_config(device); + if (!nm_device_can_assume_connections(device)) { + nm_device_assume_state_reset(device); + _LOG2D(LOGD_DEVICE, device, "assume: device cannot assume connection"); + return NULL; + } + if (ifindex) { int master_ifindex = nm_platform_link_get_master(priv->platform, ifindex); @@ -2638,39 +2632,47 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat } } - /* The core of the API is nm_device_generate_connection() function and - * update_connection() virtual method and the convenient connection_type - * class attribute. Subclasses supporting the new API must have - * update_connection() implemented, otherwise nm_device_generate_connection() - * returns NULL. - */ - connection = nm_device_generate_connection(device, master, &maybe_later, &gen_error); - if (!connection) { - if (maybe_later) { - /* The device can generate a connection, but it failed for now. - * Give it a chance to match a connection from the state file. */ - only_by_uuid = TRUE; - } else { - nm_device_assume_state_reset(device); - _LOG2D(LOGD_DEVICE, - device, - "assume: cannot generate connection: %s", - gen_error->message); - return NULL; + if (nm_config_data_get_device_config_boolean(NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_KEY_DEVICE_KEEP_CONFIGURATION, + device, + TRUE, + TRUE)) { + /* The core of the API is nm_device_generate_connection() function, based on + * update_connection() virtual method and the @connection_type_supported + * class attribute. Devices that support assuming existing connections must + * have update_connection() implemented, otherwise + * nm_device_generate_connection() returns NULL. */ + connection = nm_device_generate_connection(device, master, &maybe_later, &gen_error); + if (!connection) { + if (maybe_later) { + /* The device can potentially assume connections, but at this + * time we can't generate a connection because no address is + * configured. Allow the device to assume a connection indicated + * in the state file by UUID. */ + only_by_uuid = TRUE; + } else { + nm_device_assume_state_reset(device); + _LOG2D(LOGD_DEVICE, + device, + "assume: cannot generate connection: %s", + gen_error->message); + return NULL; + } } + } else { + connection = NULL; + only_by_uuid = TRUE; + g_set_error(&gen_error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "device %s has 'keep-configuration=no'", + nm_device_get_iface(device)); } nm_device_assume_state_get(device, &assume_state_guess_assume, &assume_state_connection_uuid); - /* Now we need to compare the generated connection to each configured - * connection. The comparison function is the heart of the connection - * assumption implementation and it must compare the connections very - * carefully to sort out various corner cases. Also, the comparison is - * not entirely symmetric. - * - * When no configured connection matches the generated connection, we keep - * the generated connection instead. - */ + /* If the device state file indicates a connection that was active before NM + * restarted, perform basic sanity checks on it. */ if (assume_state_connection_uuid && (connection_checked = nm_settings_get_connection_by_uuid(priv->settings, assume_state_connection_uuid)) @@ -2704,8 +2706,9 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat gs_free NMSettingsConnection **sett_conns = NULL; guint len, i, j; - /* the state file doesn't indicate a connection UUID to assume. Search the - * persistent connections for a matching candidate. */ + /* @assume_state_guess_assume=TRUE means this is the first start of NM + * and the state file contains no UUID. Search persistent connections + * for a matching candidate. */ sett_conns = nm_manager_get_activatable_connections(self, FALSE, FALSE, &len); if (len > 0) { for (i = 0, j = 0; i < len; i++) { @@ -2778,6 +2781,8 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat return matched; } + /* When no configured connection matches the generated connection, we keep + * the generated connection instead. */ _LOG2D(LOGD_DEVICE, device, "assume: generated connection '%s' (%s)", @@ -2904,15 +2909,16 @@ recheck_assume_connection(NMManager *self, NMDevice *device) NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL)); - nm_settings_connection_update(sett_conn, - con2, - NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, - NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, - NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE, - "assume-initrd", - NULL); + nm_settings_connection_update( + sett_conn, + con2, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, + NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET, + "assume-initrd", + NULL); } } } @@ -4424,13 +4430,13 @@ find_slaves(NMManager * manager, guint * out_n_slaves, gboolean for_user_request) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(manager); - gs_free NMSettingsConnection **all_connections = NULL; - guint n_all_connections; - guint i; - SlaveConnectionInfo * slaves = NULL; - guint n_slaves = 0; - NMSettingConnection * s_con; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(manager); + NMSettingsConnection *const *all_connections = NULL; + guint n_all_connections; + guint i; + SlaveConnectionInfo * slaves = NULL; + guint n_slaves = 0; + NMSettingConnection * s_con; gs_unref_hashtable GHashTable *devices = NULL; nm_assert(out_n_slaves); @@ -4444,13 +4450,9 @@ find_slaves(NMManager * manager, * even if a slave was already active, it might be deactivated during * master reactivation. */ - all_connections = nm_settings_get_connections_clone( - priv->settings, - &n_all_connections, - NULL, - NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, - NULL); + all_connections = + nm_settings_get_connections_sorted_by_autoconnect_priority(priv->settings, + &n_all_connections); for (i = 0; i < n_all_connections; i++) { NMSettingsConnection *master_connection = NULL; NMDevice * master_device = NULL, *slave_device; @@ -5695,7 +5697,7 @@ activation_add_done(NMSettings * settings, result_floating = g_variant_new("(oo@a{sv})", nm_dbus_object_get_path(NM_DBUS_OBJECT(new_connection)), nm_dbus_object_get_path(NM_DBUS_OBJECT(active)), - g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0)); + nm_g_variant_singleton_aLsvI()); } g_dbus_method_invocation_return_value(context, result_floating); @@ -6818,8 +6820,9 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde guint32 route_metric_default_effective; NMTernary nm_owned; NMDhcpConfig * dhcp_config; - const char * next_server = NULL; - const char * root_path = NULL; + const char * next_server = NULL; + const char * root_path = NULL; + const char * dhcp_bootfile = NULL; NM_SET_OUT(out_ifindex, 0); @@ -6863,8 +6866,11 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde dhcp_config = nm_device_get_dhcp_config(device, AF_INET); if (dhcp_config) { - root_path = nm_dhcp_config_get_option(dhcp_config, "root_path"); - next_server = nm_dhcp_config_get_option(dhcp_config, "next_server"); + root_path = nm_dhcp_config_get_option(dhcp_config, "root_path"); + next_server = nm_dhcp_config_get_option(dhcp_config, "next_server"); + dhcp_bootfile = nm_dhcp_config_get_option(dhcp_config, "filename"); + if (!dhcp_bootfile) + dhcp_bootfile = nm_dhcp_config_get_option(dhcp_config, "bootfile_name"); } if (!nm_config_device_state_write(ifindex, @@ -6875,7 +6881,8 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde route_metric_default_aspired, route_metric_default_effective, next_server, - root_path)) + root_path, + dhcp_bootfile)) return FALSE; NM_SET_OUT(out_ifindex, ifindex); @@ -6917,9 +6924,9 @@ devices_inited_cb(gpointer user_data) gboolean nm_manager_start(NMManager *self, GError **error) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - gs_free NMSettingsConnection **connections = NULL; - guint i; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSettingsConnection *const *connections; + guint i; nm_device_factory_manager_load_factories(_register_device_factory, self); @@ -6977,13 +6984,7 @@ nm_manager_start(NMManager *self, GError **error) NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, G_CALLBACK(connection_updated_cb), self); - connections = nm_settings_get_connections_clone( - priv->settings, - NULL, - NULL, - NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, - NULL); + connections = nm_settings_get_connections_sorted_by_autoconnect_priority(priv->settings, NULL); for (i = 0; connections[i]; i++) connection_changed(self, connections[i]); @@ -7160,6 +7161,85 @@ typedef struct { #define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied" +static const char * +_dbus_set_property_audit_log_get_args(NMDBusObject *obj, + const char * property_name, + GVariant * value, + char ** str_to_free) +{ + nm_assert(str_to_free && !*str_to_free); + + /* We assert here that the property is one of the few expected ones. + * + * Future properties should not made writable! Add a D-Bus method instead, + * they are more flexible (for example, you can set multiple properties at + * once). */ + + if (NM_IS_DEVICE(obj)) { + nm_assert(NM_IN_STRSET(property_name, + NM_DEVICE_MANAGED, + NM_DEVICE_AUTOCONNECT, + NM_DEVICE_STATISTICS_REFRESH_RATE_MS)); + return (*str_to_free = g_variant_print(value, FALSE)); + } + + nm_assert(NM_IS_MANAGER(obj)); + if (NM_IN_STRSET(property_name, + NM_MANAGER_WIRELESS_ENABLED, + NM_MANAGER_WWAN_ENABLED, + NM_MANAGER_WIMAX_ENABLED, + NM_MANAGER_CONNECTIVITY_CHECK_ENABLED)) { + return (*str_to_free = g_strdup_printf("%s:%s", + property_name, + g_variant_get_boolean(value) ? "on" : "off")); + } + if (NM_IN_STRSET(property_name, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) { + return NM_MANAGER_GLOBAL_DNS_CONFIGURATION; + } + + return nm_assert_unreachable_val("???"); +} + +/* this is a macro to catch the caller's line number. */ +#define _dbus_set_property_audit_log(obj, \ + audit_op, \ + auth_subject, \ + property_name, \ + value, \ + error_message) \ + G_STMT_START \ + { \ + NMDBusObject *const _obj = (obj); \ + const char *const _audit_op = (audit_op); \ + NMAuthSubject *const _auth_subject = (auth_subject); \ + const char *const _property_name = (property_name); \ + GVariant *const _value = (value); \ + const char *const _error_message = (error_message); \ + gs_free char * _args_to_free = NULL; \ + \ + if (NM_IS_DEVICE(_obj)) { \ + nm_audit_log_device_op(_audit_op, \ + NM_DEVICE(_obj), \ + !_error_message, \ + _dbus_set_property_audit_log_get_args(_obj, \ + _property_name, \ + _value, \ + &_args_to_free), \ + _auth_subject, \ + _error_message); \ + } else { \ + nm_audit_log_control_op(_audit_op, \ + _dbus_set_property_audit_log_get_args(_obj, \ + _property_name, \ + _value, \ + &_args_to_free), \ + !_error_message, \ + _auth_subject, \ + _error_message); \ + } \ + } \ + G_STMT_END + static void _dbus_set_property_auth_cb(NMAuthChain * chain, GDBusMethodInvocation *invocation, @@ -7217,11 +7297,13 @@ _dbus_set_property_auth_cb(NMAuthChain * chain, g_value_unset(&gvalue); out: - nm_audit_log_control_op(property_info->writable.audit_op, - property_info->property_name, - !error_message, - nm_auth_chain_get_subject(chain), - error_message); + _dbus_set_property_audit_log(obj, + property_info->writable.audit_op, + nm_auth_chain_get_subject(chain), + property_info->property_name, + value, + error_message); + if (error_message) g_dbus_method_invocation_return_dbus_error(invocation, error_name, error_message); else @@ -7245,10 +7327,27 @@ nm_manager_dbus_set_property_handle(NMDBusObject * obj, gs_unref_object NMAuthSubject *subject = NULL; DBusSetPropertyHandle * handle_data; + /* we only have writable properties on Device or Manager. In the future, + * we probably should not add new API with writable properties. Add + * methods instead. Systemd also avoids writable properties. */ + nm_assert(obj == (gpointer) self || NM_IS_DEVICE(obj)); + subject = nm_dbus_manager_new_auth_subject_from_context(invocation); if (!subject) { error_message = NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN; - goto err; + + _dbus_set_property_audit_log(obj, + property_info->writable.audit_op, + NULL, + property_info->property_name, + value, + error_message); + + g_dbus_method_invocation_return_error_literal(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_AUTH_FAILED, + error_message); + return; } handle_data = g_slice_new0(DBusSetPropertyHandle); @@ -7262,18 +7361,6 @@ nm_manager_dbus_set_property_handle(NMDBusObject * obj, chain = nm_auth_chain_new_subject(subject, invocation, _dbus_set_property_auth_cb, handle_data); c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); nm_auth_chain_add_call_unsafe(chain, property_info->writable.permission, TRUE); - return; - -err: - nm_audit_log_control_op(property_info->writable.audit_op, - property_info->property_name, - FALSE, - invocation, - error_message); - g_dbus_method_invocation_return_error_literal(invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_AUTH_FAILED, - error_message); } /*****************************************************************************/ @@ -7912,10 +7999,8 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) break; case PROP_CAPABILITIES: g_value_set_variant(value, - g_variant_new_fixed_array(G_VARIANT_TYPE("u"), - priv->capabilities->data, - priv->capabilities->len, - sizeof(guint32))); + nm_g_variant_new_au((const guint32 *) priv->capabilities->data, + priv->capabilities->len)); break; case PROP_STATE: g_value_set_uint(value, priv->state); @@ -8355,76 +8440,74 @@ static const NMDBusInterfaceInfoExtended interface_info_manager = { NM_DEFINE_GDBUS_ARG_INFO("checkpoint", "o"), NM_DEFINE_GDBUS_ARG_INFO("add_timeout", "u"), ), ), .handle = impl_manager_checkpoint_adjust_rollback_timeout, ), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_check_permissions, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_check_permissions, &signal_info_state_changed, &signal_info_device_added, &signal_info_device_removed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Devices", "ao", NM_MANAGER_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AllDevices", - "ao", - NM_MANAGER_ALL_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Checkpoints", - "ao", - NM_MANAGER_CHECKPOINTS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("NetworkingEnabled", - "b", - NM_MANAGER_NETWORKING_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Devices", "ao", NM_MANAGER_DEVICES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AllDevices", + "ao", + NM_MANAGER_ALL_DEVICES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Checkpoints", + "ao", + NM_MANAGER_CHECKPOINTS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NetworkingEnabled", + "b", + NM_MANAGER_NETWORKING_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE( "WirelessEnabled", "b", NM_MANAGER_WIRELESS_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, NM_AUDIT_OP_RADIO_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WirelessHardwareEnabled", - "b", - NM_MANAGER_WIRELESS_HARDWARE_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WirelessHardwareEnabled", + "b", + NM_MANAGER_WIRELESS_HARDWARE_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE( "WwanEnabled", "b", NM_MANAGER_WWAN_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, NM_AUDIT_OP_RADIO_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WwanHardwareEnabled", - "b", - NM_MANAGER_WWAN_HARDWARE_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WwanHardwareEnabled", + "b", + NM_MANAGER_WWAN_HARDWARE_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE( "WimaxEnabled", "b", NM_MANAGER_WIMAX_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, NM_AUDIT_OP_RADIO_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WimaxHardwareEnabled", - "b", - NM_MANAGER_WIMAX_HARDWARE_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActiveConnections", - "ao", - NM_MANAGER_ACTIVE_CONNECTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PrimaryConnection", - "o", - NM_MANAGER_PRIMARY_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PrimaryConnectionType", - "s", - NM_MANAGER_PRIMARY_CONNECTION_TYPE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Metered", "u", NM_MANAGER_METERED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActivatingConnection", - "o", - NM_MANAGER_ACTIVATING_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Startup", "b", NM_MANAGER_STARTUP), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Version", "s", NM_MANAGER_VERSION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Capabilities", - "au", - NM_MANAGER_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("State", "u", NM_MANAGER_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Connectivity", - "u", - NM_MANAGER_CONNECTIVITY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L( - "ConnectivityCheckAvailable", - "b", - NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WimaxHardwareEnabled", + "b", + NM_MANAGER_WIMAX_HARDWARE_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ActiveConnections", + "ao", + NM_MANAGER_ACTIVE_CONNECTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PrimaryConnection", + "o", + NM_MANAGER_PRIMARY_CONNECTION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PrimaryConnectionType", + "s", + NM_MANAGER_PRIMARY_CONNECTION_TYPE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Metered", "u", NM_MANAGER_METERED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ActivatingConnection", + "o", + NM_MANAGER_ACTIVATING_CONNECTION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Startup", "b", NM_MANAGER_STARTUP), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Version", "s", NM_MANAGER_VERSION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Capabilities", + "au", + NM_MANAGER_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("State", "u", NM_MANAGER_STATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Connectivity", + "u", + NM_MANAGER_CONNECTIVITY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ConnectivityCheckAvailable", + "b", + NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE( "ConnectivityCheckEnabled", "b", NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, @@ -8433,13 +8516,12 @@ static const NMDBusInterfaceInfoExtended interface_info_manager = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ConnectivityCheckUri", "s", NM_MANAGER_CONNECTIVITY_CHECK_URI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE( "GlobalDnsConfiguration", "a{sv}", NM_MANAGER_GLOBAL_DNS_CONFIGURATION, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, NM_AUDIT_OP_NET_CONTROL), ), ), - .legacy_property_changed = TRUE, }; static void diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index 88ea09b6..d5a0317d 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -7,15 +7,15 @@ #include "nm-netns.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-c-list.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-l3cfg.h" -#include "platform/nm-platform.h" -#include "nm-platform/nmp-netns.h" -#include "platform/nmp-rules-manager.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-netns.h" +#include "libnm-platform/nmp-rules-manager.h" /*****************************************************************************/ @@ -263,7 +263,7 @@ nm_netns_shared_ip_reserve(NMNetns *self) if (!priv->shared_ips) { addr = addr_start; - priv->shared_ips = g_hash_table_new(nm_puint32_hash, nm_puint32_equals); + priv->shared_ips = g_hash_table_new(nm_puint32_hash, nm_puint32_equal); g_object_ref(self); } else { guint32 count; @@ -392,7 +392,7 @@ constructed(GObject *object) if (!priv->platform) g_return_if_reached(); - priv->l3cfgs = g_hash_table_new_full(nm_pint_hash, nm_pint_equals, _l3cfg_data_free, NULL); + priv->l3cfgs = g_hash_table_new_full(nm_pint_hash, nm_pint_equal, _l3cfg_data_free, NULL); priv->platform_netns = nm_platform_netns_get(priv->platform); diff --git a/src/core/nm-netns.h b/src/core/nm-netns.h index aab3b520..78a9121a 100644 --- a/src/core/nm-netns.h +++ b/src/core/nm-netns.h @@ -6,7 +6,7 @@ #ifndef __NM_NETNS_H__ #define __NM_NETNS_H__ -#include "nm-platform/nmp-base.h" +#include "libnm-platform/nmp-base.h" #define NM_TYPE_NETNS (nm_netns_get_type()) #define NM_NETNS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_NETNS, NMNetns)) @@ -19,13 +19,15 @@ typedef struct _NMNetnsClass NMNetnsClass; +struct _NMPlatform; + GType nm_netns_get_type(void); NMNetns *nm_netns_get(void); -NMNetns *nm_netns_new(NMPlatform *platform); +NMNetns *nm_netns_new(struct _NMPlatform *platform); -NMPlatform *nm_netns_get_platform(NMNetns *self); -NMPNetns * nm_netns_get_platform_netns(NMNetns *self); +struct _NMPlatform *nm_netns_get_platform(NMNetns *self); +NMPNetns * nm_netns_get_platform_netns(NMNetns *self); struct _NMPRulesManager *nm_netns_get_rules_manager(NMNetns *self); diff --git a/src/core/nm-pacrunner-manager.c b/src/core/nm-pacrunner-manager.c index b58aef06..67930dba 100644 --- a/src/core/nm-pacrunner-manager.c +++ b/src/core/nm-pacrunner-manager.c @@ -9,13 +9,13 @@ #include "nm-utils.h" #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-dbus-manager.h" #include "nm-proxy-config.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" #include "c-list/src/c-list.h" -#include "nm-glib-aux/nm-dbus-aux.h" +#include "libnm-glib-aux/nm-dbus-aux.h" #define PACRUNNER_DBUS_SERVICE "org.pacrunner" #define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager" @@ -198,6 +198,7 @@ _make_request_create_proxy_configuration(NMProxyConfig *proxy_config, g_variant_builder_add(&builder, "{sv}", "Script", g_variant_new_string(pac_script)); } break; + case NM_PROXY_CONFIG_METHOD_UNKNOWN: case NM_PROXY_CONFIG_METHOD_NONE: g_variant_builder_add(&builder, "{sv}", "Method", g_variant_new_string("direct")); break; diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index 71aa1ece..e147e504 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -17,14 +17,14 @@ #include "devices/nm-device.h" #include "nm-setting-ip4-config.h" #include "nm-setting-connection.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "dns/nm-dns-manager.h" #include "vpn/nm-vpn-manager.h" #include "nm-auth-utils.h" -#include "nm-firewall-manager.h" +#include "nm-firewalld-manager.h" #include "nm-dispatcher.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-manager.h" #include "settings/nm-settings.h" #include "settings/nm-settings-connection.h" @@ -45,10 +45,10 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMPolicy, PROP_ACTIVATING_IP6_AC, ); typedef struct { - NMManager * manager; - NMNetns * netns; - NMFirewallManager *firewall_manager; - CList pending_activation_checks; + NMManager * manager; + NMNetns * netns; + NMFirewalldManager *firewalld_manager; + CList pending_activation_checks; NMAgentManager *agent_mgr; @@ -2004,19 +2004,12 @@ device_state_changed(NMDevice * device, nm_settings_connection_get_id(sett_conn)); } } - - nm_settings_connection_clear_secrets(sett_conn, FALSE, FALSE); } break; case NM_DEVICE_STATE_ACTIVATED: if (sett_conn) { /* Reset auto retries back to default since connection was successful */ nm_settings_connection_autoconnect_retries_reset(sett_conn); - - /* And clear secrets so they will always be requested from the - * settings service when the next connection is made. - */ - nm_settings_connection_clear_secrets(sett_conn, FALSE, FALSE); } /* Add device's new IPv4 and IPv6 configs to DNS */ @@ -2526,21 +2519,22 @@ connection_added(NMSettings *settings, NMSettingsConnection *connection, gpointe } static void -firewall_state_changed(NMFirewallManager *manager, gboolean initialized_now, gpointer user_data) +firewall_state_changed(NMFirewalldManager *manager, int signal_type_i, gpointer user_data) { - NMPolicy * self = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); - const CList * tmp_lst; - NMDevice * device; + const NMFirewalldManagerStateChangedType signal_type = signal_type_i; + NMPolicy * self = user_data; + NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self); + const CList * tmp_lst; + NMDevice * device; - if (initialized_now) { + if (signal_type == NM_FIREWALLD_MANAGER_STATE_CHANGED_TYPE_INITIALIZED) { /* the firewall manager was initializing, but all requests * so fare were queued and are already sent. No need to * re-update the firewall zone of the devices. */ return; } - if (!nm_firewall_manager_get_running(manager)) + if (!nm_firewalld_manager_get_running(manager)) return; /* add interface of each device to correct zone */ @@ -2792,9 +2786,9 @@ constructed(GObject *object) priv->agent_mgr = g_object_ref(nm_agent_manager_get()); - priv->firewall_manager = g_object_ref(nm_firewall_manager_get()); - g_signal_connect(priv->firewall_manager, - NM_FIREWALL_MANAGER_STATE_CHANGED, + priv->firewalld_manager = g_object_ref(nm_firewalld_manager_get()); + g_signal_connect(priv->firewalld_manager, + NM_FIREWALLD_MANAGER_STATE_CHANGED, G_CALLBACK(firewall_state_changed), self); @@ -2897,9 +2891,9 @@ dispose(GObject *object) g_slist_free_full(priv->pending_secondaries, (GDestroyNotify) pending_secondary_data_free); priv->pending_secondaries = NULL; - if (priv->firewall_manager) { - g_signal_handlers_disconnect_by_func(priv->firewall_manager, firewall_state_changed, self); - g_clear_object(&priv->firewall_manager); + if (priv->firewalld_manager) { + g_signal_handlers_disconnect_by_func(priv->firewalld_manager, firewall_state_changed, self); + g_clear_object(&priv->firewalld_manager); } if (priv->agent_mgr) { diff --git a/src/core/nm-proxy-config.c b/src/core/nm-proxy-config.c index f41601c9..49156dfa 100644 --- a/src/core/nm-proxy-config.c +++ b/src/core/nm-proxy-config.c @@ -9,7 +9,7 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ diff --git a/src/core/nm-proxy-config.h b/src/core/nm-proxy-config.h index 7aa587d0..7b6241f8 100644 --- a/src/core/nm-proxy-config.h +++ b/src/core/nm-proxy-config.h @@ -7,8 +7,7 @@ #define __NETWORKMANAGER_PROXY_CONFIG_H__ #include "nm-setting-proxy.h" - -typedef enum { NM_PROXY_CONFIG_METHOD_AUTO = 0, NM_PROXY_CONFIG_METHOD_NONE } NMProxyConfigMethod; +#include "nm-l3-config-data.h" #define NM_TYPE_PROXY_CONFIG (nm_proxy_config_get_type()) #define NM_PROXY_CONFIG(obj) \ diff --git a/src/core/nm-rfkill-manager.c b/src/core/nm-rfkill-manager.c index f032851e..7f0b7726 100644 --- a/src/core/nm-rfkill-manager.c +++ b/src/core/nm-rfkill-manager.c @@ -9,7 +9,7 @@ #include -#include "nm-udev-aux/nm-udev-utils.h" +#include "libnm-udev-aux/nm-udev-utils.h" /*****************************************************************************/ diff --git a/src/core/nm-sleep-monitor.c b/src/core/nm-sleep-monitor.c index ffb4db4e..306453e7 100644 --- a/src/core/nm-sleep-monitor.c +++ b/src/core/nm-sleep-monitor.c @@ -11,7 +11,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #if defined(SUSPEND_RESUME_UPOWER) @@ -108,7 +108,7 @@ upower_resuming_cb(GDBusProxy *proxy, gpointer user_data) sleep_signal(user_data, FALSE); } -#else /* USE_UPOWER */ +#else /* USE_UPOWER */ static void drop_inhibitor(NMSleepMonitor *self, gboolean force) diff --git a/src/core/nm-test-utils-core.h b/src/core/nm-test-utils-core.h index e655ce22..99d12ba9 100644 --- a/src/core/nm-test-utils-core.h +++ b/src/core/nm-test-utils-core.h @@ -7,41 +7,11 @@ #define __NM_TEST_UTILS_CORE_H__ #include "NetworkManagerUtils.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #define _NMTST_INSIDE_CORE 1 -#include "nm-utils/nm-test-utils.h" - -/*****************************************************************************/ - -#define NMTST_EXPECT_NM(level, msg) NMTST_EXPECT("NetworkManager", level, msg) - -#define NMTST_EXPECT_NM_ERROR(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_MESSAGE, "* [*] " msg) -#define NMTST_EXPECT_NM_WARN(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_MESSAGE, "* [*] " msg) -#define NMTST_EXPECT_NM_INFO(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_INFO, "* [*] " msg) -#define NMTST_EXPECT_NM_DEBUG(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_DEBUG, "* [*] " msg) -#define NMTST_EXPECT_NM_TRACE(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_DEBUG, "* [*] " msg) - -static inline void -nmtst_init_with_logging(int *argc, char ***argv, const char *log_level, const char *log_domains) -{ - __nmtst_init(argc, argv, FALSE, log_level, log_domains, NULL); -} -static inline void -nmtst_init_assert_logging(int *argc, char ***argv, const char *log_level, const char *log_domains) -{ - gboolean set_logging; - - __nmtst_init(argc, argv, TRUE, NULL, NULL, &set_logging); - - if (!set_logging) { - gboolean success; - - success = nm_logging_setup(log_level, log_domains, NULL, NULL); - g_assert(success); - } -} +#include "libnm-glib-aux/nm-test-utils.h" /*****************************************************************************/ @@ -347,7 +317,7 @@ nmtst_platform_ip6_routes_equal_aptr(const NMPObject *const * a, #ifdef __NETWORKMANAGER_IP4_CONFIG_H__ - #include "nm-glib-aux/nm-dedup-multi.h" + #include "libnm-glib-aux/nm-dedup-multi.h" static inline NMIP4Config * nmtst_ip4_config_new(int ifindex) @@ -361,7 +331,7 @@ nmtst_ip4_config_new(int ifindex) #ifdef __NETWORKMANAGER_IP6_CONFIG_H__ - #include "nm-glib-aux/nm-dedup-multi.h" + #include "libnm-glib-aux/nm-dedup-multi.h" static inline NMIP6Config * nmtst_ip6_config_new(int ifindex) diff --git a/src/core/nm-types.h b/src/core/nm-types.h index 8a32b7d2..7ad5aee1 100644 --- a/src/core/nm-types.h +++ b/src/core/nm-types.h @@ -10,8 +10,6 @@ #error Cannot use this header. #endif -#define _NM_SD_MAX_CLIENT_ID_LEN (sizeof(guint32) + 128) - /* core */ typedef struct _NMDBusObject NMDBusObject; typedef struct _NMActiveConnection NMActiveConnection; @@ -77,147 +75,6 @@ typedef enum { NM_ACTIVATION_REASON_USER_REQUEST, } NMActivationReason; -/* platform */ -typedef struct _NMPlatform NMPlatform; -typedef struct _NMPlatformObject NMPlatformObject; -typedef struct _NMPlatformObjWithIfindex NMPlatformObjWithIfindex; -typedef struct _NMPlatformIP4Address NMPlatformIP4Address; -typedef struct _NMPlatformIP4Route NMPlatformIP4Route; -typedef struct _NMPlatformIP6Address NMPlatformIP6Address; -typedef struct _NMPlatformIP6Route NMPlatformIP6Route; -typedef struct _NMPlatformLink NMPlatformLink; -typedef struct _NMPObject NMPObject; - -typedef enum { - - /* No type, used as error value */ - NM_LINK_TYPE_NONE, - - NM_LINK_TYPE_UNKNOWN, - - NM_LINK_TYPE_ANY, - -#define _NM_LINK_TYPE_REAL_FIRST NM_LINK_TYPE_ETHERNET - -/* Hardware types */ -#define _NM_LINK_TYPE_HW_FIRST NM_LINK_TYPE_ETHERNET - NM_LINK_TYPE_ETHERNET, - NM_LINK_TYPE_INFINIBAND, - NM_LINK_TYPE_OLPC_MESH, - NM_LINK_TYPE_WIFI, - NM_LINK_TYPE_WWAN_NET, /* WWAN kernel netdevice */ - NM_LINK_TYPE_WIMAX, - NM_LINK_TYPE_WPAN, - NM_LINK_TYPE_6LOWPAN, - NM_LINK_TYPE_WIFI_P2P, -#define _NM_LINK_TYPE_HW_LAST NM_LINK_TYPE_WIFI_P2P - -/* Software types */ -#define _NM_LINK_TYPE_SW_FIRST NM_LINK_TYPE_BNEP - NM_LINK_TYPE_BNEP, /* Bluetooth Ethernet emulation */ - NM_LINK_TYPE_DUMMY, - NM_LINK_TYPE_GRE, - NM_LINK_TYPE_GRETAP, - NM_LINK_TYPE_IFB, - NM_LINK_TYPE_IP6TNL, - NM_LINK_TYPE_IP6GRE, - NM_LINK_TYPE_IP6GRETAP, - NM_LINK_TYPE_IPIP, - NM_LINK_TYPE_LOOPBACK, - NM_LINK_TYPE_MACSEC, - NM_LINK_TYPE_MACVLAN, - NM_LINK_TYPE_MACVTAP, - NM_LINK_TYPE_OPENVSWITCH, - NM_LINK_TYPE_PPP, - NM_LINK_TYPE_SIT, - NM_LINK_TYPE_TUN, - NM_LINK_TYPE_VETH, - NM_LINK_TYPE_VLAN, - NM_LINK_TYPE_VRF, - NM_LINK_TYPE_VXLAN, - NM_LINK_TYPE_WIREGUARD, -#define _NM_LINK_TYPE_SW_LAST NM_LINK_TYPE_WIREGUARD - -/* Software types with slaves */ -#define _NM_LINK_TYPE_SW_MASTER_FIRST NM_LINK_TYPE_BRIDGE - NM_LINK_TYPE_BRIDGE, - NM_LINK_TYPE_BOND, - NM_LINK_TYPE_TEAM, -#define _NM_LINK_TYPE_SW_MASTER_LAST NM_LINK_TYPE_TEAM - -#define _NM_LINK_TYPE_REAL_LAST NM_LINK_TYPE_TEAM - -#define _NM_LINK_TYPE_REAL_NUM ((int) (_NM_LINK_TYPE_REAL_LAST - _NM_LINK_TYPE_REAL_FIRST + 1)) - -} NMLinkType; - -static inline gboolean -nm_link_type_is_software(NMLinkType link_type) -{ - G_STATIC_ASSERT(_NM_LINK_TYPE_SW_LAST + 1 == _NM_LINK_TYPE_SW_MASTER_FIRST); - - return link_type >= _NM_LINK_TYPE_SW_FIRST && link_type <= _NM_LINK_TYPE_SW_MASTER_LAST; -} - -static inline gboolean -nm_link_type_supports_slaves(NMLinkType link_type) -{ - return link_type >= _NM_LINK_TYPE_SW_MASTER_FIRST && link_type <= _NM_LINK_TYPE_SW_MASTER_LAST; -} - -typedef enum { - NMP_OBJECT_TYPE_UNKNOWN, - NMP_OBJECT_TYPE_LINK, - -#define NMP_OBJECT_TYPE_IP_ADDRESS(is_ipv4) \ - ((is_ipv4) ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS) - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS, - -#define NMP_OBJECT_TYPE_IP_ROUTE(is_ipv4) \ - ((is_ipv4) ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE) - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE, - - NMP_OBJECT_TYPE_ROUTING_RULE, - - NMP_OBJECT_TYPE_QDISC, - - NMP_OBJECT_TYPE_TFILTER, - - NMP_OBJECT_TYPE_LNK_BRIDGE, - NMP_OBJECT_TYPE_LNK_GRE, - NMP_OBJECT_TYPE_LNK_GRETAP, - NMP_OBJECT_TYPE_LNK_INFINIBAND, - NMP_OBJECT_TYPE_LNK_IP6TNL, - NMP_OBJECT_TYPE_LNK_IP6GRE, - NMP_OBJECT_TYPE_LNK_IP6GRETAP, - NMP_OBJECT_TYPE_LNK_IPIP, - NMP_OBJECT_TYPE_LNK_MACSEC, - NMP_OBJECT_TYPE_LNK_MACVLAN, - NMP_OBJECT_TYPE_LNK_MACVTAP, - NMP_OBJECT_TYPE_LNK_SIT, - NMP_OBJECT_TYPE_LNK_TUN, - NMP_OBJECT_TYPE_LNK_VLAN, - NMP_OBJECT_TYPE_LNK_VRF, - NMP_OBJECT_TYPE_LNK_VXLAN, - NMP_OBJECT_TYPE_LNK_WIREGUARD, - - __NMP_OBJECT_TYPE_LAST, - NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1, -} NMPObjectType; - -static inline guint32 -nmp_object_type_to_flags(NMPObjectType obj_type) -{ - G_STATIC_ASSERT_EXPR(NMP_OBJECT_TYPE_MAX < 32); - - nm_assert(_NM_INT_NOT_NEGATIVE(obj_type)); - nm_assert(obj_type < NMP_OBJECT_TYPE_MAX); - - return ((guint32) 1u) << obj_type; -} - /** * NMIPConfigMergeFlags: * @NM_IP_CONFIG_MERGE_DEFAULT: no flags set @@ -236,36 +93,12 @@ typedef enum { NM_IP_CONFIG_MERGE_EXTERNAL = (1LL << 3), } NMIPConfigMergeFlags; -/** - * NMIPRouteTableSyncMode: - * @NM_IP_ROUTE_TABLE_SYNC_MODE_NONE: indicate an invalid setting. - * @NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN: only the main table is synced. For all - * other tables, NM won't delete any extra routes. - * @NM_IP_ROUTE_TABLE_SYNC_MODE_FULL: NM will sync all tables, except the - * local table (255). - * @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL: NM will sync all tables, including the - * local table (255). - * @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE: NM will sync all tables (including - * the local table). It will thereby remove all addresses, that is during - * deactivation. - */ -typedef enum { - NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, - NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, - NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE, -} NMIPRouteTableSyncMode; - /* settings */ typedef struct _NMAgentManager NMAgentManager; typedef struct _NMSecretAgent NMSecretAgent; typedef struct _NMSettings NMSettings; typedef struct _NMSettingsConnection NMSettingsConnection; -/* utils */ -typedef struct _NMUtilsIPv6IfaceId NMUtilsIPv6IfaceId; - #define NM_SETTING_CONNECTION_MDNS_UNKNOWN ((NMSettingConnectionMdns) -42) #endif /* NM_TYPES_H */ diff --git a/src/core/platform/linux/nl802154.h b/src/core/platform/linux/nl802154.h deleted file mode 100644 index c21bd079..00000000 --- a/src/core/platform/linux/nl802154.h +++ /dev/null @@ -1,450 +0,0 @@ -#ifndef __NL802154_H -#define __NL802154_H -/* - * 802.15.4 netlink interface public header - * - * Copyright (C) 2014 Alexander Aring - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#define NL802154_GENL_NAME "nl802154" - -enum nl802154_commands { - /* don't change the order or add anything between, this is ABI! */ - /* currently we don't shipping this file via uapi, ignore the above one */ - NL802154_CMD_UNSPEC, - - NL802154_CMD_GET_WPAN_PHY, /* can dump */ - NL802154_CMD_SET_WPAN_PHY, - NL802154_CMD_NEW_WPAN_PHY, - NL802154_CMD_DEL_WPAN_PHY, - - NL802154_CMD_GET_INTERFACE, /* can dump */ - NL802154_CMD_SET_INTERFACE, - NL802154_CMD_NEW_INTERFACE, - NL802154_CMD_DEL_INTERFACE, - - NL802154_CMD_SET_CHANNEL, - - NL802154_CMD_SET_PAN_ID, - NL802154_CMD_SET_SHORT_ADDR, - - NL802154_CMD_SET_TX_POWER, - NL802154_CMD_SET_CCA_MODE, - NL802154_CMD_SET_CCA_ED_LEVEL, - - NL802154_CMD_SET_MAX_FRAME_RETRIES, - - NL802154_CMD_SET_BACKOFF_EXPONENT, - NL802154_CMD_SET_MAX_CSMA_BACKOFFS, - - NL802154_CMD_SET_LBT_MODE, - - NL802154_CMD_SET_ACKREQ_DEFAULT, - - NL802154_CMD_SET_WPAN_PHY_NETNS, - -/* add new commands above here */ - -#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL - NL802154_CMD_SET_SEC_PARAMS, - NL802154_CMD_GET_SEC_KEY, /* can dump */ - NL802154_CMD_NEW_SEC_KEY, - NL802154_CMD_DEL_SEC_KEY, - NL802154_CMD_GET_SEC_DEV, /* can dump */ - NL802154_CMD_NEW_SEC_DEV, - NL802154_CMD_DEL_SEC_DEV, - NL802154_CMD_GET_SEC_DEVKEY, /* can dump */ - NL802154_CMD_NEW_SEC_DEVKEY, - NL802154_CMD_DEL_SEC_DEVKEY, - NL802154_CMD_GET_SEC_LEVEL, /* can dump */ - NL802154_CMD_NEW_SEC_LEVEL, - NL802154_CMD_DEL_SEC_LEVEL, -#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ - - /* used to define NL802154_CMD_MAX below */ - __NL802154_CMD_AFTER_LAST, - NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1 -}; - -enum nl802154_attrs { - /* don't change the order or add anything between, this is ABI! */ - /* currently we don't shipping this file via uapi, ignore the above one */ - NL802154_ATTR_UNSPEC, - - NL802154_ATTR_WPAN_PHY, - NL802154_ATTR_WPAN_PHY_NAME, - - NL802154_ATTR_IFINDEX, - NL802154_ATTR_IFNAME, - NL802154_ATTR_IFTYPE, - - NL802154_ATTR_WPAN_DEV, - - NL802154_ATTR_PAGE, - NL802154_ATTR_CHANNEL, - - NL802154_ATTR_PAN_ID, - NL802154_ATTR_SHORT_ADDR, - - NL802154_ATTR_TX_POWER, - - NL802154_ATTR_CCA_MODE, - NL802154_ATTR_CCA_OPT, - NL802154_ATTR_CCA_ED_LEVEL, - - NL802154_ATTR_MAX_FRAME_RETRIES, - - NL802154_ATTR_MAX_BE, - NL802154_ATTR_MIN_BE, - NL802154_ATTR_MAX_CSMA_BACKOFFS, - - NL802154_ATTR_LBT_MODE, - - NL802154_ATTR_GENERATION, - - NL802154_ATTR_CHANNELS_SUPPORTED, - NL802154_ATTR_SUPPORTED_CHANNEL, - - NL802154_ATTR_EXTENDED_ADDR, - - NL802154_ATTR_WPAN_PHY_CAPS, - - NL802154_ATTR_SUPPORTED_COMMANDS, - - NL802154_ATTR_ACKREQ_DEFAULT, - - NL802154_ATTR_PAD, - - NL802154_ATTR_PID, - NL802154_ATTR_NETNS_FD, - -/* add attributes here, update the policy in nl802154.c */ - -#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL - NL802154_ATTR_SEC_ENABLED, - NL802154_ATTR_SEC_OUT_LEVEL, - NL802154_ATTR_SEC_OUT_KEY_ID, - NL802154_ATTR_SEC_FRAME_COUNTER, - - NL802154_ATTR_SEC_LEVEL, - NL802154_ATTR_SEC_DEVICE, - NL802154_ATTR_SEC_DEVKEY, - NL802154_ATTR_SEC_KEY, -#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ - - __NL802154_ATTR_AFTER_LAST, - NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 -}; - -enum nl802154_iftype { - /* for backwards compatibility TODO */ - NL802154_IFTYPE_UNSPEC = -1, - - NL802154_IFTYPE_NODE, - NL802154_IFTYPE_MONITOR, - NL802154_IFTYPE_COORD, - - /* keep last */ - NUM_NL802154_IFTYPES, - NL802154_IFTYPE_MAX = NUM_NL802154_IFTYPES - 1 -}; - -/** - * enum nl802154_wpan_phy_capability_attr - wpan phy capability attributes - * - * @__NL802154_CAP_ATTR_INVALID: attribute number 0 is reserved - * @NL802154_CAP_ATTR_CHANNELS: a nested attribute for nl802154_channel_attr - * @NL802154_CAP_ATTR_TX_POWERS: a nested attribute for nl802154_wpan_phy_tx_power - * @NL802154_CAP_ATTR_MIN_CCA_ED_LEVEL: minimum value for cca_ed_level - * @NL802154_CAP_ATTR_MAX_CCA_ED_LEVEL: maxmimum value for cca_ed_level - * @NL802154_CAP_ATTR_CCA_MODES: nl802154_cca_modes flags - * @NL802154_CAP_ATTR_CCA_OPTS: nl802154_cca_opts flags - * @NL802154_CAP_ATTR_MIN_MINBE: minimum of minbe value - * @NL802154_CAP_ATTR_MAX_MINBE: maximum of minbe value - * @NL802154_CAP_ATTR_MIN_MAXBE: minimum of maxbe value - * @NL802154_CAP_ATTR_MAX_MINBE: maximum of maxbe value - * @NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS: minimum of csma backoff value - * @NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS: maximum of csma backoffs value - * @NL802154_CAP_ATTR_MIN_FRAME_RETRIES: minimum of frame retries value - * @NL802154_CAP_ATTR_MAX_FRAME_RETRIES: maximum of frame retries value - * @NL802154_CAP_ATTR_IFTYPES: nl802154_iftype flags - * @NL802154_CAP_ATTR_LBT: nl802154_supported_bool_states flags - * @NL802154_CAP_ATTR_MAX: highest cap attribute currently defined - * @__NL802154_CAP_ATTR_AFTER_LAST: internal use - */ -enum nl802154_wpan_phy_capability_attr { - __NL802154_CAP_ATTR_INVALID, - - NL802154_CAP_ATTR_IFTYPES, - - NL802154_CAP_ATTR_CHANNELS, - NL802154_CAP_ATTR_TX_POWERS, - - NL802154_CAP_ATTR_CCA_ED_LEVELS, - NL802154_CAP_ATTR_CCA_MODES, - NL802154_CAP_ATTR_CCA_OPTS, - - NL802154_CAP_ATTR_MIN_MINBE, - NL802154_CAP_ATTR_MAX_MINBE, - - NL802154_CAP_ATTR_MIN_MAXBE, - NL802154_CAP_ATTR_MAX_MAXBE, - - NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS, - NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS, - - NL802154_CAP_ATTR_MIN_FRAME_RETRIES, - NL802154_CAP_ATTR_MAX_FRAME_RETRIES, - - NL802154_CAP_ATTR_LBT, - - /* keep last */ - __NL802154_CAP_ATTR_AFTER_LAST, - NL802154_CAP_ATTR_MAX = __NL802154_CAP_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl802154_cca_modes - cca modes - * - * @__NL802154_CCA_INVALID: cca mode number 0 is reserved - * @NL802154_CCA_ENERGY: Energy above threshold - * @NL802154_CCA_CARRIER: Carrier sense only - * @NL802154_CCA_ENERGY_CARRIER: Carrier sense with energy above threshold - * @NL802154_CCA_ALOHA: CCA shall always report an idle medium - * @NL802154_CCA_UWB_SHR: UWB preamble sense based on the SHR of a frame - * @NL802154_CCA_UWB_MULTIPLEXED: UWB preamble sense based on the packet with the multiplexed preamble - * @__NL802154_CCA_ATTR_AFTER_LAST: Internal - * @NL802154_CCA_ATTR_MAX: Maximum CCA attribute number - */ -enum nl802154_cca_modes { - __NL802154_CCA_INVALID, - NL802154_CCA_ENERGY, - NL802154_CCA_CARRIER, - NL802154_CCA_ENERGY_CARRIER, - NL802154_CCA_ALOHA, - NL802154_CCA_UWB_SHR, - NL802154_CCA_UWB_MULTIPLEXED, - - /* keep last */ - __NL802154_CCA_ATTR_AFTER_LAST, - NL802154_CCA_ATTR_MAX = __NL802154_CCA_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl802154_cca_opts - additional options for cca modes - * - * @NL802154_CCA_OPT_ENERGY_CARRIER_OR: NL802154_CCA_ENERGY_CARRIER with OR - * @NL802154_CCA_OPT_ENERGY_CARRIER_AND: NL802154_CCA_ENERGY_CARRIER with AND - */ -enum nl802154_cca_opts { - NL802154_CCA_OPT_ENERGY_CARRIER_AND, - NL802154_CCA_OPT_ENERGY_CARRIER_OR, - - /* keep last */ - __NL802154_CCA_OPT_ATTR_AFTER_LAST, - NL802154_CCA_OPT_ATTR_MAX = __NL802154_CCA_OPT_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl802154_supported_bool_states - bool states for bool capability entry - * - * @NL802154_SUPPORTED_BOOL_FALSE: indicates to set false - * @NL802154_SUPPORTED_BOOL_TRUE: indicates to set true - * @__NL802154_SUPPORTED_BOOL_INVALD: reserved - * @NL802154_SUPPORTED_BOOL_BOTH: indicates to set true and false - * @__NL802154_SUPPORTED_BOOL_AFTER_LAST: Internal - * @NL802154_SUPPORTED_BOOL_MAX: highest value for bool states - */ -enum nl802154_supported_bool_states { - NL802154_SUPPORTED_BOOL_FALSE, - NL802154_SUPPORTED_BOOL_TRUE, - /* to handle them in a mask */ - __NL802154_SUPPORTED_BOOL_INVALD, - NL802154_SUPPORTED_BOOL_BOTH, - - /* keep last */ - __NL802154_SUPPORTED_BOOL_AFTER_LAST, - NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1 -}; - -#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL - -enum nl802154_dev_addr_modes { - NL802154_DEV_ADDR_NONE, - __NL802154_DEV_ADDR_INVALID, - NL802154_DEV_ADDR_SHORT, - NL802154_DEV_ADDR_EXTENDED, - - /* keep last */ - __NL802154_DEV_ADDR_AFTER_LAST, - NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1 -}; - -enum nl802154_dev_addr_attrs { - NL802154_DEV_ADDR_ATTR_UNSPEC, - - NL802154_DEV_ADDR_ATTR_PAN_ID, - NL802154_DEV_ADDR_ATTR_MODE, - NL802154_DEV_ADDR_ATTR_SHORT, - NL802154_DEV_ADDR_ATTR_EXTENDED, - NL802154_DEV_ADDR_ATTR_PAD, - - /* keep last */ - __NL802154_DEV_ADDR_ATTR_AFTER_LAST, - NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1 -}; - -enum nl802154_key_id_modes { - NL802154_KEY_ID_MODE_IMPLICIT, - NL802154_KEY_ID_MODE_INDEX, - NL802154_KEY_ID_MODE_INDEX_SHORT, - NL802154_KEY_ID_MODE_INDEX_EXTENDED, - - /* keep last */ - __NL802154_KEY_ID_MODE_AFTER_LAST, - NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1 -}; - -enum nl802154_key_id_attrs { - NL802154_KEY_ID_ATTR_UNSPEC, - - NL802154_KEY_ID_ATTR_MODE, - NL802154_KEY_ID_ATTR_INDEX, - NL802154_KEY_ID_ATTR_IMPLICIT, - NL802154_KEY_ID_ATTR_SOURCE_SHORT, - NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, - NL802154_KEY_ID_ATTR_PAD, - - /* keep last */ - __NL802154_KEY_ID_ATTR_AFTER_LAST, - NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1 -}; - -enum nl802154_seclevels { - NL802154_SECLEVEL_NONE, - NL802154_SECLEVEL_MIC32, - NL802154_SECLEVEL_MIC64, - NL802154_SECLEVEL_MIC128, - NL802154_SECLEVEL_ENC, - NL802154_SECLEVEL_ENC_MIC32, - NL802154_SECLEVEL_ENC_MIC64, - NL802154_SECLEVEL_ENC_MIC128, - - /* keep last */ - __NL802154_SECLEVEL_AFTER_LAST, - NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1 -}; - -enum nl802154_frames { - NL802154_FRAME_BEACON, - NL802154_FRAME_DATA, - NL802154_FRAME_ACK, - NL802154_FRAME_CMD, - - /* keep last */ - __NL802154_FRAME_AFTER_LAST, - NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1 -}; - -enum nl802154_cmd_frames { - __NL802154_CMD_FRAME_INVALID, - NL802154_CMD_FRAME_ASSOC_REQUEST, - NL802154_CMD_FRAME_ASSOC_RESPONSE, - NL802154_CMD_FRAME_DISASSOC_NOTIFY, - NL802154_CMD_FRAME_DATA_REQUEST, - NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY, - NL802154_CMD_FRAME_ORPHAN_NOTIFY, - NL802154_CMD_FRAME_BEACON_REQUEST, - NL802154_CMD_FRAME_COORD_REALIGNMENT, - NL802154_CMD_FRAME_GTS_REQUEST, - - /* keep last */ - __NL802154_CMD_FRAME_AFTER_LAST, - NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1 -}; - -enum nl802154_seclevel_attrs { - NL802154_SECLEVEL_ATTR_UNSPEC, - - NL802154_SECLEVEL_ATTR_LEVELS, - NL802154_SECLEVEL_ATTR_FRAME, - NL802154_SECLEVEL_ATTR_CMD_FRAME, - NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, - - /* keep last */ - __NL802154_SECLEVEL_ATTR_AFTER_LAST, - NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1 -}; - -/* TODO what is this? couldn't find in mib */ -enum { - NL802154_DEVKEY_IGNORE, - NL802154_DEVKEY_RESTRICT, - NL802154_DEVKEY_RECORD, - - /* keep last */ - __NL802154_DEVKEY_AFTER_LAST, - NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1 -}; - -enum nl802154_dev { - NL802154_DEV_ATTR_UNSPEC, - - NL802154_DEV_ATTR_FRAME_COUNTER, - NL802154_DEV_ATTR_PAN_ID, - NL802154_DEV_ATTR_SHORT_ADDR, - NL802154_DEV_ATTR_EXTENDED_ADDR, - NL802154_DEV_ATTR_SECLEVEL_EXEMPT, - NL802154_DEV_ATTR_KEY_MODE, - NL802154_DEV_ATTR_PAD, - - /* keep last */ - __NL802154_DEV_ATTR_AFTER_LAST, - NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1 -}; - -enum nl802154_devkey { - NL802154_DEVKEY_ATTR_UNSPEC, - - NL802154_DEVKEY_ATTR_FRAME_COUNTER, - NL802154_DEVKEY_ATTR_EXTENDED_ADDR, - NL802154_DEVKEY_ATTR_ID, - NL802154_DEVKEY_ATTR_PAD, - - /* keep last */ - __NL802154_DEVKEY_ATTR_AFTER_LAST, - NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1 -}; - -enum nl802154_key { - NL802154_KEY_ATTR_UNSPEC, - - NL802154_KEY_ATTR_ID, - NL802154_KEY_ATTR_USAGE_FRAMES, - NL802154_KEY_ATTR_USAGE_CMDS, - NL802154_KEY_ATTR_BYTES, - - /* keep last */ - __NL802154_KEY_ATTR_AFTER_LAST, - NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1 -}; - - #define NL802154_KEY_SIZE 16 - #define NL802154_CMD_FRAME_NR_IDS 256 - -#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ - -#endif /* __NL802154_H */ diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c index 81c9f06c..b773df9a 100644 --- a/src/core/platform/nm-fake-platform.c +++ b/src/core/platform/nm-fake-platform.c @@ -13,12 +13,9 @@ #include #include -#include "nm-utils.h" - -#include "nm-core-utils.h" -#include "nm-platform/nm-platform-utils.h" -#include "nm-platform-private.h" -#include "nmp-object.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-platform/nm-platform-private.h" +#include "libnm-platform/nmp-object.h" #include "nm-test-utils-core.h" @@ -506,6 +503,21 @@ link_set_flags(NMPlatform *platform, NMFakePlatformLink *device, guint n_ifi_fla link_set_obj(platform, device, obj_tmp); } +static int +link_change_flags(NMPlatform *platform, int ifindex, unsigned flags_mask, unsigned flags_set) +{ + NMFakePlatformLink *device = link_get(platform, ifindex); + + if (!device) + return -ENOENT; + + link_set_flags(platform, + device, + NM_FLAGS_ASSIGN_MASK(device->obj->link.n_ifi_flags, flags_mask, flags_set)); + + return 0; +} + static void link_changed(NMPlatform * platform, NMFakePlatformLink *device, @@ -543,72 +555,13 @@ link_changed(NMPlatform * platform, } } -static gboolean -link_set_up(NMPlatform *platform, int ifindex, gboolean *out_no_firmware) -{ - NMFakePlatformLink *device = link_get(platform, ifindex); - - if (out_no_firmware) - *out_no_firmware = FALSE; - - if (!device) { - _LOGE("failure changing link: netlink error (No such device)"); - return FALSE; - } - - link_set_flags(platform, device, NM_FLAGS_ASSIGN(device->obj->link.n_ifi_flags, IFF_UP, TRUE)); - return TRUE; -} - -static gboolean -link_set_down(NMPlatform *platform, int ifindex) -{ - NMFakePlatformLink *device = link_get(platform, ifindex); - - if (!device) { - _LOGE("failure changing link: netlink error (No such device)"); - return FALSE; - } - - link_set_flags(platform, device, NM_FLAGS_UNSET(device->obj->link.n_ifi_flags, IFF_UP)); - return TRUE; -} - -static gboolean -link_set_arp(NMPlatform *platform, int ifindex) -{ - NMFakePlatformLink *device = link_get(platform, ifindex); - - if (!device) { - _LOGE("failure changing link: netlink error (No such device)"); - return FALSE; - } - - link_set_flags(platform, device, NM_FLAGS_UNSET(device->obj->link.n_ifi_flags, IFF_NOARP)); - return TRUE; -} - -static gboolean -link_set_noarp(NMPlatform *platform, int ifindex) -{ - NMFakePlatformLink *device = link_get(platform, ifindex); - - if (!device) { - _LOGE("failure changing link: netlink error (No such device)"); - return FALSE; - } - - link_set_flags(platform, device, NM_FLAGS_SET(device->obj->link.n_ifi_flags, IFF_NOARP)); - return TRUE; -} - static int link_set_address(NMPlatform *platform, int ifindex, gconstpointer addr, size_t len) { NMFakePlatformLink *device = link_get(platform, ifindex); nm_auto_nmpobj NMPObject *obj_tmp = NULL; - if (len == 0 || len > NM_UTILS_HWADDR_LEN_MAX || !addr) + if (len == 0 || len > _NM_UTILS_HWADDR_LEN_MAX || !addr) g_return_val_if_reached(-NME_BUG); if (!device) @@ -749,8 +702,8 @@ link_release(NMPlatform *platform, int master_idx, int slave_idx) static gboolean link_vlan_change(NMPlatform * platform, int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, + _NMVlanFlags flags_mask, + _NMVlanFlags flags_set, gboolean ingress_reset_all, const NMVlanQosMapping *ingress_map, gsize n_ingress_map, @@ -799,7 +752,7 @@ infiniband_partition_add(NMPlatform * platform, parent_device = link_get(platform, parent); g_return_val_if_fail(parent_device != NULL, FALSE); - nm_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key); + nmp_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key); link_add_one(platform, name, NM_LINK_TYPE_INFINIBAND, _infiniband_add_prepare, &d, out_link); return TRUE; @@ -814,12 +767,12 @@ infiniband_partition_delete(NMPlatform *platform, int parent, int p_key) parent_device = link_get(platform, parent); g_return_val_if_fail(parent_device != NULL, FALSE); - nm_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key); + nmp_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key); return link_delete(platform, nm_platform_link_get_ifindex(platform, name)); } static gboolean -wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) +wifi_get_capabilities(NMPlatform *platform, int ifindex, _NMDeviceWifiCapabilities *caps) { NMFakePlatformLink *device = link_get(platform, ifindex); @@ -829,10 +782,10 @@ wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilitie return FALSE; if (caps) { - *caps = (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104 - | NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP - | NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN | NM_WIFI_DEVICE_CAP_AP - | NM_WIFI_DEVICE_CAP_ADHOC); + *caps = (_NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | _NM_WIFI_DEVICE_CAP_CIPHER_WEP104 + | _NM_WIFI_DEVICE_CAP_CIPHER_TKIP | _NM_WIFI_DEVICE_CAP_CIPHER_CCMP + | _NM_WIFI_DEVICE_CAP_WPA | _NM_WIFI_DEVICE_CAP_RSN | _NM_WIFI_DEVICE_CAP_AP + | _NM_WIFI_DEVICE_CAP_ADHOC); } return TRUE; } @@ -861,14 +814,14 @@ wifi_get_rate(NMPlatform *platform, int ifindex) return 0; } -static NM80211Mode +static _NM80211Mode wifi_get_mode(NMPlatform *platform, int ifindex) { - return NM_802_11_MODE_UNKNOWN; + return _NM_802_11_MODE_UNKNOWN; } static void -wifi_set_mode(NMPlatform *platform, int ifindex, NM80211Mode mode) +wifi_set_mode(NMPlatform *platform, int ifindex, _NM80211Mode mode) { ; } @@ -1164,6 +1117,9 @@ ip_route_add(NMPlatform * platform, : NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route); r = NMP_OBJECT_CAST_IP_ROUTE(obj); + + r->is_external = TRUE; + nm_platform_ip_route_normalize(addr_family, r); switch (addr_family) { @@ -1357,14 +1313,11 @@ nm_fake_platform_class_init(NMFakePlatformClass *klass) platform_class->link_add = link_add; platform_class->link_delete = link_delete; - platform_class->link_set_up = link_set_up; - platform_class->link_set_down = link_set_down; - platform_class->link_set_arp = link_set_arp; - platform_class->link_set_noarp = link_set_noarp; - platform_class->link_set_address = link_set_address; platform_class->link_set_mtu = link_set_mtu; + platform_class->link_change_flags = link_change_flags; + platform_class->link_get_driver_info = link_get_driver_info; platform_class->link_supports_carrier_detect = link_supports_carrier_detect; diff --git a/src/core/platform/nm-fake-platform.h b/src/core/platform/nm-fake-platform.h index a1d44f8f..8f8571fa 100644 --- a/src/core/platform/nm-fake-platform.h +++ b/src/core/platform/nm-fake-platform.h @@ -6,7 +6,7 @@ #ifndef __NETWORKMANAGER_FAKE_PLATFORM_H__ #define __NETWORKMANAGER_FAKE_PLATFORM_H__ -#include "nm-platform.h" +#include "libnm-platform/nm-platform.h" #define NM_TYPE_FAKE_PLATFORM (nm_fake_platform_get_type()) #define NM_FAKE_PLATFORM(obj) \ diff --git a/src/core/platform/nm-linux-platform.c b/src/core/platform/nm-linux-platform.c deleted file mode 100644 index 7bd42bba..00000000 --- a/src/core/platform/nm-linux-platform.c +++ /dev/null @@ -1,9696 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2012 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-linux-platform.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-std-aux/unaligned.h" - -#include "nm-utils.h" -#include "nm-core-internal.h" -#include "nm-setting-vlan.h" - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-glib-aux/nm-c-list.h" -#include "nm-platform/nm-netlink.h" -#include "nm-core-utils.h" -#include "nmp-object.h" -#include "nm-platform/nmp-netns.h" -#include "nm-platform/nm-platform-utils.h" -#include "nm-platform-private.h" -#include "wifi/nm-wifi-utils.h" -#include "wifi/nm-wifi-utils-wext.h" -#include "wpan/nm-wpan-utils.h" -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-udev-aux/nm-udev-utils.h" - -/*****************************************************************************/ - -/* re-implement to build against kernel - * headers that lack this. */ - -#include - -struct tc_defact { - tc_gen; -}; - -enum { TCA_DEF_UNSPEC, TCA_DEF_TM, TCA_DEF_PARMS, TCA_DEF_DATA, TCA_DEF_PAD, __TCA_DEF_MAX }; -#define TCA_DEF_MAX (__TCA_DEF_MAX - 1) - -/*****************************************************************************/ - -/* Compat with older kernels. */ - -#define TCA_FQ_CODEL_CE_THRESHOLD 7 -#define TCA_FQ_CODEL_MEMORY_LIMIT 9 - -/*****************************************************************************/ - -#define VLAN_FLAG_MVRP 0x8 - -/*****************************************************************************/ - -#define IFQDISCSIZ 32 - -/*****************************************************************************/ - -#ifndef IFLA_PROMISCUITY - #define IFLA_PROMISCUITY 30 -#endif -#define IFLA_NUM_TX_QUEUES 31 -#define IFLA_NUM_RX_QUEUES 32 -#define IFLA_CARRIER 33 -#define IFLA_PHYS_PORT_ID 34 -#define IFLA_LINK_NETNSID 37 -#define __IFLA_MAX 39 - -#define IFLA_INET6_TOKEN 7 -#define IFLA_INET6_ADDR_GEN_MODE 8 -#define __IFLA_INET6_MAX 9 - -#define IFLA_VLAN_PROTOCOL 5 -#define __IFLA_VLAN_MAX 6 - -#define IFA_FLAGS 8 -#define __IFA_MAX 9 - -#define IFLA_MACVLAN_FLAGS 2 -#define __IFLA_MACVLAN_MAX 3 - -#define IFLA_IPTUN_LINK 1 -#define IFLA_IPTUN_LOCAL 2 -#define IFLA_IPTUN_REMOTE 3 -#define IFLA_IPTUN_TTL 4 -#define IFLA_IPTUN_TOS 5 -#define IFLA_IPTUN_ENCAP_LIMIT 6 -#define IFLA_IPTUN_FLOWINFO 7 -#define IFLA_IPTUN_FLAGS 8 -#define IFLA_IPTUN_PROTO 9 -#define IFLA_IPTUN_PMTUDISC 10 -#define __IFLA_IPTUN_MAX 19 -#ifndef IFLA_IPTUN_MAX - #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) -#endif - -#define IFLA_TUN_UNSPEC 0 -#define IFLA_TUN_OWNER 1 -#define IFLA_TUN_GROUP 2 -#define IFLA_TUN_TYPE 3 -#define IFLA_TUN_PI 4 -#define IFLA_TUN_VNET_HDR 5 -#define IFLA_TUN_PERSIST 6 -#define IFLA_TUN_MULTI_QUEUE 7 -#define IFLA_TUN_NUM_QUEUES 8 -#define IFLA_TUN_NUM_DISABLED_QUEUES 9 -#define __IFLA_TUN_MAX 10 -#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) - -G_STATIC_ASSERT(RTA_MAX == (__RTA_MAX - 1)); -#define RTA_PREF 20 -#undef RTA_MAX -#define RTA_MAX (MAX((__RTA_MAX - 1), RTA_PREF)) - -#ifndef MACVLAN_FLAG_NOPROMISC - #define MACVLAN_FLAG_NOPROMISC 1 -#endif - -#define IP6_FLOWINFO_TCLASS_MASK 0x0FF00000 -#define IP6_FLOWINFO_TCLASS_SHIFT 20 -#define IP6_FLOWINFO_FLOWLABEL_MASK 0x000FFFFF - -#define IFLA_BR_VLAN_STATS_ENABLED 41 - -/*****************************************************************************/ - -/* Appeared in the kernel prior to 3.13 dated 19 January, 2014 */ -#ifndef ARPHRD_6LOWPAN - #define ARPHRD_6LOWPAN 825 -#endif - -/*****************************************************************************/ - -#define FRA_TUN_ID 12 -#define FRA_SUPPRESS_IFGROUP 13 -#define FRA_SUPPRESS_PREFIXLEN 14 -#define FRA_PAD 18 -#define FRA_L3MDEV 19 -#define FRA_UID_RANGE 20 -#define FRA_PROTOCOL 21 -#define FRA_IP_PROTO 22 -#define FRA_SPORT_RANGE 23 -#define FRA_DPORT_RANGE 24 - -/*****************************************************************************/ - -#define IFLA_MACSEC_UNSPEC 0 -#define IFLA_MACSEC_SCI 1 -#define IFLA_MACSEC_PORT 2 -#define IFLA_MACSEC_ICV_LEN 3 -#define IFLA_MACSEC_CIPHER_SUITE 4 -#define IFLA_MACSEC_WINDOW 5 -#define IFLA_MACSEC_ENCODING_SA 6 -#define IFLA_MACSEC_ENCRYPT 7 -#define IFLA_MACSEC_PROTECT 8 -#define IFLA_MACSEC_INC_SCI 9 -#define IFLA_MACSEC_ES 10 -#define IFLA_MACSEC_SCB 11 -#define IFLA_MACSEC_REPLAY_PROTECT 12 -#define IFLA_MACSEC_VALIDATION 13 -#define IFLA_MACSEC_PAD 14 -#define __IFLA_MACSEC_MAX 15 - -/*****************************************************************************/ - -#define WG_CMD_GET_DEVICE 0 -#define WG_CMD_SET_DEVICE 1 - -#define WGDEVICE_F_REPLACE_PEERS ((guint32)(1U << 0)) - -#define WGPEER_F_REMOVE_ME ((guint32)(1U << 0)) -#define WGPEER_F_REPLACE_ALLOWEDIPS ((guint32)(1U << 1)) - -#define WGDEVICE_A_UNSPEC 0 -#define WGDEVICE_A_IFINDEX 1 -#define WGDEVICE_A_IFNAME 2 -#define WGDEVICE_A_PRIVATE_KEY 3 -#define WGDEVICE_A_PUBLIC_KEY 4 -#define WGDEVICE_A_FLAGS 5 -#define WGDEVICE_A_LISTEN_PORT 6 -#define WGDEVICE_A_FWMARK 7 -#define WGDEVICE_A_PEERS 8 -#define WGDEVICE_A_MAX 8 - -#define WGPEER_A_UNSPEC 0 -#define WGPEER_A_PUBLIC_KEY 1 -#define WGPEER_A_PRESHARED_KEY 2 -#define WGPEER_A_FLAGS 3 -#define WGPEER_A_ENDPOINT 4 -#define WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL 5 -#define WGPEER_A_LAST_HANDSHAKE_TIME 6 -#define WGPEER_A_RX_BYTES 7 -#define WGPEER_A_TX_BYTES 8 -#define WGPEER_A_ALLOWEDIPS 9 -#define WGPEER_A_MAX 9 - -#define WGALLOWEDIP_A_UNSPEC 0 -#define WGALLOWEDIP_A_FAMILY 1 -#define WGALLOWEDIP_A_IPADDR 2 -#define WGALLOWEDIP_A_CIDR_MASK 3 -#define WGALLOWEDIP_A_MAX 3 - -/*****************************************************************************/ - -/* Redefine VF enums and structures that are not available on older kernels. */ - -#define IFLA_VF_UNSPEC 0 -#define IFLA_VF_MAC 1 -#define IFLA_VF_VLAN 2 -#define IFLA_VF_TX_RATE 3 -#define IFLA_VF_SPOOFCHK 4 -#define IFLA_VF_LINK_STATE 5 -#define IFLA_VF_RATE 6 -#define IFLA_VF_RSS_QUERY_EN 7 -#define IFLA_VF_STATS 8 -#define IFLA_VF_TRUST 9 -#define IFLA_VF_IB_NODE_GUID 10 -#define IFLA_VF_IB_PORT_GUID 11 -#define IFLA_VF_VLAN_LIST 12 - -#define IFLA_VF_VLAN_INFO_UNSPEC 0 -#define IFLA_VF_VLAN_INFO 1 - -/* valid for TRUST, SPOOFCHK, LINK_STATE, RSS_QUERY_EN */ -struct _ifla_vf_setting { - guint32 vf; - guint32 setting; -}; - -struct _ifla_vf_rate { - guint32 vf; - guint32 min_tx_rate; - guint32 max_tx_rate; -}; - -struct _ifla_vf_vlan_info { - guint32 vf; - guint32 vlan; /* 0 - 4095, 0 disables VLAN filter */ - guint32 qos; - guint16 vlan_proto; /* VLAN protocol, either 802.1Q or 802.1ad */ -}; - -/*****************************************************************************/ - -/* Appeared in the kernel 4.0 dated April 12, 2015 */ -#ifndef BRIDGE_VLAN_INFO_RANGE_BEGIN - #define BRIDGE_VLAN_INFO_RANGE_BEGIN (1 << 3) /* VLAN is start of vlan range */ - #define BRIDGE_VLAN_INFO_RANGE_END (1 << 4) /* VLAN is end of vlan range */ -#endif - -/*****************************************************************************/ - -#define PSCHED_TIME_UNITS_PER_SEC 1000000 - -/*****************************************************************************/ - -typedef enum { - INFINIBAND_ACTION_CREATE_CHILD, - INFINIBAND_ACTION_DELETE_CHILD, -} InfinibandAction; - -typedef enum { - CHANGE_LINK_TYPE_UNSPEC, - CHANGE_LINK_TYPE_SET_MTU, - CHANGE_LINK_TYPE_SET_ADDRESS, -} ChangeLinkType; - -typedef struct { - union { - struct { - gconstpointer address; - gsize length; - } set_address; - }; -} ChangeLinkData; - -typedef enum { - _REFRESH_ALL_TYPE_FIRST = 0, - - REFRESH_ALL_TYPE_LINKS = 0, - REFRESH_ALL_TYPE_IP4_ADDRESSES = 1, - REFRESH_ALL_TYPE_IP6_ADDRESSES = 2, - REFRESH_ALL_TYPE_IP4_ROUTES = 3, - REFRESH_ALL_TYPE_IP6_ROUTES = 4, - REFRESH_ALL_TYPE_ROUTING_RULES_IP4 = 5, - REFRESH_ALL_TYPE_ROUTING_RULES_IP6 = 6, - REFRESH_ALL_TYPE_QDISCS = 7, - REFRESH_ALL_TYPE_TFILTERS = 8, - - _REFRESH_ALL_TYPE_NUM, -} RefreshAllType; - -typedef struct { - NMPObjectType obj_type; - - /* for NLM_F_DUMP, which address family to request. */ - int addr_family; -} RefreshAllInfo; - -typedef enum { - DELAYED_ACTION_TYPE_NONE = 0, - -#define F(val, name) ((sizeof(char[(((val)) == (name)) ? 1 : -1]) * 0) + (val)) - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS = 1 << F(0, REFRESH_ALL_TYPE_LINKS), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES = 1 << F(1, REFRESH_ALL_TYPE_IP4_ADDRESSES), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES = 1 << F(2, REFRESH_ALL_TYPE_IP6_ADDRESSES), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES = 1 << F(3, REFRESH_ALL_TYPE_IP4_ROUTES), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES = 1 << F(4, REFRESH_ALL_TYPE_IP6_ROUTES), - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4 = 1 - << F(5, REFRESH_ALL_TYPE_ROUTING_RULES_IP4), - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6 = 1 - << F(6, REFRESH_ALL_TYPE_ROUTING_RULES_IP6), - DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS = 1 << F(7, REFRESH_ALL_TYPE_QDISCS), - DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS = 1 << F(8, REFRESH_ALL_TYPE_TFILTERS), -#undef F - - DELAYED_ACTION_TYPE_REFRESH_LINK = 1 << 9, - DELAYED_ACTION_TYPE_MASTER_CONNECTED = 1 << 10, - DELAYED_ACTION_TYPE_READ_NETLINK = 1 << 11, - DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE = 1 << 12, - - __DELAYED_ACTION_TYPE_MAX, - - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL = - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4 - | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, - - DELAYED_ACTION_TYPE_REFRESH_ALL = - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS - | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - - DELAYED_ACTION_TYPE_MAX = __DELAYED_ACTION_TYPE_MAX - 1, -} DelayedActionType; - -#define FOR_EACH_DELAYED_ACTION(iflags, flags_all) \ - for ((iflags) = (DelayedActionType) 0x1LL; ({ \ - gboolean _good = FALSE; \ - \ - nm_assert(nm_utils_is_power_of_two(iflags)); \ - \ - while ((iflags) <= DELAYED_ACTION_TYPE_MAX) { \ - if (NM_FLAGS_ANY((flags_all), (iflags))) { \ - _good = TRUE; \ - break; \ - } \ - (iflags) <<= 1; \ - } \ - _good; \ - }); \ - (iflags) <<= 1) - -typedef enum { - /* Negative values are errors from kernel. Add dummy member to - * make enum signed. */ - _WAIT_FOR_NL_RESPONSE_RESULT_SYSTEM_ERROR = G_MININT, - - WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN = 0, - WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK, - WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS, -} WaitForNlResponseResult; - -typedef enum { - DELAYED_ACTION_RESPONSE_TYPE_VOID = 0, - DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS = 1, - DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET = 2, -} DelayedActionWaitForNlResponseType; - -typedef struct { - guint32 seq_number; - WaitForNlResponseResult seq_result; - DelayedActionWaitForNlResponseType response_type; - gint64 timeout_abs_ns; - WaitForNlResponseResult * out_seq_result; - char ** out_errmsg; - union { - int * out_refresh_all_in_progress; - NMPObject **out_route_get; - gpointer out_data; - } response; -} DelayedActionWaitForNlResponseData; - -/*****************************************************************************/ - -typedef struct { - struct nl_sock *genl; - - struct nl_sock *nlh; - - GSource *event_source; - - guint32 nlh_seq_next; -#if NM_MORE_LOGGING - guint32 nlh_seq_last_handled; -#endif - guint32 nlh_seq_last_seen; - - guint32 pruning[_REFRESH_ALL_TYPE_NUM]; - - GHashTable *sysctl_get_prev_values; - CList sysctl_list; - - NMUdevClient *udev_client; - - struct { - /* which delayed actions are scheduled, as marked in @flags. - * Some types have additional arguments in the fields below. */ - DelayedActionType flags; - - /* counter that a refresh all action is in progress, separated - * by type. */ - int refresh_all_in_progress[_REFRESH_ALL_TYPE_NUM]; - - GPtrArray *list_master_connected; - GPtrArray *list_refresh_link; - GArray * list_wait_for_nl_response; - - int is_handling; - } delayed_action; -} NMLinuxPlatformPrivate; - -struct _NMLinuxPlatform { - NMPlatform parent; - NMLinuxPlatformPrivate _priv; -}; - -struct _NMLinuxPlatformClass { - NMPlatformClass parent; -}; - -G_DEFINE_TYPE(NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM) - -#define NM_LINUX_PLATFORM_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMLinuxPlatform, NM_IS_LINUX_PLATFORM, NMPlatform) - -/*****************************************************************************/ - -#define _NMLOG_PREFIX_NAME "platform-linux" -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG2_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, platform, __VA_ARGS__) -#define _NMLOG_err(errsv, level, ...) _LOG_err(errsv, level, _NMLOG_DOMAIN, platform, __VA_ARGS__) -#define _NMLOG2(level, ...) _LOG(level, _NMLOG2_DOMAIN, NULL, __VA_ARGS__) -#define _NMLOG2_err(errsv, level, ...) _LOG_err(errsv, level, _NMLOG2_DOMAIN, NULL, __VA_ARGS__) - -#define _LOG_print(__level, __domain, __errsv, self, ...) \ - G_STMT_START \ - { \ - char __prefix[32]; \ - const char * __p_prefix = _NMLOG_PREFIX_NAME; \ - NMPlatform *const __self = (self); \ - \ - if (__self && nm_platform_get_log_with_ptr(__self)) { \ - g_snprintf(__prefix, sizeof(__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ - __p_prefix = __prefix; \ - } \ - _nm_log(__level, \ - __domain, \ - __errsv, \ - NULL, \ - NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __p_prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -#define _LOG(level, domain, self, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ - \ - if (nm_logging_enabled(__level, __domain)) { \ - _LOG_print(__level, __domain, 0, self, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - -#define _LOG_err(errsv, level, domain, self, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ - \ - if (nm_logging_enabled(__level, __domain)) { \ - int __errsv = (errsv); \ - \ - /* The %m format specifier (GNU extension) would already allow you to specify the error - * message conveniently (and nm_log would get that right too). But we don't want to depend - * on that, so instead append the message at the end. - * Currently, users are expected not to use %m in the format string. */ \ - _LOG_print( \ - __level, \ - __domain, \ - __errsv, \ - self, \ - _NM_UTILS_MACRO_FIRST(__VA_ARGS__) ": %s (%d)" _NM_UTILS_MACRO_REST(__VA_ARGS__), \ - nm_strerror_native(__errsv), \ - __errsv); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static void -delayed_action_schedule(NMPlatform *platform, DelayedActionType action_type, gpointer user_data); -static gboolean delayed_action_handle_all(NMPlatform *platform, gboolean read_netlink); -static void do_request_link_no_delayed_actions(NMPlatform *platform, int ifindex, const char *name); -static void do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action_type); -static void cache_on_change(NMPlatform * platform, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new); -static void cache_prune_all(NMPlatform *platform); -static gboolean event_handler_read_netlink(NMPlatform *platform, gboolean wait_for_acks); -static struct nl_sock *_genl_sock(NMLinuxPlatform *platform); - -/*****************************************************************************/ - -static int -wait_for_nl_response_to_nmerr(WaitForNlResponseResult seq_result) -{ - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - if (seq_result < 0) - return (int) seq_result; - return -NME_PL_NETLINK; -} - -static const char * -wait_for_nl_response_to_string(WaitForNlResponseResult seq_result, - const char * errmsg, - char * buf, - gsize buf_size) -{ - char *buf0 = buf; - - switch (seq_result) { - case WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN: - nm_utils_strbuf_append_str(&buf, &buf_size, "unknown"); - break; - case WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK: - nm_utils_strbuf_append_str(&buf, &buf_size, "success"); - break; - case WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN: - nm_utils_strbuf_append_str(&buf, &buf_size, "failure"); - break; - default: - if (seq_result < 0) { - nm_utils_strbuf_append(&buf, - &buf_size, - "failure %d (%s%s%s)", - -((int) seq_result), - nm_strerror_native(-((int) seq_result)), - errmsg ? " - " : "", - errmsg ?: ""); - } else - nm_utils_strbuf_append(&buf, &buf_size, "internal failure %d", (int) seq_result); - break; - } - return buf0; -} - -/****************************************************************** - * Various utilities - ******************************************************************/ - -static int -_vlan_qos_mapping_cmp_from(gconstpointer a, gconstpointer b, gpointer user_data) -{ - const NMVlanQosMapping *map_a = a; - const NMVlanQosMapping *map_b = b; - - if (map_a->from != map_b->from) - return map_a->from < map_b->from ? -1 : 1; - return 0; -} - -static int -_vlan_qos_mapping_cmp_from_ptr(gconstpointer a, gconstpointer b, gpointer user_data) -{ - return _vlan_qos_mapping_cmp_from(*((const NMVlanQosMapping **) a), - *((const NMVlanQosMapping **) b), - NULL); -} - -/****************************************************************** - * NMLinkType functions - ******************************************************************/ - -typedef struct { - const char *type_string; - - /* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type - * should only be specified if the device type can be created without - * additional parameters, and if the device type can be determined from - * the rtnl_type. eg, tun/tap should not be specified since both - * tun and tap devices use "tun", and InfiniBand should not be - * specified because a PKey is required at creation. Drivers set this - * value from their 'struct rtnl_link_ops' structure. - */ - const char *rtnl_type; - - /* uevent DEVTYPE where applicable, from /sys/class/net//uevent; - * drivers set this value from their SET_NETDEV_DEV() call and the - * 'struct device_type' name member. - */ - const char *devtype; -} LinkDesc; - -static const LinkDesc link_descs[] = { - [NM_LINK_TYPE_NONE] = {"none", NULL, NULL}, - [NM_LINK_TYPE_UNKNOWN] = {"unknown", NULL, NULL}, - [NM_LINK_TYPE_ANY] = {"any", NULL, NULL}, - - [NM_LINK_TYPE_ETHERNET] = {"ethernet", NULL, NULL}, - [NM_LINK_TYPE_INFINIBAND] = {"infiniband", NULL, NULL}, - [NM_LINK_TYPE_OLPC_MESH] = {"olpc-mesh", NULL, NULL}, - [NM_LINK_TYPE_WIFI] = {"wifi", NULL, "wlan"}, - [NM_LINK_TYPE_WWAN_NET] = {"wwan", NULL, "wwan"}, - [NM_LINK_TYPE_WIMAX] = {"wimax", "wimax", "wimax"}, - [NM_LINK_TYPE_WPAN] = {"wpan", NULL, NULL}, - [NM_LINK_TYPE_6LOWPAN] = {"6lowpan", NULL, NULL}, - - [NM_LINK_TYPE_BNEP] = {"bluetooth", NULL, "bluetooth"}, - [NM_LINK_TYPE_DUMMY] = {"dummy", "dummy", NULL}, - [NM_LINK_TYPE_GRE] = {"gre", "gre", NULL}, - [NM_LINK_TYPE_GRETAP] = {"gretap", "gretap", NULL}, - [NM_LINK_TYPE_IFB] = {"ifb", "ifb", NULL}, - [NM_LINK_TYPE_IP6TNL] = {"ip6tnl", "ip6tnl", NULL}, - [NM_LINK_TYPE_IP6GRE] = {"ip6gre", "ip6gre", NULL}, - [NM_LINK_TYPE_IP6GRETAP] = {"ip6gretap", "ip6gretap", NULL}, - [NM_LINK_TYPE_IPIP] = {"ipip", "ipip", NULL}, - [NM_LINK_TYPE_LOOPBACK] = {"loopback", NULL, NULL}, - [NM_LINK_TYPE_MACSEC] = {"macsec", "macsec", NULL}, - [NM_LINK_TYPE_MACVLAN] = {"macvlan", "macvlan", NULL}, - [NM_LINK_TYPE_MACVTAP] = {"macvtap", "macvtap", NULL}, - [NM_LINK_TYPE_OPENVSWITCH] = {"openvswitch", "openvswitch", NULL}, - [NM_LINK_TYPE_PPP] = {"ppp", NULL, "ppp"}, - [NM_LINK_TYPE_SIT] = {"sit", "sit", NULL}, - [NM_LINK_TYPE_TUN] = {"tun", "tun", NULL}, - [NM_LINK_TYPE_VETH] = {"veth", "veth", NULL}, - [NM_LINK_TYPE_VLAN] = {"vlan", "vlan", "vlan"}, - [NM_LINK_TYPE_VRF] = {"vrf", "vrf", "vrf"}, - [NM_LINK_TYPE_VXLAN] = {"vxlan", "vxlan", "vxlan"}, - [NM_LINK_TYPE_WIREGUARD] = {"wireguard", "wireguard", "wireguard"}, - - [NM_LINK_TYPE_BRIDGE] = {"bridge", "bridge", "bridge"}, - [NM_LINK_TYPE_BOND] = {"bond", "bond", "bond"}, - [NM_LINK_TYPE_TEAM] = {"team", "team", NULL}, -}; - -static const LinkDesc * -_link_desc_from_link_type(NMLinkType link_type) -{ - nm_assert(_NM_INT_NOT_NEGATIVE(link_type)); - nm_assert(link_type < G_N_ELEMENTS(link_descs)); - nm_assert(link_descs[link_type].type_string); - - return &link_descs[link_type]; -} - -static NMLinkType -_link_type_from_rtnl_type(const char *name) -{ - static const NMLinkType LIST[] = { - NM_LINK_TYPE_BOND, /* "bond" */ - NM_LINK_TYPE_BRIDGE, /* "bridge" */ - NM_LINK_TYPE_DUMMY, /* "dummy" */ - NM_LINK_TYPE_GRE, /* "gre" */ - NM_LINK_TYPE_GRETAP, /* "gretap" */ - NM_LINK_TYPE_IFB, /* "ifb" */ - NM_LINK_TYPE_IP6GRE, /* "ip6gre" */ - NM_LINK_TYPE_IP6GRETAP, /* "ip6gretap" */ - NM_LINK_TYPE_IP6TNL, /* "ip6tnl" */ - NM_LINK_TYPE_IPIP, /* "ipip" */ - NM_LINK_TYPE_MACSEC, /* "macsec" */ - NM_LINK_TYPE_MACVLAN, /* "macvlan" */ - NM_LINK_TYPE_MACVTAP, /* "macvtap" */ - NM_LINK_TYPE_OPENVSWITCH, /* "openvswitch" */ - NM_LINK_TYPE_SIT, /* "sit" */ - NM_LINK_TYPE_TEAM, /* "team" */ - NM_LINK_TYPE_TUN, /* "tun" */ - NM_LINK_TYPE_VETH, /* "veth" */ - NM_LINK_TYPE_VLAN, /* "vlan" */ - NM_LINK_TYPE_VRF, /* "vrf" */ - NM_LINK_TYPE_VXLAN, /* "vxlan" */ - NM_LINK_TYPE_WIMAX, /* "wimax" */ - NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ - }; - - nm_assert(name); - - if (NM_MORE_ASSERT_ONCE(5)) { - int i, j, k; - - for (i = 0; i < G_N_ELEMENTS(LIST); i++) { - nm_assert(_link_desc_from_link_type(LIST[i]) == &link_descs[LIST[i]]); - nm_assert(link_descs[LIST[i]].rtnl_type); - if (i > 0) - nm_assert(strcmp(link_descs[LIST[i - 1]].rtnl_type, link_descs[LIST[i]].rtnl_type) - < 0); - } - for (i = 0; i < G_N_ELEMENTS(link_descs); i++) { - if (!link_descs[i].rtnl_type) - continue; - for (j = 0, k = 0; j < G_N_ELEMENTS(LIST); j++) - k += (LIST[j] == i); - nm_assert(k == 1); - } - } - - { - int imin = 0; - int imax = (G_N_ELEMENTS(LIST) - 1); - int imid = (G_N_ELEMENTS(LIST) - 1) / 2; - - for (;;) { - const int cmp = strcmp(link_descs[LIST[imid]].rtnl_type, name); - - if (G_UNLIKELY(cmp == 0)) - return LIST[imid]; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - - if (G_UNLIKELY(imin > imax)) - return NM_LINK_TYPE_NONE; - - imid = (imin + imax) / 2; - } - } -} - -static NMLinkType -_link_type_from_devtype(const char *name) -{ - static const NMLinkType LIST[] = { - NM_LINK_TYPE_BNEP, /* "bluetooth" */ - NM_LINK_TYPE_BOND, /* "bond" */ - NM_LINK_TYPE_BRIDGE, /* "bridge" */ - NM_LINK_TYPE_PPP, /* "ppp" */ - NM_LINK_TYPE_VLAN, /* "vlan" */ - NM_LINK_TYPE_VRF, /* "vrf" */ - NM_LINK_TYPE_VXLAN, /* "vxlan" */ - NM_LINK_TYPE_WIMAX, /* "wimax" */ - NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ - NM_LINK_TYPE_WIFI, /* "wlan" */ - NM_LINK_TYPE_WWAN_NET, /* "wwan" */ - }; - - nm_assert(name); - - if (NM_MORE_ASSERT_ONCE(5)) { - int i, j, k; - - for (i = 0; i < G_N_ELEMENTS(LIST); i++) { - nm_assert(_link_desc_from_link_type(LIST[i]) == &link_descs[LIST[i]]); - nm_assert(link_descs[LIST[i]].devtype); - if (i > 0) - nm_assert(strcmp(link_descs[LIST[i - 1]].devtype, link_descs[LIST[i]].devtype) < 0); - } - for (i = 0; i < G_N_ELEMENTS(link_descs); i++) { - if (!link_descs[i].devtype) - continue; - for (j = 0, k = 0; j < G_N_ELEMENTS(LIST); j++) - k += (LIST[j] == i); - nm_assert(k == 1); - } - } - - { - int imin = 0; - int imax = (G_N_ELEMENTS(LIST) - 1); - int imid = (G_N_ELEMENTS(LIST) - 1) / 2; - - for (;;) { - const int cmp = strcmp(link_descs[LIST[imid]].devtype, name); - - if (G_UNLIKELY(cmp == 0)) - return LIST[imid]; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - - if (G_UNLIKELY(imin > imax)) - return NM_LINK_TYPE_NONE; - - imid = (imin + imax) / 2; - } - } -} - -static const char * -nm_link_type_to_rtnl_type_string(NMLinkType link_type) -{ - return _link_desc_from_link_type(link_type)->rtnl_type; -} - -const char * -nm_link_type_to_string(NMLinkType link_type) -{ - return _link_desc_from_link_type(link_type)->type_string; -} - -/****************************************************************** - * Utilities - ******************************************************************/ - -/* _timestamp_nl_to_ms: - * @timestamp_nl: a timestamp from ifa_cacheinfo. - * @monotonic_ms: *now* in CLOCK_MONOTONIC. Needed to estimate the current - * uptime and how often timestamp_nl wrapped. - * - * Convert the timestamp from ifa_cacheinfo to CLOCK_MONOTONIC milliseconds. - * The ifa_cacheinfo fields tstamp and cstamp contains timestamps that counts - * with in 1/100th of a second of clock_gettime(CLOCK_MONOTONIC). However, - * the uint32 counter wraps every 497 days of uptime, so we have to compensate - * for that. */ -static gint64 -_timestamp_nl_to_ms(guint32 timestamp_nl, gint64 monotonic_ms) -{ - const gint64 WRAP_INTERVAL = (((gint64) G_MAXUINT32) + 1) * (1000 / 100); - gint64 timestamp_nl_ms; - - /* convert timestamp from 1/100th of a second to msec. */ - timestamp_nl_ms = ((gint64) timestamp_nl) * (1000 / 100); - - /* timestamp wraps every 497 days. Try to compensate for that.*/ - if (timestamp_nl_ms > monotonic_ms) { - /* timestamp_nl_ms is in the future. Truncate it to *now* */ - timestamp_nl_ms = monotonic_ms; - } else if (monotonic_ms >= WRAP_INTERVAL) { - timestamp_nl_ms += (monotonic_ms / WRAP_INTERVAL) * WRAP_INTERVAL; - if (timestamp_nl_ms > monotonic_ms) - timestamp_nl_ms -= WRAP_INTERVAL; - } - - return timestamp_nl_ms; -} - -static guint32 -_addrtime_timestamp_to_nm(guint32 timestamp, gint32 *out_now_nm) -{ - gint64 now_nl; - gint64 now_nm; - gint64 result; - - /* timestamp is unset. Default to 1. */ - if (!timestamp) { - NM_SET_OUT(out_now_nm, 0); - return 1; - } - - /* do all the calculations in milliseconds scale */ - - now_nm = nm_utils_get_monotonic_timestamp_msec(); - now_nl = nm_utils_clock_gettime_msec(CLOCK_MONOTONIC); - - nm_assert(now_nm >= 1000); - nm_assert(now_nl >= 0); - - result = now_nm - (now_nl - _timestamp_nl_to_ms(timestamp, now_nl)); - - NM_SET_OUT(out_now_nm, now_nm / 1000); - - /* converting the timestamp into nm_utils_get_monotonic_timestamp_msec() scale is - * a good guess but fails in the following situations: - * - * - If the address existed before start of the process, the timestamp in nm scale would - * be negative or zero. In this case we default to 1. - * - during hibernation, the CLOCK_MONOTONIC/timestamp drifts from - * nm_utils_get_monotonic_timestamp_msec() scale. - */ - if (result <= 1000) - return 1; - - if (result > now_nm) - return now_nm / 1000; - - return result / 1000; -} - -static guint32 -_addrtime_extend_lifetime(guint32 lifetime, guint32 seconds) -{ - guint64 v; - - if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT || seconds == 0) - return lifetime; - - v = (guint64) lifetime + (guint64) seconds; - return MIN(v, NM_PLATFORM_LIFETIME_PERMANENT - 1); -} - -/* The rtnl_addr object contains relative lifetimes @valid and @preferred - * that count in seconds, starting from the moment when the kernel constructed - * the netlink message. - * - * There is also a field rtnl_addr_last_update_time(), which is the absolute - * time in 1/100th of a second of clock_gettime (CLOCK_MONOTONIC) when the address - * was modified (wrapping every 497 days). - * Immediately at the time when the address was last modified, #NOW and @last_update_time - * are the same, so (only) in that case @valid and @preferred are anchored at @last_update_time. - * However, this is not true in general. As time goes by, whenever kernel sends a new address - * via netlink, the lifetimes keep counting down. - **/ -static void -_addrtime_get_lifetimes(guint32 timestamp, - guint32 lifetime, - guint32 preferred, - guint32 *out_timestamp, - guint32 *out_lifetime, - guint32 *out_preferred) -{ - gint32 now; - - if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { - if (preferred > lifetime) - preferred = lifetime; - timestamp = _addrtime_timestamp_to_nm(timestamp, &now); - - if (now == 0) { - /* strange. failed to detect the last-update time and assumed that timestamp is 1. */ - nm_assert(timestamp == 1); - now = nm_utils_get_monotonic_timestamp_sec(); - } - if (timestamp < now) { - guint32 diff = now - timestamp; - - lifetime = _addrtime_extend_lifetime(lifetime, diff); - preferred = _addrtime_extend_lifetime(preferred, diff); - } else - nm_assert(timestamp == now); - } else - timestamp = 0; - *out_timestamp = timestamp; - *out_lifetime = lifetime; - *out_preferred = preferred; -} - -/*****************************************************************************/ - -static const NMPObject * -_lookup_cached_link(const NMPCache * cache, - int ifindex, - gboolean * completed_from_cache, - const NMPObject **link_cached) -{ - const NMPObject *obj; - - nm_assert(completed_from_cache && link_cached); - - if (!*completed_from_cache) { - obj = ifindex > 0 && cache ? nmp_cache_lookup_link(cache, ifindex) : NULL; - - *link_cached = obj; - *completed_from_cache = TRUE; - } - return *link_cached; -} - -/*****************************************************************************/ - -#define DEVTYPE_PREFIX "DEVTYPE=" - -static char * -_linktype_read_devtype(int dirfd) -{ - gs_free char *contents = NULL; - char * cont, *end; - - nm_assert(dirfd >= 0); - - if (!nm_utils_file_get_contents(dirfd, - "uevent", - 1 * 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - NULL, - NULL, - NULL)) - return NULL; - for (cont = contents; cont; cont = end) { - end = strpbrk(cont, "\r\n"); - if (end) - *end++ = '\0'; - if (strncmp(cont, DEVTYPE_PREFIX, NM_STRLEN(DEVTYPE_PREFIX)) == 0) { - cont += NM_STRLEN(DEVTYPE_PREFIX); - memmove(contents, cont, strlen(cont) + 1); - return g_steal_pointer(&contents); - } - } - return NULL; -} - -static NMLinkType -_linktype_get_type(NMPlatform * platform, - const NMPCache * cache, - const char * kind, - int ifindex, - const char * ifname, - unsigned flags, - unsigned arptype, - gboolean * completed_from_cache, - const NMPObject **link_cached, - const char ** out_kind) -{ - NMLinkType link_type; - - NMTST_ASSERT_PLATFORM_NETNS_CURRENT(platform); - nm_assert(ifname); - nm_assert(_link_type_from_devtype("wlan") == NM_LINK_TYPE_WIFI); - nm_assert(_link_type_from_rtnl_type("bond") == NM_LINK_TYPE_BOND); - - if (completed_from_cache) { - const NMPObject *obj; - - obj = _lookup_cached_link(cache, ifindex, completed_from_cache, link_cached); - - /* If we detected the link type before, we stick to that - * decision unless the "kind" or "name" changed. If "name" changed, - * it means that their type may not have been determined correctly - * due to race conditions while accessing sysfs. - * - * This way, we save additional ethtool/sysctl lookups, but moreover, - * we keep the linktype stable and don't change it as long as the link - * exists. - * - * Note that kernel *can* reuse the ifindex (on integer overflow, and - * when moving interface to other netns). Thus here there is a tiny potential - * of messing stuff up. */ - if (obj && obj->_link.netlink.is_in_netlink - && !NM_IN_SET(obj->link.type, NM_LINK_TYPE_UNKNOWN, NM_LINK_TYPE_NONE) - && nm_streq(ifname, obj->link.name) && (!kind || nm_streq0(kind, obj->link.kind))) { - nm_assert(obj->link.kind == g_intern_string(obj->link.kind)); - *out_kind = obj->link.kind; - return obj->link.type; - } - } - - /* we intern kind to not require us to keep the pointer alive. Essentially - * leaking it in a global cache. That should be safe enough, because the - * kind comes only from kernel messages, which depend on the number of - * available drivers. So, there is not the danger that we leak uncontrolled - * many kinds. */ - *out_kind = g_intern_string(kind); - - if (kind) { - link_type = _link_type_from_rtnl_type(kind); - if (link_type != NM_LINK_TYPE_NONE) - return link_type; - } - - if (arptype == ARPHRD_LOOPBACK) - return NM_LINK_TYPE_LOOPBACK; - else if (arptype == ARPHRD_INFINIBAND) - return NM_LINK_TYPE_INFINIBAND; - else if (arptype == ARPHRD_SIT) - return NM_LINK_TYPE_SIT; - else if (arptype == ARPHRD_TUNNEL6) - return NM_LINK_TYPE_IP6TNL; - else if (arptype == ARPHRD_PPP) - return NM_LINK_TYPE_PPP; - else if (arptype == ARPHRD_IEEE802154) - return NM_LINK_TYPE_WPAN; - else if (arptype == ARPHRD_6LOWPAN) - return NM_LINK_TYPE_6LOWPAN; - - { - NMPUtilsEthtoolDriverInfo driver_info; - - /* Fallback OVS detection for kernel <= 3.16 */ - if (nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) { - if (nm_streq(driver_info.driver, "openvswitch")) - return NM_LINK_TYPE_OPENVSWITCH; - - if (arptype == 256) { - /* Some s390 CTC-type devices report 256 for the encapsulation type - * for some reason, but we need to call them Ethernet. - */ - if (nm_streq(driver_info.driver, "ctcm")) - return NM_LINK_TYPE_ETHERNET; - } - } - } - - { - nm_auto_close int dirfd = -1; - gs_free char * devtype = NULL; - char ifname_verified[IFNAMSIZ]; - - dirfd = nmp_utils_sysctl_open_netdir(ifindex, ifname, ifname_verified); - if (dirfd >= 0) { - if (faccessat(dirfd, "anycast_mask", F_OK, 0) == 0) - return NM_LINK_TYPE_OLPC_MESH; - - devtype = _linktype_read_devtype(dirfd); - if (devtype) { - link_type = _link_type_from_devtype(devtype); - if (link_type != NM_LINK_TYPE_NONE) { - if (link_type == NM_LINK_TYPE_BNEP && arptype != ARPHRD_ETHER) { - /* Both BNEP and 6lowpan use DEVTYPE=bluetooth, so we must - * use arptype to distinguish between them. - */ - } else - return link_type; - } - } - - /* Fallback for drivers that don't call SET_NETDEV_DEVTYPE() */ - if (nm_wifi_utils_is_wifi(dirfd, ifname_verified)) - return NM_LINK_TYPE_WIFI; - } - - if (arptype == ARPHRD_ETHER) { - /* Misc non-upstream WWAN drivers. rmnet is Qualcomm's proprietary - * modem interface, ccmni is MediaTek's. FIXME: these drivers should - * really set devtype=WWAN. - */ - if (g_str_has_prefix(ifname, "rmnet") || g_str_has_prefix(ifname, "rev_rmnet") - || g_str_has_prefix(ifname, "ccmni")) - return NM_LINK_TYPE_WWAN_NET; - - /* Standard wired ethernet interfaces don't report an rtnl_link_type, so - * only allow fallback to Ethernet if no type is given. This should - * prevent future virtual network drivers from being treated as Ethernet - * when they should be Generic instead. - */ - if (!kind && !devtype) - return NM_LINK_TYPE_ETHERNET; - - /* The USB gadget interfaces behave and look like ordinary ethernet devices - * aside from the DEVTYPE. */ - if (nm_streq0(devtype, "gadget")) - return NM_LINK_TYPE_ETHERNET; - - /* Distributed Switch Architecture switch chips */ - if (nm_streq0(devtype, "dsa")) - return NM_LINK_TYPE_ETHERNET; - } - } - - return NM_LINK_TYPE_UNKNOWN; -} - -/****************************************************************** - * libnl unility functions and wrappers - ******************************************************************/ - -#define NLMSG_TAIL(nmsg) ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -/* copied from iproute2's addattr_l(). */ -static gboolean -_nl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) -{ - int len = RTA_LENGTH(alen); - struct rtattr *rta; - - if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) - return FALSE; - - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - return TRUE; -} - -/****************************************************************** - * NMPObject/netlink functions - ******************************************************************/ - -#define _check_addr_or_return_val(tb, attr, addr_len, ret_val) \ - ({ \ - const struct nlattr *__t = (tb)[(attr)]; \ - \ - if (__t) { \ - if (nla_len(__t) != (addr_len)) { \ - return ret_val; \ - } \ - } \ - !!__t; \ - }) - -#define _check_addr_or_return_null(tb, attr, addr_len) \ - _check_addr_or_return_val(tb, attr, addr_len, NULL) - -/*****************************************************************************/ - -/* Copied and heavily modified from libnl3's inet6_parse_protinfo(). */ -static gboolean -_parse_af_inet6(NMPlatform * platform, - struct nlattr * attr, - NMUtilsIPv6IfaceId *out_token, - gboolean * out_token_valid, - guint8 * out_addr_gen_mode_inv, - gboolean * out_addr_gen_mode_valid) -{ - static const struct nla_policy policy[] = { - [IFLA_INET6_FLAGS] = {.type = NLA_U32}, - [IFLA_INET6_CACHEINFO] = {.minlen = nm_offsetofend(struct ifla_cacheinfo, retrans_time)}, - [IFLA_INET6_CONF] = {.minlen = 4}, - [IFLA_INET6_STATS] = {.minlen = 8}, - [IFLA_INET6_ICMP6STATS] = {.minlen = 8}, - [IFLA_INET6_TOKEN] = {.minlen = sizeof(struct in6_addr)}, - [IFLA_INET6_ADDR_GEN_MODE] = {.type = NLA_U8}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - struct in6_addr i6_token; - gboolean token_valid = FALSE; - gboolean addr_gen_mode_valid = FALSE; - guint8 i6_addr_gen_mode_inv = 0; - - if (nla_parse_nested_arr(tb, attr, policy) < 0) - return FALSE; - - if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4) - return FALSE; - if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8) - return FALSE; - if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8) - return FALSE; - - if (_check_addr_or_return_val(tb, IFLA_INET6_TOKEN, sizeof(struct in6_addr), FALSE)) { - nla_memcpy(&i6_token, tb[IFLA_INET6_TOKEN], sizeof(struct in6_addr)); - token_valid = TRUE; - } - - /* Hack to detect support addrgenmode of the kernel. We only parse - * netlink messages that we receive from kernel, hence this check - * is valid. */ - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { - /* IFLA_INET6_ADDR_GEN_MODE was added in kernel 3.17, dated 5 October, 2014. */ - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL, - tb[IFLA_INET6_ADDR_GEN_MODE] ? 1 : -1); - } - - if (tb[IFLA_INET6_ADDR_GEN_MODE]) { - i6_addr_gen_mode_inv = _nm_platform_uint8_inv(nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE])); - if (i6_addr_gen_mode_inv == 0) { - /* an inverse addrgenmode of zero is unexpected. We need to reserve zero - * to signal "unset". */ - return FALSE; - } - addr_gen_mode_valid = TRUE; - } - - if (token_valid) { - *out_token_valid = token_valid; - nm_utils_ipv6_interface_identifier_get_from_addr(out_token, &i6_token); - } - if (addr_gen_mode_valid) { - *out_addr_gen_mode_valid = addr_gen_mode_valid; - *out_addr_gen_mode_inv = i6_addr_gen_mode_inv; - } - return TRUE; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_bridge(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_BR_FORWARD_DELAY] = {.type = NLA_U32}, - [IFLA_BR_HELLO_TIME] = {.type = NLA_U32}, - [IFLA_BR_MAX_AGE] = {.type = NLA_U32}, - [IFLA_BR_AGEING_TIME] = {.type = NLA_U32}, - [IFLA_BR_STP_STATE] = {.type = NLA_U32}, - [IFLA_BR_PRIORITY] = {.type = NLA_U16}, - [IFLA_BR_VLAN_PROTOCOL] = {.type = NLA_U16}, - [IFLA_BR_VLAN_STATS_ENABLED] = {.type = NLA_U8}, - [IFLA_BR_GROUP_FWD_MASK] = {.type = NLA_U16}, - [IFLA_BR_GROUP_ADDR] = {.minlen = sizeof(NMEtherAddr)}, - [IFLA_BR_MCAST_SNOOPING] = {.type = NLA_U8}, - [IFLA_BR_MCAST_ROUTER] = {.type = NLA_U8}, - [IFLA_BR_MCAST_QUERY_USE_IFADDR] = {.type = NLA_U8}, - [IFLA_BR_MCAST_QUERIER] = {.type = NLA_U8}, - [IFLA_BR_MCAST_HASH_MAX] = {.type = NLA_U32}, - [IFLA_BR_MCAST_LAST_MEMBER_CNT] = {.type = NLA_U32}, - [IFLA_BR_MCAST_STARTUP_QUERY_CNT] = {.type = NLA_U32}, - [IFLA_BR_MCAST_LAST_MEMBER_INTVL] = {.type = NLA_U64}, - [IFLA_BR_MCAST_MEMBERSHIP_INTVL] = {.type = NLA_U64}, - [IFLA_BR_MCAST_QUERIER_INTVL] = {.type = NLA_U64}, - [IFLA_BR_MCAST_QUERY_INTVL] = {.type = NLA_U64}, - [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = {.type = NLA_U64}, - [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = {.type = NLA_U64}, - }; - NMPlatformLnkBridge *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - - if (!info_data || !nm_streq0(kind, "bridge")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_BRIDGE, NULL); - - props = &obj->lnk_bridge; - *props = nm_platform_lnk_bridge_default; - - if (!_nm_platform_kernel_support_detected( - NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED)) { - /* IFLA_BR_VLAN_STATS_ENABLED was added in kernel 4.10 on April 30, 2016. - * See commit 6dada9b10a0818ba72c249526a742c8c41274a73. */ - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED, - tb[IFLA_BR_VLAN_STATS_ENABLED] ? 1 : -1); - } - - if (tb[IFLA_BR_FORWARD_DELAY]) - props->forward_delay = nla_get_u32(tb[IFLA_BR_FORWARD_DELAY]); - if (tb[IFLA_BR_HELLO_TIME]) - props->hello_time = nla_get_u32(tb[IFLA_BR_HELLO_TIME]); - if (tb[IFLA_BR_MAX_AGE]) - props->max_age = nla_get_u32(tb[IFLA_BR_MAX_AGE]); - if (tb[IFLA_BR_AGEING_TIME]) - props->ageing_time = nla_get_u32(tb[IFLA_BR_AGEING_TIME]); - if (tb[IFLA_BR_STP_STATE]) - props->stp_state = !!nla_get_u32(tb[IFLA_BR_STP_STATE]); - if (tb[IFLA_BR_PRIORITY]) - props->priority = nla_get_u16(tb[IFLA_BR_PRIORITY]); - if (tb[IFLA_BR_VLAN_PROTOCOL]) - props->vlan_protocol = ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL])); - if (tb[IFLA_BR_VLAN_STATS_ENABLED]) - props->vlan_stats_enabled = nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]); - if (tb[IFLA_BR_GROUP_FWD_MASK]) - props->group_fwd_mask = nla_get_u16(tb[IFLA_BR_GROUP_FWD_MASK]); - if (tb[IFLA_BR_GROUP_ADDR]) - props->group_addr = *nla_data_as(NMEtherAddr, tb[IFLA_BR_GROUP_ADDR]); - if (tb[IFLA_BR_MCAST_SNOOPING]) - props->mcast_snooping = !!nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]); - if (tb[IFLA_BR_MCAST_ROUTER]) - props->mcast_router = nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]); - if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]) - props->mcast_query_use_ifaddr = !!nla_get_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]); - if (tb[IFLA_BR_MCAST_QUERIER]) - props->mcast_querier = nla_get_u8(tb[IFLA_BR_MCAST_QUERIER]); - if (tb[IFLA_BR_MCAST_HASH_MAX]) - props->mcast_hash_max = nla_get_u32(tb[IFLA_BR_MCAST_HASH_MAX]); - if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]) - props->mcast_last_member_count = nla_get_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]); - if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]) - props->mcast_startup_query_count = nla_get_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]); - if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]) - props->mcast_last_member_interval = nla_get_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]); - if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]) - props->mcast_membership_interval = nla_get_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]); - if (tb[IFLA_BR_MCAST_QUERIER_INTVL]) - props->mcast_querier_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]); - if (tb[IFLA_BR_MCAST_QUERY_INTVL]) - props->mcast_query_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]); - if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) - props->mcast_query_response_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]); - if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) - props->mcast_startup_query_interval = nla_get_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]); - - return obj; -} - -/***********************************************************************************/ - -static NMPObject * -_parse_lnk_gre(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_GRE_LINK] = {.type = NLA_U32}, - [IFLA_GRE_IFLAGS] = {.type = NLA_U16}, - [IFLA_GRE_OFLAGS] = {.type = NLA_U16}, - [IFLA_GRE_IKEY] = {.type = NLA_U32}, - [IFLA_GRE_OKEY] = {.type = NLA_U32}, - [IFLA_GRE_LOCAL] = {.type = NLA_U32}, - [IFLA_GRE_REMOTE] = {.type = NLA_U32}, - [IFLA_GRE_TTL] = {.type = NLA_U8}, - [IFLA_GRE_TOS] = {.type = NLA_U8}, - [IFLA_GRE_PMTUDISC] = {.type = NLA_U8}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkGre *props; - gboolean is_tap; - - if (!info_data || !kind) - return NULL; - - if (nm_streq(kind, "gretap")) - is_tap = TRUE; - else if (nm_streq(kind, "gre")) - is_tap = FALSE; - else - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(is_tap ? NMP_OBJECT_TYPE_LNK_GRETAP : NMP_OBJECT_TYPE_LNK_GRE, NULL); - props = &obj->lnk_gre; - - props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32(tb[IFLA_GRE_LINK]) : 0; - props->input_flags = tb[IFLA_GRE_IFLAGS] ? ntohs(nla_get_u16(tb[IFLA_GRE_IFLAGS])) : 0; - props->output_flags = tb[IFLA_GRE_OFLAGS] ? ntohs(nla_get_u16(tb[IFLA_GRE_OFLAGS])) : 0; - props->input_key = tb[IFLA_GRE_IKEY] ? ntohl(nla_get_u32(tb[IFLA_GRE_IKEY])) : 0; - props->output_key = tb[IFLA_GRE_OKEY] ? ntohl(nla_get_u32(tb[IFLA_GRE_OKEY])) : 0; - props->local = tb[IFLA_GRE_LOCAL] ? nla_get_u32(tb[IFLA_GRE_LOCAL]) : 0; - props->remote = tb[IFLA_GRE_REMOTE] ? nla_get_u32(tb[IFLA_GRE_REMOTE]) : 0; - props->tos = tb[IFLA_GRE_TOS] ? nla_get_u8(tb[IFLA_GRE_TOS]) : 0; - props->ttl = tb[IFLA_GRE_TTL] ? nla_get_u8(tb[IFLA_GRE_TTL]) : 0; - props->path_mtu_discovery = !tb[IFLA_GRE_PMTUDISC] || !!nla_get_u8(tb[IFLA_GRE_PMTUDISC]); - props->is_tap = is_tap; - - return obj; -} - -/*****************************************************************************/ - -/* IFLA_IPOIB_* were introduced in the 3.7 kernel, but the kernel headers - * we're building against might not have those properties even though the - * running kernel might. - */ -#define IFLA_IPOIB_UNSPEC 0 -#define IFLA_IPOIB_PKEY 1 -#define IFLA_IPOIB_MODE 2 -#define IFLA_IPOIB_UMCAST 3 -#undef IFLA_IPOIB_MAX -#define IFLA_IPOIB_MAX IFLA_IPOIB_UMCAST - -#define IPOIB_MODE_DATAGRAM 0 /* using unreliable datagram QPs */ -#define IPOIB_MODE_CONNECTED 1 /* using connected QPs */ - -static NMPObject * -_parse_lnk_infiniband(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_IPOIB_PKEY] = {.type = NLA_U16}, - [IFLA_IPOIB_MODE] = {.type = NLA_U16}, - [IFLA_IPOIB_UMCAST] = {.type = NLA_U16}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPlatformLnkInfiniband *info; - NMPObject * obj; - const char * mode; - - if (!info_data || !nm_streq0(kind, "ipoib")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - if (!tb[IFLA_IPOIB_PKEY] || !tb[IFLA_IPOIB_MODE]) - return NULL; - - switch (nla_get_u16(tb[IFLA_IPOIB_MODE])) { - case IPOIB_MODE_DATAGRAM: - mode = "datagram"; - break; - case IPOIB_MODE_CONNECTED: - mode = "connected"; - break; - default: - return NULL; - } - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL); - info = &obj->lnk_infiniband; - - info->p_key = nla_get_u16(tb[IFLA_IPOIB_PKEY]); - info->mode = mode; - - return obj; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_ip6tnl(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_IPTUN_LINK] = {.type = NLA_U32}, - [IFLA_IPTUN_LOCAL] = {.minlen = sizeof(struct in6_addr)}, - [IFLA_IPTUN_REMOTE] = {.minlen = sizeof(struct in6_addr)}, - [IFLA_IPTUN_TTL] = {.type = NLA_U8}, - [IFLA_IPTUN_ENCAP_LIMIT] = {.type = NLA_U8}, - [IFLA_IPTUN_FLOWINFO] = {.type = NLA_U32}, - [IFLA_IPTUN_PROTO] = {.type = NLA_U8}, - [IFLA_IPTUN_FLAGS] = {.type = NLA_U32}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkIp6Tnl *props; - guint32 flowinfo; - - if (!info_data || !nm_streq0(kind, "ip6tnl")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_IP6TNL, NULL); - props = &obj->lnk_ip6tnl; - - if (tb[IFLA_IPTUN_LINK]) - props->parent_ifindex = nla_get_u32(tb[IFLA_IPTUN_LINK]); - if (tb[IFLA_IPTUN_LOCAL]) - props->local = *nla_data_as(struct in6_addr, tb[IFLA_IPTUN_LOCAL]); - if (tb[IFLA_IPTUN_REMOTE]) - props->remote = *nla_data_as(struct in6_addr, tb[IFLA_IPTUN_REMOTE]); - if (tb[IFLA_IPTUN_TTL]) - props->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]); - if (tb[IFLA_IPTUN_ENCAP_LIMIT]) - props->encap_limit = nla_get_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]); - if (tb[IFLA_IPTUN_FLOWINFO]) { - flowinfo = ntohl(nla_get_u32(tb[IFLA_IPTUN_FLOWINFO])); - props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; - props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; - } - if (tb[IFLA_IPTUN_PROTO]) - props->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]); - if (tb[IFLA_IPTUN_FLAGS]) - props->flags = nla_get_u32(tb[IFLA_IPTUN_FLAGS]); - - return obj; -} - -static NMPObject * -_parse_lnk_ip6gre(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_GRE_LINK] = {.type = NLA_U32}, - [IFLA_GRE_IFLAGS] = {.type = NLA_U16}, - [IFLA_GRE_OFLAGS] = {.type = NLA_U16}, - [IFLA_GRE_IKEY] = {.type = NLA_U32}, - [IFLA_GRE_OKEY] = {.type = NLA_U32}, - [IFLA_GRE_LOCAL] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, - [IFLA_GRE_REMOTE] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, - [IFLA_GRE_TTL] = {.type = NLA_U8}, - [IFLA_GRE_ENCAP_LIMIT] = {.type = NLA_U8}, - [IFLA_GRE_FLOWINFO] = {.type = NLA_U32}, - [IFLA_GRE_FLAGS] = {.type = NLA_U32}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkIp6Tnl *props; - guint32 flowinfo; - gboolean is_tap; - - if (!info_data || !kind) - return NULL; - - if (nm_streq(kind, "ip6gre")) - is_tap = FALSE; - else if (nm_streq(kind, "ip6gretap")) - is_tap = TRUE; - else - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(is_tap ? NMP_OBJECT_TYPE_LNK_IP6GRETAP : NMP_OBJECT_TYPE_LNK_IP6GRE, NULL); - props = &obj->lnk_ip6tnl; - props->is_gre = TRUE; - props->is_tap = is_tap; - - if (tb[IFLA_GRE_LINK]) - props->parent_ifindex = nla_get_u32(tb[IFLA_GRE_LINK]); - if (tb[IFLA_GRE_IFLAGS]) - props->input_flags = ntohs(nla_get_u16(tb[IFLA_GRE_IFLAGS])); - if (tb[IFLA_GRE_OFLAGS]) - props->output_flags = ntohs(nla_get_u16(tb[IFLA_GRE_OFLAGS])); - if (tb[IFLA_GRE_IKEY]) - props->input_key = ntohl(nla_get_u32(tb[IFLA_GRE_IKEY])); - if (tb[IFLA_GRE_OKEY]) - props->output_key = ntohl(nla_get_u32(tb[IFLA_GRE_OKEY])); - if (tb[IFLA_GRE_LOCAL]) - props->local = *nla_data_as(struct in6_addr, tb[IFLA_GRE_LOCAL]); - if (tb[IFLA_GRE_REMOTE]) - props->remote = *nla_data_as(struct in6_addr, tb[IFLA_GRE_REMOTE]); - if (tb[IFLA_GRE_TTL]) - props->ttl = nla_get_u8(tb[IFLA_GRE_TTL]); - if (tb[IFLA_GRE_ENCAP_LIMIT]) - props->encap_limit = nla_get_u8(tb[IFLA_GRE_ENCAP_LIMIT]); - if (tb[IFLA_GRE_FLOWINFO]) { - flowinfo = ntohl(nla_get_u32(tb[IFLA_GRE_FLOWINFO])); - props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; - props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; - } - if (tb[IFLA_GRE_FLAGS]) - props->flags = nla_get_u32(tb[IFLA_GRE_FLAGS]); - - return obj; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_ipip(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_IPTUN_LINK] = {.type = NLA_U32}, - [IFLA_IPTUN_LOCAL] = {.type = NLA_U32}, - [IFLA_IPTUN_REMOTE] = {.type = NLA_U32}, - [IFLA_IPTUN_TTL] = {.type = NLA_U8}, - [IFLA_IPTUN_TOS] = {.type = NLA_U8}, - [IFLA_IPTUN_PMTUDISC] = {.type = NLA_U8}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkIpIp *props; - - if (!info_data || !nm_streq0(kind, "ipip")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_IPIP, NULL); - props = &obj->lnk_ipip; - - props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32(tb[IFLA_IPTUN_LINK]) : 0; - props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32(tb[IFLA_IPTUN_LOCAL]) : 0; - props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32(tb[IFLA_IPTUN_REMOTE]) : 0; - props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8(tb[IFLA_IPTUN_TOS]) : 0; - props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8(tb[IFLA_IPTUN_TTL]) : 0; - props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]); - - return obj; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_macvlan(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_MACVLAN_MODE] = {.type = NLA_U32}, - [IFLA_MACVLAN_FLAGS] = {.type = NLA_U16}, - }; - NMPlatformLnkMacvlan *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - gboolean tap; - - if (!info_data || !kind) - return NULL; - - if (nm_streq(kind, "macvlan")) - tap = FALSE; - else if (nm_streq(kind, "macvtap")) - tap = TRUE; - else - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - if (!tb[IFLA_MACVLAN_MODE]) - return NULL; - - obj = nmp_object_new(tap ? NMP_OBJECT_TYPE_LNK_MACVTAP : NMP_OBJECT_TYPE_LNK_MACVLAN, NULL); - props = &obj->lnk_macvlan; - props->mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]); - props->tap = tap; - - if (tb[IFLA_MACVLAN_FLAGS]) - props->no_promisc = - NM_FLAGS_HAS(nla_get_u16(tb[IFLA_MACVLAN_FLAGS]), MACVLAN_FLAG_NOPROMISC); - - return obj; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_macsec(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_MACSEC_SCI] = {.type = NLA_U64}, - [IFLA_MACSEC_ICV_LEN] = {.type = NLA_U8}, - [IFLA_MACSEC_CIPHER_SUITE] = {.type = NLA_U64}, - [IFLA_MACSEC_WINDOW] = {.type = NLA_U32}, - [IFLA_MACSEC_ENCODING_SA] = {.type = NLA_U8}, - [IFLA_MACSEC_ENCRYPT] = {.type = NLA_U8}, - [IFLA_MACSEC_PROTECT] = {.type = NLA_U8}, - [IFLA_MACSEC_INC_SCI] = {.type = NLA_U8}, - [IFLA_MACSEC_ES] = {.type = NLA_U8}, - [IFLA_MACSEC_SCB] = {.type = NLA_U8}, - [IFLA_MACSEC_REPLAY_PROTECT] = {.type = NLA_U8}, - [IFLA_MACSEC_VALIDATION] = {.type = NLA_U8}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkMacsec *props; - - if (!info_data || !nm_streq0(kind, "macsec")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_MACSEC, NULL); - props = &obj->lnk_macsec; - - if (tb[IFLA_MACSEC_SCI]) { - props->sci = nla_get_be64(tb[IFLA_MACSEC_SCI]); - } - if (tb[IFLA_MACSEC_ICV_LEN]) { - props->icv_length = nla_get_u8(tb[IFLA_MACSEC_ICV_LEN]); - } - if (tb[IFLA_MACSEC_CIPHER_SUITE]) { - props->cipher_suite = nla_get_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); - } - if (tb[IFLA_MACSEC_WINDOW]) { - props->window = nla_get_u32(tb[IFLA_MACSEC_WINDOW]); - } - if (tb[IFLA_MACSEC_ENCODING_SA]) { - props->encoding_sa = !!nla_get_u8(tb[IFLA_MACSEC_ENCODING_SA]); - } - if (tb[IFLA_MACSEC_ENCRYPT]) { - props->encrypt = !!nla_get_u8(tb[IFLA_MACSEC_ENCRYPT]); - } - if (tb[IFLA_MACSEC_PROTECT]) { - props->protect = !!nla_get_u8(tb[IFLA_MACSEC_PROTECT]); - } - if (tb[IFLA_MACSEC_INC_SCI]) { - props->include_sci = !!nla_get_u8(tb[IFLA_MACSEC_INC_SCI]); - } - if (tb[IFLA_MACSEC_ES]) { - props->es = !!nla_get_u8(tb[IFLA_MACSEC_ES]); - } - if (tb[IFLA_MACSEC_SCB]) { - props->scb = !!nla_get_u8(tb[IFLA_MACSEC_SCB]); - } - if (tb[IFLA_MACSEC_REPLAY_PROTECT]) { - props->replay_protect = !!nla_get_u8(tb[IFLA_MACSEC_REPLAY_PROTECT]); - } - if (tb[IFLA_MACSEC_VALIDATION]) { - props->validation = nla_get_u8(tb[IFLA_MACSEC_VALIDATION]); - } - - return obj; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_sit(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_IPTUN_LINK] = {.type = NLA_U32}, - [IFLA_IPTUN_LOCAL] = {.type = NLA_U32}, - [IFLA_IPTUN_REMOTE] = {.type = NLA_U32}, - [IFLA_IPTUN_TTL] = {.type = NLA_U8}, - [IFLA_IPTUN_TOS] = {.type = NLA_U8}, - [IFLA_IPTUN_PMTUDISC] = {.type = NLA_U8}, - [IFLA_IPTUN_FLAGS] = {.type = NLA_U16}, - [IFLA_IPTUN_PROTO] = {.type = NLA_U8}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkSit *props; - - if (!info_data || !nm_streq0(kind, "sit")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_SIT, NULL); - props = &obj->lnk_sit; - - props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32(tb[IFLA_IPTUN_LINK]) : 0; - props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32(tb[IFLA_IPTUN_LOCAL]) : 0; - props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32(tb[IFLA_IPTUN_REMOTE]) : 0; - props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8(tb[IFLA_IPTUN_TOS]) : 0; - props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8(tb[IFLA_IPTUN_TTL]) : 0; - props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]); - props->flags = tb[IFLA_IPTUN_FLAGS] ? nla_get_u16(tb[IFLA_IPTUN_FLAGS]) : 0; - props->proto = tb[IFLA_IPTUN_PROTO] ? nla_get_u8(tb[IFLA_IPTUN_PROTO]) : 0; - - return obj; -} - -/*****************************************************************************/ - -static NMPObject * -_parse_lnk_tun(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_TUN_OWNER] = {.type = NLA_U32}, - [IFLA_TUN_GROUP] = {.type = NLA_U32}, - [IFLA_TUN_TYPE] = {.type = NLA_U8}, - [IFLA_TUN_PI] = {.type = NLA_U8}, - [IFLA_TUN_VNET_HDR] = {.type = NLA_U8}, - [IFLA_TUN_PERSIST] = {.type = NLA_U8}, - [IFLA_TUN_MULTI_QUEUE] = {.type = NLA_U8}, - [IFLA_TUN_NUM_QUEUES] = {.type = NLA_U32}, - [IFLA_TUN_NUM_DISABLED_QUEUES] = {.type = NLA_U32}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - NMPlatformLnkTun *props; - - if (!info_data || !nm_streq0(kind, "tun")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - if (!tb[IFLA_TUN_TYPE]) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_TUN, NULL); - props = &obj->lnk_tun; - - props->type = nla_get_u8(tb[IFLA_TUN_TYPE]); - - props->pi = !!nla_get_u8_cond(tb, IFLA_TUN_PI, FALSE); - props->vnet_hdr = !!nla_get_u8_cond(tb, IFLA_TUN_VNET_HDR, FALSE); - props->multi_queue = !!nla_get_u8_cond(tb, IFLA_TUN_MULTI_QUEUE, FALSE); - props->persist = !!nla_get_u8_cond(tb, IFLA_TUN_PERSIST, FALSE); - - if (tb[IFLA_TUN_OWNER]) { - props->owner_valid = TRUE; - props->owner = nla_get_u32(tb[IFLA_TUN_OWNER]); - } - if (tb[IFLA_TUN_GROUP]) { - props->group_valid = TRUE; - props->group = nla_get_u32(tb[IFLA_TUN_GROUP]); - } - return obj; -} - -/*****************************************************************************/ - -static gboolean -_vlan_qos_mapping_from_nla(struct nlattr * nlattr, - const NMVlanQosMapping **out_map, - guint * out_n_map) -{ - struct nlattr * nla; - int remaining; - gs_unref_ptrarray GPtrArray *array = NULL; - - G_STATIC_ASSERT(sizeof(NMVlanQosMapping) == sizeof(struct ifla_vlan_qos_mapping)); - G_STATIC_ASSERT(sizeof(((NMVlanQosMapping *) 0)->to) - == sizeof(((struct ifla_vlan_qos_mapping *) 0)->to)); - G_STATIC_ASSERT(sizeof(((NMVlanQosMapping *) 0)->from) - == sizeof(((struct ifla_vlan_qos_mapping *) 0)->from)); - G_STATIC_ASSERT(sizeof(NMVlanQosMapping) - == sizeof(((NMVlanQosMapping *) 0)->from) - + sizeof(((NMVlanQosMapping *) 0)->to)); - - nm_assert(out_map && !*out_map); - nm_assert(out_n_map && !*out_n_map); - - if (!nlattr) - return TRUE; - - array = g_ptr_array_new(); - nla_for_each_nested (nla, nlattr, remaining) { - if (nla_len(nla) < sizeof(NMVlanQosMapping)) - return FALSE; - g_ptr_array_add(array, nla_data(nla)); - } - - if (array->len > 0) { - NMVlanQosMapping *list; - guint i, j; - - /* The sorting is necessary, because for egress mapping, kernel - * doesn't sent the items strictly sorted by the from field. */ - g_ptr_array_sort_with_data(array, _vlan_qos_mapping_cmp_from_ptr, NULL); - - list = g_new(NMVlanQosMapping, array->len); - - for (i = 0, j = 0; i < array->len; i++) { - NMVlanQosMapping *map; - - map = array->pdata[i]; - - /* kernel doesn't really send us duplicates. Just be extra cautious - * because we want strong guarantees about the sort order and uniqueness - * of our mapping list (for simpler equality comparison). */ - if (j > 0 && list[j - 1].from == map->from) - list[j - 1] = *map; - else - list[j++] = *map; - } - - *out_n_map = j; - *out_map = list; - } - - return TRUE; -} - -/* Copied and heavily modified from libnl3's vlan_parse() */ -static NMPObject * -_parse_lnk_vlan(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_VLAN_ID] = {.type = NLA_U16}, - [IFLA_VLAN_FLAGS] = {.minlen = nm_offsetofend(struct ifla_vlan_flags, flags)}, - [IFLA_VLAN_INGRESS_QOS] = {.type = NLA_NESTED}, - [IFLA_VLAN_EGRESS_QOS] = {.type = NLA_NESTED}, - [IFLA_VLAN_PROTOCOL] = {.type = NLA_U16}, - }; - struct nlattr *tb[G_N_ELEMENTS(policy)]; - nm_auto_nmpobj NMPObject *obj = NULL; - NMPObject * obj_result; - - if (!info_data || !nm_streq0(kind, "vlan")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - if (!tb[IFLA_VLAN_ID]) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_VLAN, NULL); - obj->lnk_vlan.id = nla_get_u16(tb[IFLA_VLAN_ID]); - - if (tb[IFLA_VLAN_FLAGS]) { - struct ifla_vlan_flags flags; - - nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags)); - - obj->lnk_vlan.flags = flags.flags; - } - - if (!_vlan_qos_mapping_from_nla(tb[IFLA_VLAN_INGRESS_QOS], - &obj->_lnk_vlan.ingress_qos_map, - &obj->_lnk_vlan.n_ingress_qos_map)) - return NULL; - - if (!_vlan_qos_mapping_from_nla(tb[IFLA_VLAN_EGRESS_QOS], - &obj->_lnk_vlan.egress_qos_map, - &obj->_lnk_vlan.n_egress_qos_map)) - return NULL; - - obj_result = obj; - obj = NULL; - return obj_result; -} - -/*****************************************************************************/ - -/* The installed kernel headers might not have VXLAN stuff at all, or - * they might have the original properties, but not PORT, GROUP6, or LOCAL6. - * So until we depend on kernel >= 3.11, we just ignore the actual enum - * in if_link.h and define the values ourselves. - */ -#define IFLA_VXLAN_UNSPEC 0 -#define IFLA_VXLAN_ID 1 -#define IFLA_VXLAN_GROUP 2 -#define IFLA_VXLAN_LINK 3 -#define IFLA_VXLAN_LOCAL 4 -#define IFLA_VXLAN_TTL 5 -#define IFLA_VXLAN_TOS 6 -#define IFLA_VXLAN_LEARNING 7 -#define IFLA_VXLAN_AGEING 8 -#define IFLA_VXLAN_LIMIT 9 -#define IFLA_VXLAN_PORT_RANGE 10 -#define IFLA_VXLAN_PROXY 11 -#define IFLA_VXLAN_RSC 12 -#define IFLA_VXLAN_L2MISS 13 -#define IFLA_VXLAN_L3MISS 14 -#define IFLA_VXLAN_PORT 15 -#define IFLA_VXLAN_GROUP6 16 -#define IFLA_VXLAN_LOCAL6 17 -#undef IFLA_VXLAN_MAX -#define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6 - -#define IFLA_VRF_TABLE 1 - -/* older kernel header might not contain 'struct ifla_vxlan_port_range'. - * Redefine it. */ -struct nm_ifla_vxlan_port_range { - guint16 low; - guint16 high; -}; - -static NMPObject * -_parse_lnk_vxlan(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_VXLAN_ID] = {.type = NLA_U32}, - [IFLA_VXLAN_GROUP] = {.type = NLA_U32}, - [IFLA_VXLAN_GROUP6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, - [IFLA_VXLAN_LINK] = {.type = NLA_U32}, - [IFLA_VXLAN_LOCAL] = {.type = NLA_U32}, - [IFLA_VXLAN_LOCAL6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, - [IFLA_VXLAN_TOS] = {.type = NLA_U8}, - [IFLA_VXLAN_TTL] = {.type = NLA_U8}, - [IFLA_VXLAN_LEARNING] = {.type = NLA_U8}, - [IFLA_VXLAN_AGEING] = {.type = NLA_U32}, - [IFLA_VXLAN_LIMIT] = {.type = NLA_U32}, - [IFLA_VXLAN_PORT_RANGE] = {.type = NLA_UNSPEC, - .minlen = sizeof(struct nm_ifla_vxlan_port_range)}, - [IFLA_VXLAN_PROXY] = {.type = NLA_U8}, - [IFLA_VXLAN_RSC] = {.type = NLA_U8}, - [IFLA_VXLAN_L2MISS] = {.type = NLA_U8}, - [IFLA_VXLAN_L3MISS] = {.type = NLA_U8}, - [IFLA_VXLAN_PORT] = {.type = NLA_U16}, - }; - NMPlatformLnkVxlan *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - - if (!info_data || !nm_streq0(kind, "vxlan")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_VXLAN, NULL); - - props = &obj->lnk_vxlan; - - if (tb[IFLA_VXLAN_LINK]) - props->parent_ifindex = nla_get_u32(tb[IFLA_VXLAN_LINK]); - if (tb[IFLA_VXLAN_ID]) - props->id = nla_get_u32(tb[IFLA_VXLAN_ID]); - if (tb[IFLA_VXLAN_GROUP]) - props->group = nla_get_u32(tb[IFLA_VXLAN_GROUP]); - if (tb[IFLA_VXLAN_LOCAL]) - props->local = nla_get_u32(tb[IFLA_VXLAN_LOCAL]); - if (tb[IFLA_VXLAN_LOCAL6]) - props->local6 = *nla_data_as(struct in6_addr, tb[IFLA_VXLAN_LOCAL6]); - if (tb[IFLA_VXLAN_GROUP6]) - props->group6 = *nla_data_as(struct in6_addr, tb[IFLA_VXLAN_GROUP6]); - - if (tb[IFLA_VXLAN_AGEING]) - props->ageing = nla_get_u32(tb[IFLA_VXLAN_AGEING]); - if (tb[IFLA_VXLAN_LIMIT]) - props->limit = nla_get_u32(tb[IFLA_VXLAN_LIMIT]); - if (tb[IFLA_VXLAN_TOS]) - props->tos = nla_get_u8(tb[IFLA_VXLAN_TOS]); - if (tb[IFLA_VXLAN_TTL]) - props->ttl = nla_get_u8(tb[IFLA_VXLAN_TTL]); - - if (tb[IFLA_VXLAN_PORT]) - props->dst_port = ntohs(nla_get_u16(tb[IFLA_VXLAN_PORT])); - - if (tb[IFLA_VXLAN_PORT_RANGE]) { - struct nm_ifla_vxlan_port_range *range; - - range = nla_data_as(struct nm_ifla_vxlan_port_range, tb[IFLA_VXLAN_PORT_RANGE]); - props->src_port_min = ntohs(range->low); - props->src_port_max = ntohs(range->high); - } - - if (tb[IFLA_VXLAN_LEARNING]) - props->learning = !!nla_get_u8(tb[IFLA_VXLAN_LEARNING]); - if (tb[IFLA_VXLAN_PROXY]) - props->proxy = !!nla_get_u8(tb[IFLA_VXLAN_PROXY]); - if (tb[IFLA_VXLAN_RSC]) - props->rsc = !!nla_get_u8(tb[IFLA_VXLAN_RSC]); - if (tb[IFLA_VXLAN_L2MISS]) - props->l2miss = !!nla_get_u8(tb[IFLA_VXLAN_L2MISS]); - if (tb[IFLA_VXLAN_L3MISS]) - props->l3miss = !!nla_get_u8(tb[IFLA_VXLAN_L3MISS]); - - return obj; -} - -static NMPObject * -_parse_lnk_vrf(const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_VRF_TABLE] = {.type = NLA_U32}, - }; - NMPlatformLnkVrf *props; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj; - - if (!info_data || !nm_streq0(kind, "vrf")) - return NULL; - - if (nla_parse_nested_arr(tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_VRF, NULL); - - props = &obj->lnk_vrf; - - if (tb[IFLA_VRF_TABLE]) - props->table = nla_get_u32(tb[IFLA_VRF_TABLE]); - - return obj; -} - -/*****************************************************************************/ - -static gboolean -_wireguard_update_from_allowed_ips_nla(NMPWireGuardAllowedIP *allowed_ip, struct nlattr *nlattr) -{ - static const struct nla_policy policy[] = { - [WGALLOWEDIP_A_FAMILY] = {.type = NLA_U16}, - [WGALLOWEDIP_A_IPADDR] = {.minlen = sizeof(struct in_addr)}, - [WGALLOWEDIP_A_CIDR_MASK] = {.type = NLA_U8}, - }; - struct nlattr *tb[G_N_ELEMENTS(policy)]; - int family; - int addr_len; - - if (nla_parse_nested_arr(tb, nlattr, policy) < 0) - return FALSE; - - if (!tb[WGALLOWEDIP_A_FAMILY]) - return FALSE; - - family = nla_get_u16(tb[WGALLOWEDIP_A_FAMILY]); - if (family == AF_INET) - addr_len = sizeof(in_addr_t); - else if (family == AF_INET6) - addr_len = sizeof(struct in6_addr); - else - return FALSE; - - _check_addr_or_return_val(tb, WGALLOWEDIP_A_IPADDR, addr_len, FALSE); - - *allowed_ip = (NMPWireGuardAllowedIP){ - .family = family, - }; - - nm_assert((int) allowed_ip->family == family); - - if (tb[WGALLOWEDIP_A_IPADDR]) - nla_memcpy(&allowed_ip->addr, tb[WGALLOWEDIP_A_IPADDR], addr_len); - if (tb[WGALLOWEDIP_A_CIDR_MASK]) - allowed_ip->mask = nla_get_u8(tb[WGALLOWEDIP_A_CIDR_MASK]); - - return TRUE; -} - -typedef struct { - CList lst; - NMPWireGuardPeer data; -} WireGuardPeerConstruct; - -static gboolean -_wireguard_update_from_peers_nla(CList *peers, GArray **p_allowed_ips, struct nlattr *peer_attr) -{ - static const struct nla_policy policy[] = { - [WGPEER_A_PUBLIC_KEY] = {.minlen = NMP_WIREGUARD_PUBLIC_KEY_LEN}, - [WGPEER_A_PRESHARED_KEY] = {}, - [WGPEER_A_FLAGS] = {.type = NLA_U32}, - [WGPEER_A_ENDPOINT] = {}, - [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = {.type = NLA_U16}, - [WGPEER_A_LAST_HANDSHAKE_TIME] = {}, - [WGPEER_A_RX_BYTES] = {.type = NLA_U64}, - [WGPEER_A_TX_BYTES] = {.type = NLA_U64}, - [WGPEER_A_ALLOWEDIPS] = {.type = NLA_NESTED}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - WireGuardPeerConstruct *peer_c; - - if (nla_parse_nested_arr(tb, peer_attr, policy) < 0) - return FALSE; - - if (!tb[WGPEER_A_PUBLIC_KEY]) - return FALSE; - - /* a peer with the same public key as last peer is just a continuation for extra AllowedIPs */ - peer_c = c_list_last_entry(peers, WireGuardPeerConstruct, lst); - if (peer_c - && !memcmp(nla_data(tb[WGPEER_A_PUBLIC_KEY]), - peer_c->data.public_key, - NMP_WIREGUARD_PUBLIC_KEY_LEN)) { - G_STATIC_ASSERT_EXPR(NMP_WIREGUARD_PUBLIC_KEY_LEN == sizeof(peer_c->data.public_key)); - /* this message is a continuation of the previous peer. - * Only parse WGPEER_A_ALLOWEDIPS below. */ - } else { - /* otherwise, start a new peer */ - peer_c = g_slice_new0(WireGuardPeerConstruct); - c_list_link_tail(peers, &peer_c->lst); - - nla_memcpy(&peer_c->data.public_key, - tb[WGPEER_A_PUBLIC_KEY], - sizeof(peer_c->data.public_key)); - - if (tb[WGPEER_A_PRESHARED_KEY]) { - nla_memcpy(&peer_c->data.preshared_key, - tb[WGPEER_A_PRESHARED_KEY], - sizeof(peer_c->data.preshared_key)); - /* FIXME(netlink-bzero-secret) */ - nm_explicit_bzero(nla_data(tb[WGPEER_A_PRESHARED_KEY]), - nla_len(tb[WGPEER_A_PRESHARED_KEY])); - } - - nm_sock_addr_union_cpy_untrusted( - &peer_c->data.endpoint, - tb[WGPEER_A_ENDPOINT] ? nla_data(tb[WGPEER_A_ENDPOINT]) : NULL, - tb[WGPEER_A_ENDPOINT] ? nla_len(tb[WGPEER_A_ENDPOINT]) : 0); - - if (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]) - peer_c->data.persistent_keepalive_interval = - nla_get_u16(tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]); - if (tb[WGPEER_A_LAST_HANDSHAKE_TIME]) { - if (nla_len(tb[WGPEER_A_LAST_HANDSHAKE_TIME]) - >= sizeof(peer_c->data.last_handshake_time)) - nla_memcpy(&peer_c->data.last_handshake_time, - tb[WGPEER_A_LAST_HANDSHAKE_TIME], - sizeof(peer_c->data.last_handshake_time)); - } - if (tb[WGPEER_A_RX_BYTES]) - peer_c->data.rx_bytes = nla_get_u64(tb[WGPEER_A_RX_BYTES]); - if (tb[WGPEER_A_TX_BYTES]) - peer_c->data.tx_bytes = nla_get_u64(tb[WGPEER_A_TX_BYTES]); - } - - if (tb[WGPEER_A_ALLOWEDIPS]) { - struct nlattr *attr; - int rem; - GArray * allowed_ips = *p_allowed_ips; - - nla_for_each_nested (attr, tb[WGPEER_A_ALLOWEDIPS], rem) { - if (!allowed_ips) { - allowed_ips = g_array_new(FALSE, FALSE, sizeof(NMPWireGuardAllowedIP)); - *p_allowed_ips = allowed_ips; - g_array_set_size(allowed_ips, 1); - } else - g_array_set_size(allowed_ips, allowed_ips->len + 1); - - if (!_wireguard_update_from_allowed_ips_nla( - &g_array_index(allowed_ips, NMPWireGuardAllowedIP, allowed_ips->len - 1), - attr)) { - /* we ignore the error of parsing one allowed-ip. */ - g_array_set_size(allowed_ips, allowed_ips->len - 1); - continue; - } - - if (!peer_c->data._construct_idx_end) - peer_c->data._construct_idx_start = allowed_ips->len - 1; - peer_c->data._construct_idx_end = allowed_ips->len; - } - } - - return TRUE; -} - -typedef struct { - const int ifindex; - NMPObject *obj; - CList peers; - GArray * allowed_ips; -} WireGuardParseData; - -static int -_wireguard_get_device_cb(struct nl_msg *msg, void *arg) -{ - static const struct nla_policy policy[] = { - [WGDEVICE_A_IFINDEX] = {.type = NLA_U32}, - [WGDEVICE_A_IFNAME] = {.type = NLA_NUL_STRING, .maxlen = IFNAMSIZ}, - [WGDEVICE_A_PRIVATE_KEY] = {}, - [WGDEVICE_A_PUBLIC_KEY] = {}, - [WGDEVICE_A_FLAGS] = {.type = NLA_U32}, - [WGDEVICE_A_LISTEN_PORT] = {.type = NLA_U16}, - [WGDEVICE_A_FWMARK] = {.type = NLA_U32}, - [WGDEVICE_A_PEERS] = {.type = NLA_NESTED}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - WireGuardParseData *parse_data = arg; - - if (genlmsg_parse_arr(nlmsg_hdr(msg), 0, tb, policy) < 0) - return NL_SKIP; - - if (tb[WGDEVICE_A_IFINDEX]) { - int ifindex; - - ifindex = (int) nla_get_u32(tb[WGDEVICE_A_IFINDEX]); - if (ifindex <= 0 || parse_data->ifindex != ifindex) - return NL_SKIP; - } else { - if (!parse_data->obj) - return NL_SKIP; - } - - if (parse_data->obj) { - /* we already have an object instance. This means the netlink message - * is a continuation, only providing more WGDEVICE_A_PEERS data below. */ - } else { - NMPObject * obj; - NMPlatformLnkWireGuard *props; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_WIREGUARD, NULL); - props = &obj->lnk_wireguard; - - if (tb[WGDEVICE_A_PRIVATE_KEY]) { - nla_memcpy(props->private_key, tb[WGDEVICE_A_PRIVATE_KEY], sizeof(props->private_key)); - /* FIXME(netlink-bzero-secret): extend netlink library to wipe memory. For now, - * just hack it here (yes, this does not cover all places where the - * private key was copied). */ - nm_explicit_bzero(nla_data(tb[WGDEVICE_A_PRIVATE_KEY]), - nla_len(tb[WGDEVICE_A_PRIVATE_KEY])); - } - if (tb[WGDEVICE_A_PUBLIC_KEY]) - nla_memcpy(props->public_key, tb[WGDEVICE_A_PUBLIC_KEY], sizeof(props->public_key)); - if (tb[WGDEVICE_A_LISTEN_PORT]) - props->listen_port = nla_get_u16(tb[WGDEVICE_A_LISTEN_PORT]); - if (tb[WGDEVICE_A_FWMARK]) - props->fwmark = nla_get_u32(tb[WGDEVICE_A_FWMARK]); - - parse_data->obj = obj; - } - - if (tb[WGDEVICE_A_PEERS]) { - struct nlattr *attr; - int rem; - - nla_for_each_nested (attr, tb[WGDEVICE_A_PEERS], rem) { - if (!_wireguard_update_from_peers_nla(&parse_data->peers, - &parse_data->allowed_ips, - attr)) { - /* we ignore the error of parsing one peer. - * _wireguard_update_from_peers_nla() leaves the @peers array in the - * desired state. */ - } - } - } - - return NL_OK; -} - -static const NMPObject * -_wireguard_read_info(NMPlatform * platform /* used only as logging context */, - struct nl_sock *genl, - int wireguard_family_id, - int ifindex) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - NMPObject * obj = NULL; - WireGuardPeerConstruct * peer_c; - WireGuardPeerConstruct * peer_c_safe; - gs_unref_array GArray *allowed_ips = NULL; - WireGuardParseData parse_data = { - .ifindex = ifindex, - }; - guint i; - - nm_assert(genl); - nm_assert(wireguard_family_id >= 0); - nm_assert(ifindex > 0); - - _LOGT("wireguard: fetching information for ifindex %d (genl-id %d)...", - ifindex, - wireguard_family_id); - - msg = nlmsg_alloc(); - - if (!genlmsg_put(msg, - NL_AUTO_PORT, - NL_AUTO_SEQ, - wireguard_family_id, - 0, - NLM_F_DUMP, - WG_CMD_GET_DEVICE, - 1)) - return NULL; - - NLA_PUT_U32(msg, WGDEVICE_A_IFINDEX, (guint32) ifindex); - - if (nl_send_auto(genl, msg) < 0) - return NULL; - - c_list_init(&parse_data.peers); - - /* we ignore errors, and return whatever we could successfully - * parse. */ - nl_recvmsgs(genl, - &((const struct nl_cb){ - .valid_cb = _wireguard_get_device_cb, - .valid_arg = (gpointer) &parse_data, - })); - - /* unpack: transfer ownership */ - obj = parse_data.obj; - allowed_ips = parse_data.allowed_ips; - - if (!obj) { - while ((peer_c = c_list_first_entry(&parse_data.peers, WireGuardPeerConstruct, lst))) { - c_list_unlink_stale(&peer_c->lst); - nm_explicit_bzero(&peer_c->data.preshared_key, sizeof(peer_c->data.preshared_key)); - g_slice_free(WireGuardPeerConstruct, peer_c); - } - return NULL; - } - - /* we receive peers/allowed-ips possibly in separate netlink messages. Hence, while - * parsing the dump, we don't know upfront how many peers/allowed-ips we will receive. - * - * We solve that, by collecting all peers with a CList. It's done this way, - * because a GArray would require growing the array, but we want to bzero() - * the preshared-key of each peer while reallocating. The CList apprach avoids - * that. - * - * For allowed-ips, we instead track one GArray, which are all appended - * there. The realloc/resize of the GArray is fine there. However, - * while we build the GArray, we don't yet have the final pointers. - * Hence, while constructing, we track the indexes with peer->_construct_idx_* - * fields. These indexes must be converted to actual pointers blow. - * - * This is all done during parsing. In the final NMPObjectLnkWireGuard we - * don't want the CList anymore and repackage the NMPObject tightly. The - * reason is, that NMPObject instances are immutable and long-living. Spend - * a bit effort below during construction to obtain a most suitable representation - * in this regard. */ - obj->_lnk_wireguard.peers_len = c_list_length(&parse_data.peers); - obj->_lnk_wireguard.peers = obj->_lnk_wireguard.peers_len > 0 - ? g_new(NMPWireGuardPeer, obj->_lnk_wireguard.peers_len) - : NULL; - - /* duplicate allowed_ips instead of using the pointer. The GArray possibly has more - * space allocated then we need, and we want to get rid of this excess buffer. - * Note that NMPObject instance is possibly put into the cache and long-living. */ - obj->_lnk_wireguard._allowed_ips_buf_len = allowed_ips ? allowed_ips->len : 0u; - obj->_lnk_wireguard._allowed_ips_buf = - obj->_lnk_wireguard._allowed_ips_buf_len > 0 - ? (NMPWireGuardAllowedIP *) nm_memdup(allowed_ips->data, - sizeof(NMPWireGuardAllowedIP) * allowed_ips->len) - : NULL; - - i = 0; - c_list_for_each_entry_safe (peer_c, peer_c_safe, &parse_data.peers, lst) { - NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &obj->_lnk_wireguard.peers[i++]; - - *peer = peer_c->data; - - c_list_unlink_stale(&peer_c->lst); - nm_explicit_bzero(&peer_c->data.preshared_key, sizeof(peer_c->data.preshared_key)); - g_slice_free(WireGuardPeerConstruct, peer_c); - - if (peer->_construct_idx_end != 0) { - guint len; - - nm_assert(obj->_lnk_wireguard._allowed_ips_buf); - nm_assert(peer->_construct_idx_end > peer->_construct_idx_start); - nm_assert(peer->_construct_idx_start < obj->_lnk_wireguard._allowed_ips_buf_len); - nm_assert(peer->_construct_idx_end <= obj->_lnk_wireguard._allowed_ips_buf_len); - - len = peer->_construct_idx_end - peer->_construct_idx_start; - peer->allowed_ips = &obj->_lnk_wireguard._allowed_ips_buf[peer->_construct_idx_start]; - peer->allowed_ips_len = len; - } else { - nm_assert(!peer->_construct_idx_start); - nm_assert(!peer->_construct_idx_end); - peer->allowed_ips = NULL; - peer->allowed_ips_len = 0; - } - } - - return obj; - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static int -_wireguard_get_family_id(NMPlatform *platform, int ifindex_try) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - int wireguard_family_id = -1; - - if (ifindex_try > 0) { - const NMPlatformLink *plink; - - if (nm_platform_link_get_lnk_wireguard(platform, ifindex_try, &plink)) - wireguard_family_id = NMP_OBJECT_UP_CAST(plink)->_link.wireguard_family_id; - } - if (wireguard_family_id < 0) - wireguard_family_id = genl_ctrl_resolve(priv->genl, "wireguard"); - return wireguard_family_id; -} - -static const NMPObject * -_wireguard_refresh_link(NMPlatform *platform, int wireguard_family_id, int ifindex) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - nm_auto_nmpobj const NMPObject *lnk_new = NULL; - NMPCacheOpsType cache_op; - const NMPObject * plink = NULL; - nm_auto_nmpobj NMPObject *obj = NULL; - - nm_assert(wireguard_family_id >= 0); - nm_assert(ifindex > 0); - - nm_platform_process_events(platform); - - plink = nm_platform_link_get_obj(platform, ifindex, TRUE); - - if (!plink || plink->link.type != NM_LINK_TYPE_WIREGUARD) { - nm_platform_link_refresh(platform, ifindex); - plink = nm_platform_link_get_obj(platform, ifindex, TRUE); - if (!plink || plink->link.type != NM_LINK_TYPE_WIREGUARD) - return NULL; - if (NMP_OBJECT_GET_TYPE(plink->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD) - lnk_new = nmp_object_ref(plink->_link.netlink.lnk); - } else { - lnk_new = _wireguard_read_info(platform, priv->genl, wireguard_family_id, ifindex); - if (!lnk_new) { - if (NMP_OBJECT_GET_TYPE(plink->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD) - lnk_new = nmp_object_ref(plink->_link.netlink.lnk); - } else if (nmp_object_equal(plink->_link.netlink.lnk, lnk_new)) { - nmp_object_unref(lnk_new); - lnk_new = nmp_object_ref(plink->_link.netlink.lnk); - } - } - - if (plink->_link.wireguard_family_id == wireguard_family_id - && plink->_link.netlink.lnk == lnk_new) - return plink; - - /* we use nmp_cache_update_netlink() to re-inject the new object into the cache. - * For that, we need to clone it, and tweak it so that it's suitable. It's a bit - * of a hack, in particular that we need to clear driver and udev-device. */ - obj = nmp_object_clone(plink, FALSE); - obj->_link.wireguard_family_id = wireguard_family_id; - nmp_object_unref(obj->_link.netlink.lnk); - obj->_link.netlink.lnk = g_steal_pointer(&lnk_new); - obj->link.driver = NULL; - nm_clear_pointer(&obj->_link.udev.device, udev_device_unref); - - cache_op = - nmp_cache_update_netlink(nm_platform_get_cache(platform), obj, FALSE, &obj_old, &obj_new); - nm_assert(NM_IN_SET(cache_op, NMP_CACHE_OPS_UPDATED)); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - cache_on_change(platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); - } - - nm_assert(!obj_new - || (NMP_OBJECT_GET_TYPE(obj_new) == NMP_OBJECT_TYPE_LINK - && obj_new->link.type == NM_LINK_TYPE_WIREGUARD - && (!obj_new->_link.netlink.lnk - || NMP_OBJECT_GET_TYPE(obj_new->_link.netlink.lnk) - == NMP_OBJECT_TYPE_LNK_WIREGUARD))); - return obj_new; -} - -static int -_wireguard_create_change_nlmsgs(NMPlatform * platform, - int ifindex, - int wireguard_family_id, - const NMPlatformLnkWireGuard * lnk_wireguard, - const NMPWireGuardPeer * peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags, - GPtrArray ** out_msgs) -{ - gs_unref_ptrarray GPtrArray * msgs = NULL; - nm_auto_nlmsg struct nl_msg * msg = NULL; - const guint IDX_NIL = G_MAXUINT; - guint idx_peer_curr; - guint idx_allowed_ips_curr; - struct nlattr * nest_peers; - struct nlattr * nest_curr_peer; - struct nlattr * nest_allowed_ips; - struct nlattr * nest_curr_allowed_ip; - NMPlatformWireGuardChangePeerFlags p_flags = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT; - -#define _nla_nest_end(msg, nest_start) \ - G_STMT_START \ - { \ - if (nla_nest_end((msg), (nest_start)) < 0) \ - g_return_val_if_reached(-NME_BUG); \ - } \ - G_STMT_END - - /* Adapted from LGPL-2.1+ code [1]. - * - * [1] https://git.zx2c4.com/WireGuard/tree/contrib/examples/embeddable-wg-library/wireguard.c?id=5e99a6d43fe2351adf36c786f5ea2086a8fe7ab8#n1073 */ - - idx_peer_curr = IDX_NIL; - idx_allowed_ips_curr = IDX_NIL; - - /* TODO: for the moment, we always reset all peers and allowed-ips (WGDEVICE_F_REPLACE_PEERS, WGPEER_F_REPLACE_ALLOWEDIPS). - * The platform API should be extended to also support partial updates. In particular, configuring the same configuration - * multiple times, should not clear and re-add all settings, but rather sync the existing settings with the desired configuration. */ - -again: - - msg = nlmsg_alloc(); - if (!genlmsg_put(msg, - NL_AUTO_PORT, - NL_AUTO_SEQ, - wireguard_family_id, - 0, - NLM_F_REQUEST, - WG_CMD_SET_DEVICE, - 1)) - g_return_val_if_reached(-NME_BUG); - - NLA_PUT_U32(msg, WGDEVICE_A_IFINDEX, (guint32) ifindex); - - if (idx_peer_curr == IDX_NIL) { - guint32 flags; - - if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY)) - NLA_PUT(msg, - WGDEVICE_A_PRIVATE_KEY, - sizeof(lnk_wireguard->private_key), - lnk_wireguard->private_key); - if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT)) - NLA_PUT_U16(msg, WGDEVICE_A_LISTEN_PORT, lnk_wireguard->listen_port); - if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK)) - NLA_PUT_U32(msg, WGDEVICE_A_FWMARK, lnk_wireguard->fwmark); - - flags = 0; - if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS)) - flags |= WGDEVICE_F_REPLACE_PEERS; - NLA_PUT_U32(msg, WGDEVICE_A_FLAGS, flags); - } - - if (peers_len == 0) - goto send; - - nest_curr_peer = NULL; - nest_allowed_ips = NULL; - nest_curr_allowed_ip = NULL; - - nest_peers = nla_nest_start(msg, WGDEVICE_A_PEERS); - if (!nest_peers) - g_return_val_if_reached(-NME_BUG); - - if (idx_peer_curr == IDX_NIL) - idx_peer_curr = 0; - for (; idx_peer_curr < peers_len; idx_peer_curr++) { - const NMPWireGuardPeer *p = &peers[idx_peer_curr]; - - if (peer_flags) { - p_flags = peer_flags[idx_peer_curr]; - if (!NM_FLAGS_ANY(p_flags, - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)) { - /* no flags set. We take that as indication to skip configuring the peer - * entirely. */ - nm_assert(p_flags == NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE); - continue; - } - } - - nest_curr_peer = nla_nest_start(msg, 0); - if (!nest_curr_peer) - goto toobig_peers; - - if (nla_put(msg, WGPEER_A_PUBLIC_KEY, NMP_WIREGUARD_PUBLIC_KEY_LEN, p->public_key) < 0) - goto toobig_peers; - - if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME)) { - /* all other p_flags are silently ignored. */ - if (nla_put_uint32(msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME) < 0) - goto toobig_peers; - } else { - if (idx_allowed_ips_curr == IDX_NIL) { - if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY) - && nla_put(msg, - WGPEER_A_PRESHARED_KEY, - sizeof(p->preshared_key), - p->preshared_key) - < 0) - goto toobig_peers; - - if (NM_FLAGS_HAS(p_flags, - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL) - && nla_put_uint16(msg, - WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, - p->persistent_keepalive_interval) - < 0) - goto toobig_peers; - - if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS) - && nla_put_uint32(msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0) - goto toobig_peers; - - if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT)) { - if (NM_IN_SET(p->endpoint.sa.sa_family, AF_INET, AF_INET6)) { - if (nla_put(msg, - WGPEER_A_ENDPOINT, - p->endpoint.sa.sa_family == AF_INET ? sizeof(p->endpoint.in) - : sizeof(p->endpoint.in6), - &p->endpoint) - < 0) - goto toobig_peers; - } else { - /* I think there is no way to clear an endpoint, though there should be. */ - nm_assert(p->endpoint.sa.sa_family == AF_UNSPEC); - } - } - } - - if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS) - && p->allowed_ips_len > 0) { - if (idx_allowed_ips_curr == IDX_NIL) - idx_allowed_ips_curr = 0; - - nest_allowed_ips = nla_nest_start(msg, WGPEER_A_ALLOWEDIPS); - if (!nest_allowed_ips) - goto toobig_allowedips; - - for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) { - const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr]; - - nest_curr_allowed_ip = nla_nest_start(msg, 0); - if (!nest_curr_allowed_ip) - goto toobig_allowedips; - - g_return_val_if_fail(NM_IN_SET(aip->family, AF_INET, AF_INET6), -NME_BUG); - - if (nla_put_uint16(msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0) - goto toobig_allowedips; - if (nla_put(msg, - WGALLOWEDIP_A_IPADDR, - nm_utils_addr_family_to_size(aip->family), - &aip->addr) - < 0) - goto toobig_allowedips; - if (nla_put_uint8(msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0) - goto toobig_allowedips; - - _nla_nest_end(msg, nest_curr_allowed_ip); - nest_curr_allowed_ip = NULL; - } - idx_allowed_ips_curr = IDX_NIL; - - _nla_nest_end(msg, nest_allowed_ips); - nest_allowed_ips = NULL; - } - } - - _nla_nest_end(msg, nest_curr_peer); - nest_curr_peer = NULL; - } - - _nla_nest_end(msg, nest_peers); - goto send; - -toobig_allowedips: - if (nest_curr_allowed_ip) - nla_nest_cancel(msg, nest_curr_allowed_ip); - if (nest_allowed_ips) - _nla_nest_end(msg, nest_allowed_ips); - _nla_nest_end(msg, nest_curr_peer); - _nla_nest_end(msg, nest_peers); - goto send; - -toobig_peers: - if (nest_curr_peer) - nla_nest_cancel(msg, nest_curr_peer); - _nla_nest_end(msg, nest_peers); - goto send; - -send: - if (!msgs) - msgs = g_ptr_array_new_with_free_func((GDestroyNotify) nlmsg_free); - g_ptr_array_add(msgs, g_steal_pointer(&msg)); - - if (idx_peer_curr != IDX_NIL && idx_peer_curr < peers_len) - goto again; - - NM_SET_OUT(out_msgs, g_steal_pointer(&msgs)); - return 0; - -nla_put_failure: - g_return_val_if_reached(-NME_BUG); - -#undef _nla_nest_end -} - -static int -link_wireguard_change(NMPlatform * platform, - int ifindex, - const NMPlatformLnkWireGuard * lnk_wireguard, - const NMPWireGuardPeer * peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - gs_unref_ptrarray GPtrArray *msgs = NULL; - int wireguard_family_id; - guint i; - int r; - - wireguard_family_id = _wireguard_get_family_id(platform, ifindex); - if (wireguard_family_id < 0) - return -NME_PL_NO_FIRMWARE; - - r = _wireguard_create_change_nlmsgs(platform, - ifindex, - wireguard_family_id, - lnk_wireguard, - peers, - peer_flags, - peers_len, - change_flags, - &msgs); - if (r < 0) { - _LOGW("wireguard: set-device, cannot construct netlink message: %s", nm_strerror(r)); - return r; - } - - for (i = 0; i < msgs->len; i++) { - r = nl_send_auto(priv->genl, msgs->pdata[i]); - if (r < 0) { - _LOGW("wireguard: set-device, send netlink message #%u failed: %s", i, nm_strerror(r)); - return r; - } - - do { - r = nl_recvmsgs(priv->genl, NULL); - } while (r == -EAGAIN); - if (r < 0) { - _LOGW("wireguard: set-device, message #%u was rejected: %s", i, nm_strerror(r)); - return r; - } - - _LOGT("wireguard: set-device, message #%u sent and confirmed", i); - } - - _wireguard_refresh_link(platform, wireguard_family_id, ifindex); - - return 0; -} - -/*****************************************************************************/ - -static void -_nmp_link_address_set(NMPLinkAddress *dst, const struct nlattr *nla) -{ - *dst = (NMPLinkAddress){ - .len = 0, - }; - if (nla) { - int l = nla_len(nla); - - if (l > 0 && l <= NM_UTILS_HWADDR_LEN_MAX) { - G_STATIC_ASSERT_EXPR(sizeof(dst->data) == NM_UTILS_HWADDR_LEN_MAX); - memcpy(dst->data, nla_data(nla), l); - dst->len = l; - } - } -} - -/* Copied and heavily modified from libnl3's link_msg_parser(). */ -static NMPObject * -_new_from_nl_link(NMPlatform * platform, - const NMPCache * cache, - struct nlmsghdr *nlh, - gboolean id_only) -{ - static const struct nla_policy policy[] = { - [IFLA_IFNAME] = {.type = NLA_STRING, .maxlen = IFNAMSIZ}, - [IFLA_MTU] = {.type = NLA_U32}, - [IFLA_TXQLEN] = {.type = NLA_U32}, - [IFLA_LINK] = {.type = NLA_U32}, - [IFLA_WEIGHT] = {.type = NLA_U32}, - [IFLA_MASTER] = {.type = NLA_U32}, - [IFLA_OPERSTATE] = {.type = NLA_U8}, - [IFLA_LINKMODE] = {.type = NLA_U8}, - [IFLA_LINKINFO] = {.type = NLA_NESTED}, - [IFLA_QDISC] = {.type = NLA_STRING, .maxlen = IFQDISCSIZ}, - [IFLA_STATS] = {.minlen = nm_offsetofend(struct rtnl_link_stats, tx_compressed)}, - [IFLA_STATS64] = {.minlen = nm_offsetofend(struct rtnl_link_stats64, tx_compressed)}, - [IFLA_MAP] = {.minlen = nm_offsetofend(struct rtnl_link_ifmap, port)}, - [IFLA_IFALIAS] = {.type = NLA_STRING, .maxlen = IFALIASZ}, - [IFLA_NUM_VF] = {.type = NLA_U32}, - [IFLA_AF_SPEC] = {.type = NLA_NESTED}, - [IFLA_PROMISCUITY] = {.type = NLA_U32}, - [IFLA_NUM_TX_QUEUES] = {.type = NLA_U32}, - [IFLA_NUM_RX_QUEUES] = {.type = NLA_U32}, - [IFLA_GROUP] = {.type = NLA_U32}, - [IFLA_CARRIER] = {.type = NLA_U8}, - [IFLA_PHYS_PORT_ID] = {.type = NLA_UNSPEC}, - [IFLA_NET_NS_PID] = {.type = NLA_U32}, - [IFLA_NET_NS_FD] = {.type = NLA_U32}, - [IFLA_LINK_NETNSID] = {}, - }; - const struct ifinfomsg *ifi; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - struct nlattr * nl_info_data = NULL; - const char * nl_info_kind = NULL; - nm_auto_nmpobj NMPObject *obj = NULL; - gboolean completed_from_cache_val = FALSE; - gboolean * completed_from_cache = cache ? &completed_from_cache_val : NULL; - const NMPObject * link_cached = NULL; - const NMPObject * lnk_data = NULL; - gboolean address_complete_from_cache = TRUE; - gboolean broadcast_complete_from_cache = TRUE; - gboolean lnk_data_complete_from_cache = TRUE; - gboolean need_ext_data = FALSE; - gboolean af_inet6_token_valid = FALSE; - gboolean af_inet6_addr_gen_mode_valid = FALSE; - - if (!nlmsg_valid_hdr(nlh, sizeof(*ifi))) - return NULL; - - ifi = nlmsg_data(nlh); - - if (ifi->ifi_family != AF_UNSPEC) - return NULL; - if (ifi->ifi_index <= 0) - return NULL; - - obj = nmp_object_new_link(ifi->ifi_index); - - if (id_only) - return g_steal_pointer(&obj); - - if (nlmsg_parse_arr(nlh, sizeof(*ifi), tb, policy) < 0) - return NULL; - - if (!tb[IFLA_IFNAME]) - return NULL; - nla_strlcpy(obj->link.name, tb[IFLA_IFNAME], IFNAMSIZ); - if (!obj->link.name[0]) - return NULL; - - if (!tb[IFLA_MTU]) { - /* Kernel has two places that send RTM_GETLINK messages: - * net/core/rtnetlink.c and net/wireless/ext-core.c. - * Unfortunately ext-core.c sets only IFLA_WIRELESS and - * IFLA_IFNAME. This confuses code in this function, because - * it cannot get complete set of data for the interface and - * later incomplete object this function creates is used to - * overwrite existing data in NM's cache. - * Since ext-core.c doesn't set IFLA_MTU we can use it as a - * signal to ignore incoming message. - * To some extent this is a hack and correct approach is to - * merge objects per-field. - */ - return NULL; - } - obj->link.mtu = nla_get_u32(tb[IFLA_MTU]); - - if (tb[IFLA_LINKINFO]) { - static const struct nla_policy policy_link_info[] = { - [IFLA_INFO_KIND] = {.type = NLA_STRING}, - [IFLA_INFO_DATA] = {.type = NLA_NESTED}, - [IFLA_INFO_XSTATS] = {.type = NLA_NESTED}, - }; - struct nlattr *li[G_N_ELEMENTS(policy_link_info)]; - - if (nla_parse_nested_arr(li, tb[IFLA_LINKINFO], policy_link_info) < 0) - return NULL; - - if (li[IFLA_INFO_KIND]) - nl_info_kind = nla_get_string(li[IFLA_INFO_KIND]); - - nl_info_data = li[IFLA_INFO_DATA]; - } - - if (tb[IFLA_STATS64]) { - const char *stats = nla_data(tb[IFLA_STATS64]); - - obj->link.rx_packets = - unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, rx_packets)]); - obj->link.rx_bytes = - unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, rx_bytes)]); - obj->link.tx_packets = - unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, tx_packets)]); - obj->link.tx_bytes = - unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, tx_bytes)]); - } - - obj->link.n_ifi_flags = ifi->ifi_flags; - obj->link.connected = NM_FLAGS_HAS(obj->link.n_ifi_flags, IFF_LOWER_UP); - obj->link.arptype = ifi->ifi_type; - - obj->link.type = _linktype_get_type(platform, - cache, - nl_info_kind, - obj->link.ifindex, - obj->link.name, - obj->link.n_ifi_flags, - obj->link.arptype, - completed_from_cache, - &link_cached, - &obj->link.kind); - - if (tb[IFLA_MASTER]) - obj->link.master = nla_get_u32(tb[IFLA_MASTER]); - - if (tb[IFLA_LINK]) { - if (!tb[IFLA_LINK_NETNSID]) - obj->link.parent = nla_get_u32(tb[IFLA_LINK]); - else - obj->link.parent = NM_PLATFORM_LINK_OTHER_NETNS; - } - - if (tb[IFLA_ADDRESS]) { - _nmp_link_address_set(&obj->link.l_address, tb[IFLA_ADDRESS]); - address_complete_from_cache = FALSE; - } - - if (tb[IFLA_BROADCAST]) { - _nmp_link_address_set(&obj->link.l_broadcast, tb[IFLA_BROADCAST]); - broadcast_complete_from_cache = FALSE; - } - - if (tb[IFLA_AF_SPEC]) { - struct nlattr *af_attr; - int remaining; - - nla_for_each_nested (af_attr, tb[IFLA_AF_SPEC], remaining) { - switch (nla_type(af_attr)) { - case AF_INET6: - _parse_af_inet6(platform, - af_attr, - &obj->link.inet6_token, - &af_inet6_token_valid, - &obj->link.inet6_addr_gen_mode_inv, - &af_inet6_addr_gen_mode_valid); - break; - } - } - } - - switch (obj->link.type) { - case NM_LINK_TYPE_BRIDGE: - lnk_data = _parse_lnk_bridge(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: - lnk_data = _parse_lnk_gre(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_INFINIBAND: - lnk_data = _parse_lnk_infiniband(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_IP6TNL: - lnk_data = _parse_lnk_ip6tnl(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_IP6GRE: - case NM_LINK_TYPE_IP6GRETAP: - lnk_data = _parse_lnk_ip6gre(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_IPIP: - lnk_data = _parse_lnk_ipip(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_MACSEC: - lnk_data = _parse_lnk_macsec(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_MACVLAN: - case NM_LINK_TYPE_MACVTAP: - lnk_data = _parse_lnk_macvlan(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_SIT: - lnk_data = _parse_lnk_sit(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_TUN: - lnk_data = _parse_lnk_tun(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_VLAN: - lnk_data = _parse_lnk_vlan(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_VRF: - lnk_data = _parse_lnk_vrf(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_VXLAN: - lnk_data = _parse_lnk_vxlan(nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_WIFI: - case NM_LINK_TYPE_OLPC_MESH: - case NM_LINK_TYPE_WPAN: - need_ext_data = TRUE; - lnk_data_complete_from_cache = FALSE; - break; - case NM_LINK_TYPE_WIREGUARD: - lnk_data_complete_from_cache = TRUE; - break; - default: - lnk_data_complete_from_cache = FALSE; - break; - } - - if (completed_from_cache - && (lnk_data_complete_from_cache || need_ext_data || address_complete_from_cache - || broadcast_complete_from_cache || !af_inet6_token_valid - || !af_inet6_addr_gen_mode_valid || !tb[IFLA_STATS64])) { - _lookup_cached_link(cache, obj->link.ifindex, completed_from_cache, &link_cached); - if (link_cached && link_cached->_link.netlink.is_in_netlink) { - if (lnk_data_complete_from_cache && link_cached->link.type == obj->link.type - && link_cached->_link.netlink.lnk - && (!lnk_data || nmp_object_equal(lnk_data, link_cached->_link.netlink.lnk))) { - /* We always try to look into the cache and reuse the object there. - * We do that, because we consider the lnk object as immutable and don't - * modify it after creating. Hence we can share it and reuse. - * - * Also, sometimes the info-data is missing for updates. In this case - * we want to keep the previously received lnk_data. */ - nmp_object_unref(lnk_data); - lnk_data = nmp_object_ref(link_cached->_link.netlink.lnk); - } - - if (need_ext_data && link_cached->link.type == obj->link.type - && link_cached->_link.ext_data) { - /* Prefer reuse of existing ext_data object */ - obj->_link.ext_data = g_object_ref(link_cached->_link.ext_data); - } - - if (address_complete_from_cache) - obj->link.l_address = link_cached->link.l_address; - if (broadcast_complete_from_cache) - obj->link.l_broadcast = link_cached->link.l_broadcast; - if (!af_inet6_token_valid) - obj->link.inet6_token = link_cached->link.inet6_token; - if (!af_inet6_addr_gen_mode_valid) - obj->link.inet6_addr_gen_mode_inv = link_cached->link.inet6_addr_gen_mode_inv; - if (!tb[IFLA_STATS64]) { - obj->link.rx_packets = link_cached->link.rx_packets; - obj->link.rx_bytes = link_cached->link.rx_bytes; - obj->link.tx_packets = link_cached->link.tx_packets; - obj->link.tx_bytes = link_cached->link.tx_bytes; - } - } - } - - obj->_link.netlink.lnk = lnk_data; - - if (need_ext_data && obj->_link.ext_data == NULL) { - switch (obj->link.type) { - case NM_LINK_TYPE_WIFI: - case NM_LINK_TYPE_OLPC_MESH: - obj->_link.ext_data = - (GObject *) nm_wifi_utils_new(ifi->ifi_index, - _genl_sock(NM_LINUX_PLATFORM(platform)), - TRUE); - break; - case NM_LINK_TYPE_WPAN: - obj->_link.ext_data = - (GObject *) nm_wpan_utils_new(ifi->ifi_index, - _genl_sock(NM_LINUX_PLATFORM(platform)), - TRUE); - break; - default: - g_assert_not_reached(); - } - } - - if (obj->link.type == NM_LINK_TYPE_WIREGUARD) { - const NMPObject *lnk_data_new = NULL; - struct nl_sock * genl = NM_LINUX_PLATFORM_GET_PRIVATE(platform)->genl; - - /* The WireGuard kernel module does not yet send link update - * notifications, so we don't actually update the cache. For - * now, always refetch link data here. */ - - _lookup_cached_link(cache, obj->link.ifindex, completed_from_cache, &link_cached); - if (link_cached && link_cached->_link.netlink.is_in_netlink - && link_cached->link.type == NM_LINK_TYPE_WIREGUARD) - obj->_link.wireguard_family_id = link_cached->_link.wireguard_family_id; - else - obj->_link.wireguard_family_id = -1; - - if (obj->_link.wireguard_family_id < 0) - obj->_link.wireguard_family_id = genl_ctrl_resolve(genl, "wireguard"); - - if (obj->_link.wireguard_family_id >= 0) { - lnk_data_new = _wireguard_read_info(platform, - genl, - obj->_link.wireguard_family_id, - obj->link.ifindex); - } - - if (lnk_data_new && obj->_link.netlink.lnk - && nmp_object_equal(obj->_link.netlink.lnk, lnk_data_new)) - nmp_object_unref(lnk_data_new); - else { - nmp_object_unref(obj->_link.netlink.lnk); - obj->_link.netlink.lnk = lnk_data_new; - } - } - - obj->_link.netlink.is_in_netlink = TRUE; - return g_steal_pointer(&obj); -} - -/* Copied and heavily modified from libnl3's addr_msg_parser(). */ -static NMPObject * -_new_from_nl_addr(struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [IFA_LABEL] = {.type = NLA_STRING, .maxlen = IFNAMSIZ}, - [IFA_CACHEINFO] = {.minlen = nm_offsetofend(struct ifa_cacheinfo, tstamp)}, - [IFA_FLAGS] = {}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - const struct ifaddrmsg *ifa; - gboolean is_v4; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_len; - guint32 lifetime, preferred, timestamp; - - if (!nlmsg_valid_hdr(nlh, sizeof(*ifa))) - return NULL; - - ifa = nlmsg_data(nlh); - - if (!NM_IN_SET(ifa->ifa_family, AF_INET, AF_INET6)) - return NULL; - - is_v4 = ifa->ifa_family == AF_INET; - - if (nlmsg_parse_arr(nlh, sizeof(*ifa), tb, policy) < 0) - return NULL; - - addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); - - if (ifa->ifa_prefixlen > (is_v4 ? 32 : 128)) - return NULL; - - /*****************************************************************/ - - obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL); - - obj->ip_address.ifindex = ifa->ifa_index; - obj->ip_address.plen = ifa->ifa_prefixlen; - - _check_addr_or_return_null(tb, IFA_ADDRESS, addr_len); - _check_addr_or_return_null(tb, IFA_LOCAL, addr_len); - if (is_v4) { - /* For IPv4, kernel omits IFA_LOCAL/IFA_ADDRESS if (and only if) they - * are effectively 0.0.0.0 (all-zero). */ - if (tb[IFA_LOCAL]) - memcpy(&obj->ip4_address.address, nla_data(tb[IFA_LOCAL]), addr_len); - if (tb[IFA_ADDRESS]) - memcpy(&obj->ip4_address.peer_address, nla_data(tb[IFA_ADDRESS]), addr_len); - - _check_addr_or_return_null(tb, IFA_BROADCAST, addr_len); - obj->ip4_address.broadcast_address = - tb[IFA_BROADCAST] ? nla_get_u32(tb[IFA_BROADCAST]) : 0u; - obj->ip4_address.use_ip4_broadcast_address = TRUE; - } else { - /* For IPv6, IFA_ADDRESS is always present. - * - * If IFA_LOCAL is missing, IFA_ADDRESS is @address and @peer_address - * is :: (all-zero). - * - * If unexpectedly IFA_ADDRESS is missing, make the best of it -- but it _should_ - * actually be there. */ - if (tb[IFA_ADDRESS] || tb[IFA_LOCAL]) { - if (tb[IFA_LOCAL]) { - memcpy(&obj->ip6_address.address, nla_data(tb[IFA_LOCAL]), addr_len); - if (tb[IFA_ADDRESS]) - memcpy(&obj->ip6_address.peer_address, nla_data(tb[IFA_ADDRESS]), addr_len); - else - obj->ip6_address.peer_address = obj->ip6_address.address; - } else - memcpy(&obj->ip6_address.address, nla_data(tb[IFA_ADDRESS]), addr_len); - } - } - - obj->ip_address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; - - obj->ip_address.n_ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifa->ifa_flags; - - if (is_v4) { - if (tb[IFA_LABEL]) { - char label[IFNAMSIZ]; - - nla_strlcpy(label, tb[IFA_LABEL], IFNAMSIZ); - - /* Check for ':'; we're only interested in labels used as interface aliases */ - if (strchr(label, ':')) - g_strlcpy(obj->ip4_address.label, label, sizeof(obj->ip4_address.label)); - } - } - - lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - preferred = NM_PLATFORM_LIFETIME_PERMANENT; - timestamp = 0; - /* IPv6 only */ - if (tb[IFA_CACHEINFO]) { - const struct ifa_cacheinfo *ca; - - ca = nla_data_as(struct ifa_cacheinfo, tb[IFA_CACHEINFO]); - lifetime = ca->ifa_valid; - preferred = ca->ifa_prefered; - timestamp = ca->tstamp; - } - _addrtime_get_lifetimes(timestamp, - lifetime, - preferred, - &obj->ip_address.timestamp, - &obj->ip_address.lifetime, - &obj->ip_address.preferred); - - return g_steal_pointer(&obj); -} - -/* Copied and heavily modified from libnl3's rtnl_route_parse() and parse_multipath(). */ -static NMPObject * -_new_from_nl_route(struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [RTA_TABLE] = {.type = NLA_U32}, - [RTA_IIF] = {.type = NLA_U32}, - [RTA_OIF] = {.type = NLA_U32}, - [RTA_PRIORITY] = {.type = NLA_U32}, - [RTA_PREF] = {.type = NLA_U8}, - [RTA_FLOW] = {.type = NLA_U32}, - [RTA_CACHEINFO] = {.minlen = nm_offsetofend(struct rta_cacheinfo, rta_tsage)}, - [RTA_METRICS] = {.type = NLA_NESTED}, - [RTA_MULTIPATH] = {.type = NLA_NESTED}, - }; - const struct rtmsg *rtm; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - gboolean is_v4; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_len; - struct { - gboolean is_present; - int ifindex; - NMIPAddr gateway; - } nh = { - .is_present = FALSE, - }; - guint32 mss; - guint32 window = 0; - guint32 cwnd = 0; - guint32 initcwnd = 0; - guint32 initrwnd = 0; - guint32 mtu = 0; - guint32 lock = 0; - - if (!nlmsg_valid_hdr(nlh, sizeof(*rtm))) - return NULL; - - rtm = nlmsg_data(nlh); - - /***************************************************************** - * only handle ~supported~ routes. - *****************************************************************/ - - if (!NM_IN_SET(rtm->rtm_family, AF_INET, AF_INET6)) - return NULL; - - if (!NM_IN_SET(rtm->rtm_type, RTN_UNICAST, RTN_LOCAL)) - return NULL; - - if (nlmsg_parse_arr(nlh, sizeof(struct rtmsg), tb, policy) < 0) - return NULL; - - /*****************************************************************/ - - is_v4 = rtm->rtm_family == AF_INET; - addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); - - if (rtm->rtm_dst_len > (is_v4 ? 32 : 128)) - return NULL; - - /***************************************************************** - * parse nexthops. Only handle routes with one nh. - *****************************************************************/ - - if (tb[RTA_MULTIPATH]) { - size_t tlen = nla_len(tb[RTA_MULTIPATH]); - struct rtnexthop *rtnh; - - if (tlen < sizeof(*rtnh)) - goto rta_multipath_done; - - rtnh = nla_data_as(struct rtnexthop, tb[RTA_MULTIPATH]); - - if (tlen < rtnh->rtnh_len) - goto rta_multipath_done; - - while (TRUE) { - if (nh.is_present) { - /* we don't support multipath routes. */ - return NULL; - } - - nh.is_present = TRUE; - nh.ifindex = rtnh->rtnh_ifindex; - - if (rtnh->rtnh_len > sizeof(*rtnh)) { - struct nlattr *ntb[G_N_ELEMENTS(policy)]; - - if (nla_parse_arr(ntb, - (struct nlattr *) RTNH_DATA(rtnh), - rtnh->rtnh_len - sizeof(*rtnh), - policy) - < 0) - return NULL; - - if (_check_addr_or_return_null(ntb, RTA_GATEWAY, addr_len)) - memcpy(&nh.gateway, nla_data(ntb[RTA_GATEWAY]), addr_len); - } - - if (tlen < RTNH_ALIGN(rtnh->rtnh_len) + sizeof(*rtnh)) - goto rta_multipath_done; - - tlen -= RTNH_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } -rta_multipath_done:; - } - - if (tb[RTA_OIF] || tb[RTA_GATEWAY] || tb[RTA_FLOW]) { - int ifindex = 0; - NMIPAddr gateway = {}; - - if (tb[RTA_OIF]) - ifindex = nla_get_u32(tb[RTA_OIF]); - if (_check_addr_or_return_null(tb, RTA_GATEWAY, addr_len)) - memcpy(&gateway, nla_data(tb[RTA_GATEWAY]), addr_len); - - if (!nh.is_present) { - /* If no nexthops have been provided via RTA_MULTIPATH - * we add it as regular nexthop to maintain backwards - * compatibility */ - nh.ifindex = ifindex; - nh.gateway = gateway; - } else { - /* Kernel supports new style nexthop configuration, - * verify that it is a duplicate and ignore old-style nexthop. */ - if (nh.ifindex != ifindex || memcmp(&nh.gateway, &gateway, addr_len) != 0) - return NULL; - } - } else if (!nh.is_present) - return NULL; - - /*****************************************************************/ - - mss = 0; - if (tb[RTA_METRICS]) { - static const struct nla_policy rtax_policy[] = { - [RTAX_LOCK] = {.type = NLA_U32}, - [RTAX_ADVMSS] = {.type = NLA_U32}, - [RTAX_WINDOW] = {.type = NLA_U32}, - [RTAX_CWND] = {.type = NLA_U32}, - [RTAX_INITCWND] = {.type = NLA_U32}, - [RTAX_INITRWND] = {.type = NLA_U32}, - [RTAX_MTU] = {.type = NLA_U32}, - }; - struct nlattr *mtb[G_N_ELEMENTS(rtax_policy)]; - - if (nla_parse_nested_arr(mtb, tb[RTA_METRICS], rtax_policy) < 0) - return NULL; - - if (mtb[RTAX_LOCK]) - lock = nla_get_u32(mtb[RTAX_LOCK]); - if (mtb[RTAX_ADVMSS]) - mss = nla_get_u32(mtb[RTAX_ADVMSS]); - if (mtb[RTAX_WINDOW]) - window = nla_get_u32(mtb[RTAX_WINDOW]); - if (mtb[RTAX_CWND]) - cwnd = nla_get_u32(mtb[RTAX_CWND]); - if (mtb[RTAX_INITCWND]) - initcwnd = nla_get_u32(mtb[RTAX_INITCWND]); - if (mtb[RTAX_INITRWND]) - initrwnd = nla_get_u32(mtb[RTAX_INITRWND]); - if (mtb[RTAX_MTU]) - mtu = nla_get_u32(mtb[RTAX_MTU]); - } - - /*****************************************************************/ - - obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL); - - obj->ip_route.type_coerced = nm_platform_route_type_coerce(rtm->rtm_type); - obj->ip_route.table_coerced = nm_platform_route_table_coerce( - tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : (guint32) rtm->rtm_table); - - obj->ip_route.ifindex = nh.ifindex; - - if (_check_addr_or_return_null(tb, RTA_DST, addr_len)) - memcpy(obj->ip_route.network_ptr, nla_data(tb[RTA_DST]), addr_len); - - obj->ip_route.plen = rtm->rtm_dst_len; - - if (tb[RTA_PRIORITY]) - obj->ip_route.metric = nla_get_u32(tb[RTA_PRIORITY]); - - if (is_v4) - obj->ip4_route.gateway = nh.gateway.addr4; - else - obj->ip6_route.gateway = nh.gateway.addr6; - - if (is_v4) - obj->ip4_route.scope_inv = nm_platform_route_scope_inv(rtm->rtm_scope); - - if (_check_addr_or_return_null(tb, RTA_PREFSRC, addr_len)) { - if (is_v4) - memcpy(&obj->ip4_route.pref_src, nla_data(tb[RTA_PREFSRC]), addr_len); - else - memcpy(&obj->ip6_route.pref_src, nla_data(tb[RTA_PREFSRC]), addr_len); - } - - if (is_v4) - obj->ip4_route.tos = rtm->rtm_tos; - else { - if (tb[RTA_SRC]) { - _check_addr_or_return_null(tb, RTA_SRC, addr_len); - memcpy(&obj->ip6_route.src, nla_data(tb[RTA_SRC]), addr_len); - } - obj->ip6_route.src_plen = rtm->rtm_src_len; - } - - obj->ip_route.mss = mss; - obj->ip_route.window = window; - obj->ip_route.cwnd = cwnd; - obj->ip_route.initcwnd = initcwnd; - obj->ip_route.initrwnd = initrwnd; - obj->ip_route.mtu = mtu; - obj->ip_route.lock_window = NM_FLAGS_HAS(lock, 1 << RTAX_WINDOW); - obj->ip_route.lock_cwnd = NM_FLAGS_HAS(lock, 1 << RTAX_CWND); - obj->ip_route.lock_initcwnd = NM_FLAGS_HAS(lock, 1 << RTAX_INITCWND); - obj->ip_route.lock_initrwnd = NM_FLAGS_HAS(lock, 1 << RTAX_INITRWND); - obj->ip_route.lock_mtu = NM_FLAGS_HAS(lock, 1 << RTAX_MTU); - - if (!is_v4) { - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)) { - /* Detect support for RTA_PREF by inspecting the netlink message. - * RTA_PREF was added in kernel 4.1, dated 21 June, 2015. */ - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF, - tb[RTA_PREF] ? 1 : -1); - } - - if (tb[RTA_PREF]) - obj->ip6_route.rt_pref = nla_get_u8(tb[RTA_PREF]); - } - - obj->ip_route.r_rtm_flags = rtm->rtm_flags; - obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot(rtm->rtm_protocol); - - return g_steal_pointer(&obj); -} - -static NMPObject * -_new_from_nl_routing_rule(struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [FRA_UNSPEC] = {}, - [FRA_DST] = {/* struct in_addr, struct in6_addr */}, - [FRA_SRC] = {/* struct in_addr, struct in6_addr */}, - [FRA_IIFNAME] = - { - .type = NLA_STRING, - .maxlen = IFNAMSIZ, - }, - [FRA_GOTO] = - { - .type = NLA_U32, - }, - [FRA_UNUSED2] = {}, - [FRA_PRIORITY] = - { - .type = NLA_U32, - }, - [FRA_UNUSED3] = {}, - [FRA_UNUSED4] = {}, - [FRA_UNUSED5] = {}, - [FRA_FWMARK] = - { - .type = NLA_U32, - }, - [FRA_FLOW] = - { - .type = NLA_U32, - }, - [FRA_TUN_ID] = - { - .type = NLA_U64, - }, - [FRA_SUPPRESS_IFGROUP] = - { - .type = NLA_U32, - }, - [FRA_SUPPRESS_PREFIXLEN] = - { - .type = NLA_U32, - }, - [FRA_TABLE] = - { - .type = NLA_U32, - }, - [FRA_FWMASK] = - { - .type = NLA_U32, - }, - [FRA_OIFNAME] = - { - .type = NLA_STRING, - .maxlen = IFNAMSIZ, - }, - [FRA_PAD] = - { - .type = NLA_U32, - }, - [FRA_L3MDEV] = - { - .type = NLA_U8, - }, - [FRA_UID_RANGE] = - { - .minlen = sizeof(NMFibRuleUidRange), - .maxlen = sizeof(NMFibRuleUidRange), - }, - [FRA_PROTOCOL] = - { - .type = NLA_U8, - }, - [FRA_IP_PROTO] = - { - .type = NLA_U8, - }, - [FRA_SPORT_RANGE] = - { - .minlen = sizeof(NMFibRulePortRange), - .maxlen = sizeof(NMFibRulePortRange), - }, - [FRA_DPORT_RANGE] = - { - .minlen = sizeof(NMFibRulePortRange), - .maxlen = sizeof(NMFibRulePortRange), - }, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - const struct fib_rule_hdr *frh; - NMPlatformRoutingRule * props; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_family; - guint8 addr_size; - - if (nlmsg_parse_arr(nlh, sizeof(*frh), tb, policy) < 0) - return NULL; - - frh = nlmsg_data(nlh); - - addr_family = frh->family; - - if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { - /* we don't care about other address families. */ - return NULL; - } - - addr_size = nm_utils_addr_family_to_size(addr_family); - - obj = nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, NULL); - props = &obj->routing_rule; - - props->addr_family = addr_family; - props->action = frh->action; - props->flags = frh->flags; - props->tos = frh->tos; - - props->table = tb[FRA_TABLE] ? nla_get_u32(tb[FRA_TABLE]) : frh->table; - - if (tb[FRA_SUPPRESS_PREFIXLEN]) - props->suppress_prefixlen_inverse = ~nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]); - - if (tb[FRA_SUPPRESS_IFGROUP]) - props->suppress_ifgroup_inverse = ~nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]); - - if (tb[FRA_IIFNAME]) - nla_strlcpy(props->iifname, tb[FRA_IIFNAME], sizeof(props->iifname)); - - if (tb[FRA_OIFNAME]) - nla_strlcpy(props->oifname, tb[FRA_OIFNAME], sizeof(props->oifname)); - - if (tb[FRA_PRIORITY]) - props->priority = nla_get_u32(tb[FRA_PRIORITY]); - - if (tb[FRA_FWMARK]) - props->fwmark = nla_get_u32(tb[FRA_FWMARK]); - - if (tb[FRA_FWMASK]) - props->fwmask = nla_get_u32(tb[FRA_FWMASK]); - - if (tb[FRA_GOTO]) - props->goto_target = nla_get_u32(tb[FRA_GOTO]); - - props->src_len = frh->src_len; - if (props->src_len > addr_size * 8) - return NULL; - if (!tb[FRA_SRC]) { - if (props->src_len > 0) - return NULL; - } else if (!nm_ip_addr_set_from_untrusted(addr_family, - &props->src, - nla_data(tb[FRA_SRC]), - nla_len(tb[FRA_SRC]), - NULL)) - return NULL; - - props->dst_len = frh->dst_len; - if (props->dst_len > addr_size * 8) - return NULL; - if (!tb[FRA_DST]) { - if (props->dst_len > 0) - return NULL; - } else if (!nm_ip_addr_set_from_untrusted(addr_family, - &props->dst, - nla_data(tb[FRA_DST]), - nla_len(tb[FRA_DST]), - NULL)) - return NULL; - - if (tb[FRA_FLOW]) - props->flow = nla_get_u32(tb[FRA_FLOW]); - - if (tb[FRA_TUN_ID]) - props->tun_id = nla_get_be64(tb[FRA_TUN_ID]); - - if (tb[FRA_L3MDEV]) { - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV)) { - /* support for FRA_L3MDEV was added in 96c63fa7393d0a346acfe5a91e0c7d4c7782641b, - * kernel 4.8, 3 October 2017. - * - * We can only detect support if the attribute is present. A missing attribute - * is not conclusive. */ - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, 1); - } - - /* actually, kernel only allows this attribute to be missing or - * "1". Still, encode it as full uint8. - * - * Note that FRA_L3MDEV and FRA_TABLE are mutally exclusive. */ - props->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); - } - - if (tb[FRA_PROTOCOL]) - props->protocol = nla_get_u8(tb[FRA_PROTOCOL]); - else - nm_assert(props->protocol == RTPROT_UNSPEC); - - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) { - /* FRA_PROTOCOL was added in kernel 4.17, dated 3 June, 2018. - * See commit 1b71af6053af1bd2f849e9fda4f71c1e3f145dcf. */ - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL, - tb[FRA_PROTOCOL] ? 1 : -1); - } - - if (tb[FRA_IP_PROTO]) - props->ip_proto = nla_get_u8(tb[FRA_IP_PROTO]); - - G_STATIC_ASSERT_EXPR(sizeof(NMFibRulePortRange) == 4); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRulePortRange, start) == 0); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRulePortRange, end) == 2); - - nla_memcpy_checked_size(&props->sport_range, tb[FRA_SPORT_RANGE], sizeof(props->sport_range)); - nla_memcpy_checked_size(&props->dport_range, tb[FRA_DPORT_RANGE], sizeof(props->dport_range)); - - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { - /* support for FRA_IP_PROTO, FRA_SPORT_RANGE, and FRA_DPORT_RANGE was added together - * by bfff4862653bb96001ab57c1edd6d03f48e5f035, kernel 4.17, 4 June 2018. - * - * Unfortunately, a missing attribute does not tell us anything about support. - * We can only tell for sure when we have support, but not when we don't have. */ - if (tb[FRA_IP_PROTO] || tb[FRA_SPORT_RANGE] || tb[FRA_DPORT_RANGE]) - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO, 1); - } - - G_STATIC_ASSERT_EXPR(sizeof(NMFibRuleUidRange) == 8); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRuleUidRange, start) == 0); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRuleUidRange, end) == 4); - - if (tb[FRA_UID_RANGE]) { - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { - /* support for FRA_UID_RANGE was added in 622ec2c9d52405973c9f1ca5116eb1c393adfc7d, - * kernel 4.10, 19 February 2017. - * - * We can only detect support if the attribute is present. A missing attribute - * is not conclusive. */ - _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, 1); - } - - nla_memcpy_checked_size(&props->uid_range, tb[FRA_UID_RANGE], sizeof(props->uid_range)); - props->uid_range_has = TRUE; - } - - return g_steal_pointer(&obj); -} - -static guint32 -psched_tick_to_time(NMPlatform *platform, guint32 tick) -{ - static gboolean initialized; - static double tick_in_usec = 1; - - if (!initialized) { - gs_free char *params = NULL; - double clock_factor = 1; - guint32 clock_res; - guint32 t2us; - guint32 us2t; - - initialized = TRUE; - params = nm_platform_sysctl_get(platform, NMP_SYSCTL_PATHID_ABSOLUTE("/proc/net/psched")); - if (!params || sscanf(params, "%08x%08x%08x", &t2us, &us2t, &clock_res) != 3) { - _LOGW("packet scheduler parameters not available"); - } else { - /* See tc_core_init() in iproute2 */ - if (clock_res == 1000000000) - t2us = us2t; - - clock_factor = (double) clock_res / PSCHED_TIME_UNITS_PER_SEC; - tick_in_usec = (double) t2us / us2t * clock_factor; - } - } - - return tick / tick_in_usec; -} - -static NMPObject * -_new_from_nl_qdisc(NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [TCA_KIND] = {.type = NLA_STRING}, - [TCA_OPTIONS] = {.type = NLA_NESTED}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - const struct tcmsg *tcm; - nm_auto_nmpobj NMPObject *obj = NULL; - - if (nlmsg_parse_arr(nlh, sizeof(*tcm), tb, policy) < 0) - return NULL; - - if (!tb[TCA_KIND]) - return NULL; - - tcm = nlmsg_data(nlh); - - obj = nmp_object_new(NMP_OBJECT_TYPE_QDISC, NULL); - - obj->qdisc.kind = g_intern_string(nla_get_string(tb[TCA_KIND])); - obj->qdisc.ifindex = tcm->tcm_ifindex; - obj->qdisc.addr_family = tcm->tcm_family; - obj->qdisc.handle = tcm->tcm_handle; - obj->qdisc.parent = tcm->tcm_parent; - obj->qdisc.info = tcm->tcm_info; - - if (nm_streq0(obj->qdisc.kind, "fq_codel")) { - obj->qdisc.fq_codel.memory_limit = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; - obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED; - } - - if (tb[TCA_OPTIONS]) { - struct nlattr *options_attr; - int remaining; - - if (nm_streq0(obj->qdisc.kind, "sfq")) { - struct tc_sfq_qopt_v1 opt; - - if (tb[TCA_OPTIONS]->nla_len >= nla_attr_size(sizeof(opt))) { - memcpy(&opt, nla_data(tb[TCA_OPTIONS]), sizeof(opt)); - obj->qdisc.sfq.quantum = opt.v0.quantum; - obj->qdisc.sfq.perturb_period = opt.v0.perturb_period; - obj->qdisc.sfq.limit = opt.v0.limit; - obj->qdisc.sfq.divisor = opt.v0.divisor; - obj->qdisc.sfq.flows = opt.v0.flows; - obj->qdisc.sfq.depth = opt.depth; - } - } else if (nm_streq0(obj->qdisc.kind, "tbf")) { - static const struct nla_policy tbf_policy[] = { - [TCA_TBF_PARMS] = {.minlen = sizeof(struct tc_tbf_qopt)}, - [TCA_TBF_RATE64] = {.type = NLA_U64}, - }; - struct nlattr * tbf_tb[G_N_ELEMENTS(tbf_policy)]; - struct tc_tbf_qopt opt; - - if (nla_parse_nested_arr(tbf_tb, tb[TCA_OPTIONS], tbf_policy) < 0) - return NULL; - if (!tbf_tb[TCA_TBF_PARMS]) - return NULL; - - nla_memcpy_checked_size(&opt, tbf_tb[TCA_TBF_PARMS], sizeof(opt)); - obj->qdisc.tbf.rate = opt.rate.rate; - if (tbf_tb[TCA_TBF_RATE64]) - obj->qdisc.tbf.rate = nla_get_u64(tbf_tb[TCA_TBF_RATE64]); - obj->qdisc.tbf.burst = - ((double) obj->qdisc.tbf.rate * psched_tick_to_time(platform, opt.buffer)) - / PSCHED_TIME_UNITS_PER_SEC; - obj->qdisc.tbf.limit = opt.limit; - } else { - nla_for_each_nested (options_attr, tb[TCA_OPTIONS], remaining) { - if (nla_len(options_attr) < sizeof(uint32_t)) - continue; - - if (nm_streq0(obj->qdisc.kind, "fq_codel")) { - switch (nla_type(options_attr)) { - case TCA_FQ_CODEL_LIMIT: - obj->qdisc.fq_codel.limit = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_FLOWS: - obj->qdisc.fq_codel.flows = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_TARGET: - obj->qdisc.fq_codel.target = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_INTERVAL: - obj->qdisc.fq_codel.interval = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_QUANTUM: - obj->qdisc.fq_codel.quantum = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_CE_THRESHOLD: - obj->qdisc.fq_codel.ce_threshold = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_MEMORY_LIMIT: - obj->qdisc.fq_codel.memory_limit = nla_get_u32(options_attr); - break; - case TCA_FQ_CODEL_ECN: - obj->qdisc.fq_codel.ecn = !!nla_get_u32(options_attr); - break; - } - } - } - } - } - - return g_steal_pointer(&obj); -} - -static NMPObject * -_new_from_nl_tfilter(struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [TCA_KIND] = {.type = NLA_STRING}, - }; - struct nlattr * tb[G_N_ELEMENTS(policy)]; - NMPObject * obj = NULL; - const struct tcmsg *tcm; - - if (nlmsg_parse_arr(nlh, sizeof(*tcm), tb, policy) < 0) - return NULL; - - if (!tb[TCA_KIND]) - return NULL; - - tcm = nlmsg_data(nlh); - - obj = nmp_object_new(NMP_OBJECT_TYPE_TFILTER, NULL); - - obj->tfilter.kind = g_intern_string(nla_get_string(tb[TCA_KIND])); - obj->tfilter.ifindex = tcm->tcm_ifindex; - obj->tfilter.addr_family = tcm->tcm_family; - obj->tfilter.handle = tcm->tcm_handle; - obj->tfilter.parent = tcm->tcm_parent; - obj->tfilter.info = tcm->tcm_info; - - return obj; -} - -/** - * nmp_object_new_from_nl: - * @platform: (allow-none): for creating certain objects, the constructor wants to check - * sysfs. For this the platform instance is needed. If missing, the object might not - * be correctly detected. - * @cache: (allow-none): for certain objects, the netlink message doesn't contain all the information. - * If a cache is given, the object is completed with information from the cache. - * @nlh: the netlink message header - * @id_only: whether only to create an empty object with only the ID fields set. - * - * Returns: %NULL or a newly created NMPObject instance. - **/ -static NMPObject * -nmp_object_new_from_nl(NMPlatform * platform, - const NMPCache *cache, - struct nl_msg * msg, - gboolean id_only) -{ - struct nlmsghdr *msghdr; - - if (nlmsg_get_proto(msg) != NETLINK_ROUTE) - return NULL; - - msghdr = nlmsg_hdr(msg); - - switch (msghdr->nlmsg_type) { - case RTM_NEWLINK: - case RTM_DELLINK: - case RTM_GETLINK: - case RTM_SETLINK: - return _new_from_nl_link(platform, cache, msghdr, id_only); - case RTM_NEWADDR: - case RTM_DELADDR: - case RTM_GETADDR: - return _new_from_nl_addr(msghdr, id_only); - case RTM_NEWROUTE: - case RTM_DELROUTE: - case RTM_GETROUTE: - return _new_from_nl_route(msghdr, id_only); - case RTM_NEWRULE: - case RTM_DELRULE: - case RTM_GETRULE: - return _new_from_nl_routing_rule(msghdr, id_only); - case RTM_NEWQDISC: - case RTM_DELQDISC: - case RTM_GETQDISC: - return _new_from_nl_qdisc(platform, msghdr, id_only); - case RTM_NEWTFILTER: - case RTM_DELTFILTER: - case RTM_GETTFILTER: - return _new_from_nl_tfilter(msghdr, id_only); - default: - return NULL; - } -} - -/*****************************************************************************/ - -static gboolean -_nl_msg_new_link_set_afspec(struct nl_msg *msg, int addr_gen_mode, NMUtilsIPv6IfaceId *iid) -{ - struct nlattr *af_spec; - struct nlattr *af_attr; - - nm_assert(msg); - - if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) - goto nla_put_failure; - - if (addr_gen_mode >= 0 || iid) { - if (!(af_attr = nla_nest_start(msg, AF_INET6))) - goto nla_put_failure; - - if (addr_gen_mode >= 0) - NLA_PUT_U8(msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode); - - if (iid) { - struct in6_addr i6_token = {.s6_addr = { - 0, - }}; - - nm_utils_ipv6_addr_set_interface_identifier(&i6_token, *iid); - NLA_PUT(msg, IFLA_INET6_TOKEN, sizeof(struct in6_addr), &i6_token); - } - - nla_nest_end(msg, af_attr); - } - - nla_nest_end(msg, af_spec); - - return TRUE; -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -_nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpointer extra_data) -{ - struct nlattr *info; - struct nlattr *data = NULL; - const char * kind; - - nm_assert(msg); - - kind = nm_link_type_to_rtnl_type_string(link_type); - if (!kind) - goto nla_put_failure; - - if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING(msg, IFLA_INFO_KIND, kind); - - switch (link_type) { - case NM_LINK_TYPE_BRIDGE: - { - const NMPlatformLnkBridge *props = extra_data; - - nm_assert(extra_data); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32(msg, IFLA_BR_FORWARD_DELAY, props->forward_delay); - NLA_PUT_U32(msg, IFLA_BR_HELLO_TIME, props->hello_time); - NLA_PUT_U32(msg, IFLA_BR_MAX_AGE, props->max_age); - NLA_PUT_U32(msg, IFLA_BR_AGEING_TIME, props->ageing_time); - NLA_PUT_U32(msg, IFLA_BR_STP_STATE, !!props->stp_state); - NLA_PUT_U16(msg, IFLA_BR_PRIORITY, props->priority); - NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL, htons(props->vlan_protocol)); - if (props->vlan_stats_enabled) - NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED, !!props->vlan_stats_enabled); - NLA_PUT_U16(msg, IFLA_BR_GROUP_FWD_MASK, props->group_fwd_mask); - NLA_PUT(msg, IFLA_BR_GROUP_ADDR, sizeof(props->group_addr), &props->group_addr); - NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, !!props->mcast_snooping); - NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, props->mcast_router); - NLA_PUT_U8(msg, IFLA_BR_MCAST_QUERY_USE_IFADDR, !!props->mcast_query_use_ifaddr); - NLA_PUT_U8(msg, IFLA_BR_MCAST_QUERIER, !!props->mcast_querier); - NLA_PUT_U32(msg, IFLA_BR_MCAST_HASH_MAX, props->mcast_hash_max); - NLA_PUT_U32(msg, IFLA_BR_MCAST_LAST_MEMBER_CNT, props->mcast_last_member_count); - NLA_PUT_U32(msg, IFLA_BR_MCAST_STARTUP_QUERY_CNT, props->mcast_startup_query_count); - NLA_PUT_U64(msg, IFLA_BR_MCAST_LAST_MEMBER_INTVL, props->mcast_last_member_interval); - NLA_PUT_U64(msg, IFLA_BR_MCAST_MEMBERSHIP_INTVL, props->mcast_membership_interval); - NLA_PUT_U64(msg, IFLA_BR_MCAST_QUERIER_INTVL, props->mcast_querier_interval); - NLA_PUT_U64(msg, IFLA_BR_MCAST_QUERY_INTVL, props->mcast_query_interval); - NLA_PUT_U64(msg, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, props->mcast_query_response_interval); - NLA_PUT_U64(msg, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, props->mcast_startup_query_interval); - break; - } - case NM_LINK_TYPE_VLAN: - { - const NMPlatformLnkVlan *props = extra_data; - - nm_assert(extra_data); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U16(msg, IFLA_VLAN_ID, props->id); - - { - struct ifla_vlan_flags flags = { - .flags = props->flags & NM_VLAN_FLAGS_ALL, - .mask = NM_VLAN_FLAGS_ALL, - }; - - NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags); - } - break; - } - case NM_LINK_TYPE_VRF: - { - const NMPlatformLnkVrf *props = extra_data; - - nm_assert(extra_data); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32(msg, IFLA_VRF_TABLE, props->table); - break; - } - case NM_LINK_TYPE_VXLAN: - { - const NMPlatformLnkVxlan *props = extra_data; - - nm_assert(extra_data); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32(msg, IFLA_VXLAN_ID, props->id); - - if (props->group) - NLA_PUT(msg, IFLA_VXLAN_GROUP, sizeof(props->group), &props->group); - else if (!IN6_IS_ADDR_UNSPECIFIED(&props->group6)) - NLA_PUT(msg, IFLA_VXLAN_GROUP6, sizeof(props->group6), &props->group6); - - if (props->local) - NLA_PUT(msg, IFLA_VXLAN_LOCAL, sizeof(props->local), &props->local); - else if (!IN6_IS_ADDR_UNSPECIFIED(&props->local6)) - NLA_PUT(msg, IFLA_VXLAN_LOCAL6, sizeof(props->local6), &props->local6); - - if (props->parent_ifindex >= 0) - NLA_PUT_U32(msg, IFLA_VXLAN_LINK, props->parent_ifindex); - - if (props->src_port_min || props->src_port_max) { - struct nm_ifla_vxlan_port_range port_range = { - .low = htons(props->src_port_min), - .high = htons(props->src_port_max), - }; - - NLA_PUT(msg, IFLA_VXLAN_PORT_RANGE, sizeof(port_range), &port_range); - } - - NLA_PUT_U16(msg, IFLA_VXLAN_PORT, htons(props->dst_port)); - NLA_PUT_U8(msg, IFLA_VXLAN_TOS, props->tos); - NLA_PUT_U8(msg, IFLA_VXLAN_TTL, props->ttl); - NLA_PUT_U32(msg, IFLA_VXLAN_AGEING, props->ageing); - NLA_PUT_U32(msg, IFLA_VXLAN_LIMIT, props->limit); - NLA_PUT_U8(msg, IFLA_VXLAN_LEARNING, !!props->learning); - NLA_PUT_U8(msg, IFLA_VXLAN_PROXY, !!props->proxy); - NLA_PUT_U8(msg, IFLA_VXLAN_RSC, !!props->rsc); - NLA_PUT_U8(msg, IFLA_VXLAN_L2MISS, !!props->l2miss); - NLA_PUT_U8(msg, IFLA_VXLAN_L3MISS, !!props->l3miss); - break; - } - case NM_LINK_TYPE_VETH: - { - const char * veth_peer = extra_data; - const struct ifinfomsg ifi = {}; - struct nlattr * info_peer; - - nm_assert(veth_peer); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - if (!(info_peer = nla_nest_start(msg, 1 /*VETH_INFO_PEER*/))) - goto nla_put_failure; - if (nlmsg_append_struct(msg, &ifi) < 0) - goto nla_put_failure; - NLA_PUT_STRING(msg, IFLA_IFNAME, veth_peer); - nla_nest_end(msg, info_peer); - break; - } - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: - { - const NMPlatformLnkGre *props = extra_data; - - nm_assert(props); - nm_assert(props->is_tap == (link_type == NM_LINK_TYPE_GRETAP)); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32(msg, IFLA_GRE_LINK, props->parent_ifindex); - NLA_PUT_U32(msg, IFLA_GRE_LOCAL, props->local); - NLA_PUT_U32(msg, IFLA_GRE_REMOTE, props->remote); - NLA_PUT_U8(msg, IFLA_GRE_TTL, props->ttl); - NLA_PUT_U8(msg, IFLA_GRE_TOS, props->tos); - NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); - NLA_PUT_U32(msg, IFLA_GRE_IKEY, htonl(props->input_key)); - NLA_PUT_U32(msg, IFLA_GRE_OKEY, htonl(props->output_key)); - NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, htons(props->input_flags)); - NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, htons(props->output_flags)); - break; - } - case NM_LINK_TYPE_SIT: - { - const NMPlatformLnkSit *props = extra_data; - - nm_assert(props); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32(msg, IFLA_IPTUN_LINK, props->parent_ifindex); - NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, props->local); - NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, props->remote); - NLA_PUT_U8(msg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8(msg, IFLA_IPTUN_TOS, props->tos); - NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); - break; - } - case NM_LINK_TYPE_IP6TNL: - { - const NMPlatformLnkIp6Tnl *props = extra_data; - guint32 flowinfo; - - nm_assert(props); - nm_assert(!props->is_gre); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32(msg, IFLA_IPTUN_LINK, props->parent_ifindex); - - if (!IN6_IS_ADDR_UNSPECIFIED(&props->local)) - NLA_PUT(msg, IFLA_IPTUN_LOCAL, sizeof(props->local), &props->local); - if (!IN6_IS_ADDR_UNSPECIFIED(&props->remote)) - NLA_PUT(msg, IFLA_IPTUN_REMOTE, sizeof(props->remote), &props->remote); - - NLA_PUT_U8(msg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8(msg, IFLA_IPTUN_ENCAP_LIMIT, props->encap_limit); - - flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; - flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) & IP6_FLOWINFO_TCLASS_MASK; - NLA_PUT_U32(msg, IFLA_IPTUN_FLOWINFO, htonl(flowinfo)); - NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, props->proto); - NLA_PUT_U32(msg, IFLA_IPTUN_FLAGS, props->flags); - break; - } - case NM_LINK_TYPE_IP6GRE: - case NM_LINK_TYPE_IP6GRETAP: - { - const NMPlatformLnkIp6Tnl *props = extra_data; - guint32 flowinfo; - - nm_assert(props); - nm_assert(props->is_gre); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32(msg, IFLA_GRE_LINK, props->parent_ifindex); - - NLA_PUT_U32(msg, IFLA_GRE_IKEY, htonl(props->input_key)); - NLA_PUT_U32(msg, IFLA_GRE_OKEY, htonl(props->output_key)); - NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, htons(props->input_flags)); - NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, htons(props->output_flags)); - - if (!IN6_IS_ADDR_UNSPECIFIED(&props->local)) - NLA_PUT(msg, IFLA_GRE_LOCAL, sizeof(props->local), &props->local); - if (!IN6_IS_ADDR_UNSPECIFIED(&props->local)) - NLA_PUT(msg, IFLA_GRE_REMOTE, sizeof(props->remote), &props->remote); - - NLA_PUT_U8(msg, IFLA_GRE_TTL, props->ttl); - NLA_PUT_U8(msg, IFLA_GRE_ENCAP_LIMIT, props->encap_limit); - - flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; - flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) & IP6_FLOWINFO_TCLASS_MASK; - NLA_PUT_U32(msg, IFLA_GRE_FLOWINFO, htonl(flowinfo)); - NLA_PUT_U32(msg, IFLA_GRE_FLAGS, props->flags); - break; - } - case NM_LINK_TYPE_IPIP: - { - const NMPlatformLnkIpIp *props = extra_data; - - nm_assert(props); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32(msg, IFLA_IPTUN_LINK, props->parent_ifindex); - NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, props->local); - NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, props->remote); - NLA_PUT_U8(msg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8(msg, IFLA_IPTUN_TOS, props->tos); - NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); - break; - } - case NM_LINK_TYPE_MACSEC: - { - const NMPlatformLnkMacsec *props = extra_data; - - nm_assert(props); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->icv_length) - NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, 16); - if (props->cipher_suite) - NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, props->cipher_suite); - if (props->replay_protect) - NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, props->window); - - NLA_PUT_U64(msg, IFLA_MACSEC_SCI, htobe64(props->sci)); - NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, props->encoding_sa); - NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, props->encrypt); - NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, props->protect); - NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, props->include_sci); - NLA_PUT_U8(msg, IFLA_MACSEC_ES, props->es); - NLA_PUT_U8(msg, IFLA_MACSEC_SCB, props->scb); - NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, props->replay_protect); - NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, props->validation); - break; - }; - case NM_LINK_TYPE_MACVTAP: - case NM_LINK_TYPE_MACVLAN: - { - const NMPlatformLnkMacvlan *props = extra_data; - - nm_assert(props); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, props->mode); - NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, props->no_promisc ? MACVLAN_FLAG_NOPROMISC : 0); - break; - } - default: - nm_assert(!extra_data); - break; - } - - if (data) - nla_nest_end(msg, data); - - nla_nest_end(msg, info); - - return TRUE; -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -_nl_msg_new_link_set_linkinfo_vlan(struct nl_msg * msg, - int vlan_id, - guint32 flags_mask, - guint32 flags_set, - const NMVlanQosMapping *ingress_qos, - int ingress_qos_len, - const NMVlanQosMapping *egress_qos, - int egress_qos_len) -{ - struct nlattr *info; - struct nlattr *data; - guint i; - gboolean has_any_vlan_properties = FALSE; - - G_STATIC_ASSERT(NM_VLAN_FLAG_REORDER_HEADERS == (guint32) VLAN_FLAG_REORDER_HDR); - G_STATIC_ASSERT(NM_VLAN_FLAG_GVRP == (guint32) VLAN_FLAG_GVRP); - G_STATIC_ASSERT(NM_VLAN_FLAG_LOOSE_BINDING == (guint32) VLAN_FLAG_LOOSE_BINDING); - G_STATIC_ASSERT(NM_VLAN_FLAG_MVRP == (guint32) VLAN_FLAG_MVRP); - -#define VLAN_XGRESS_PRIO_VALID(from) (((from) & ~(guint32) 0x07) == 0) - - nm_assert(msg); - - /* We must not create an empty IFLA_LINKINFO section. Otherwise, kernel - * rejects the request as invalid. */ - if (flags_mask != 0 || vlan_id >= 0) - has_any_vlan_properties = TRUE; - if (!has_any_vlan_properties && ingress_qos && ingress_qos_len > 0) { - for (i = 0; i < ingress_qos_len; i++) { - if (VLAN_XGRESS_PRIO_VALID(ingress_qos[i].from)) { - has_any_vlan_properties = TRUE; - break; - } - } - } - if (!has_any_vlan_properties && egress_qos && egress_qos_len > 0) { - for (i = 0; i < egress_qos_len; i++) { - if (VLAN_XGRESS_PRIO_VALID(egress_qos[i].to)) { - has_any_vlan_properties = TRUE; - break; - } - } - } - if (!has_any_vlan_properties) - return TRUE; - - if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); - - if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (vlan_id >= 0) - NLA_PUT_U16(msg, IFLA_VLAN_ID, vlan_id); - - if (flags_mask != 0) { - struct ifla_vlan_flags flags = { - .flags = flags_mask & flags_set, - .mask = flags_mask, - }; - - NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags); - } - - if (ingress_qos && ingress_qos_len > 0) { - struct nlattr *qos = NULL; - - for (i = 0; i < ingress_qos_len; i++) { - /* Silently ignore invalid mappings. Kernel would truncate - * them and modify the wrong mapping. */ - if (VLAN_XGRESS_PRIO_VALID(ingress_qos[i].from)) { - if (!qos) { - if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) - goto nla_put_failure; - } - NLA_PUT(msg, i, sizeof(ingress_qos[i]), &ingress_qos[i]); - } - } - - if (qos) - nla_nest_end(msg, qos); - } - - if (egress_qos && egress_qos_len > 0) { - struct nlattr *qos = NULL; - - for (i = 0; i < egress_qos_len; i++) { - if (VLAN_XGRESS_PRIO_VALID(egress_qos[i].to)) { - if (!qos) { - if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) - goto nla_put_failure; - } - NLA_PUT(msg, i, sizeof(egress_qos[i]), &egress_qos[i]); - } - } - - if (qos) - nla_nest_end(msg, qos); - } - - nla_nest_end(msg, data); - nla_nest_end(msg, info); - - return TRUE; -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static struct nl_msg * -_nl_msg_new_link_full(int nlmsg_type, - int nlmsg_flags, - int ifindex, - const char *ifname, - guint8 family, - unsigned flags_mask, - unsigned flags_set) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - const struct ifinfomsg ifi = { - .ifi_family = family, - .ifi_change = flags_mask, - .ifi_flags = flags_set, - .ifi_index = ifindex, - }; - - nm_assert(NM_IN_SET(nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK, RTM_SETLINK)); - - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); - - if (nlmsg_append_struct(msg, &ifi) < 0) - goto nla_put_failure; - - if (ifname) - NLA_PUT_STRING(msg, IFLA_IFNAME, ifname); - - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static struct nl_msg * -_nl_msg_new_link(int nlmsg_type, int nlmsg_flags, int ifindex, const char *ifname) -{ - return _nl_msg_new_link_full(nlmsg_type, nlmsg_flags, ifindex, ifname, AF_UNSPEC, 0, 0); -} - -/* Copied and modified from libnl3's build_addr_msg(). */ -static struct nl_msg * -_nl_msg_new_address(int nlmsg_type, - int nlmsg_flags, - int family, - int ifindex, - gconstpointer address, - guint8 plen, - gconstpointer peer_address, - guint32 flags, - int scope, - guint32 lifetime, - guint32 preferred, - in_addr_t ip4_broadcast_address, - const char * label) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct ifaddrmsg am = { - .ifa_family = family, - .ifa_index = ifindex, - .ifa_prefixlen = plen, - .ifa_flags = flags, - }; - gsize addr_len; - - 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); - - if (scope == -1) { - /* Allow having scope unset, and detect the scope (including IPv4 compatibility hack). */ - if (family == AF_INET && address && *((char *) address) == 127) - scope = RT_SCOPE_HOST; - else - scope = RT_SCOPE_UNIVERSE; - } - am.ifa_scope = scope, - - addr_len = family == AF_INET ? sizeof(in_addr_t) : sizeof(struct in6_addr); - - if (nlmsg_append_struct(msg, &am) < 0) - goto nla_put_failure; - - if (address) - NLA_PUT(msg, IFA_LOCAL, addr_len, address); - - if (peer_address) - NLA_PUT(msg, IFA_ADDRESS, addr_len, peer_address); - else if (address) - NLA_PUT(msg, IFA_ADDRESS, addr_len, address); - - if (label && label[0]) - NLA_PUT_STRING(msg, IFA_LABEL, label); - - if (ip4_broadcast_address != 0) - NLA_PUT(msg, IFA_BROADCAST, sizeof(in_addr_t), &ip4_broadcast_address); - - if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { - struct ifa_cacheinfo ca = { - .ifa_valid = lifetime, - .ifa_prefered = preferred, - }; - - NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); - } - - if (flags & ~((guint32) 0xFF)) { - /* only set the IFA_FLAGS attribute, if they actually contain additional - * flags that are not already set to am.ifa_flags. - * - * Older kernels refuse RTM_NEWADDR and RTM_NEWROUTE messages with EINVAL - * if they contain unknown netlink attributes. See net/core/rtnetlink.c, which - * was fixed by kernel commit 661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59. */ - NLA_PUT_U32(msg, IFA_FLAGS, flags); - } - - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static guint32 -ip_route_get_lock_flag(const NMPlatformIPRoute *route) -{ - return (((guint32) route->lock_window) << RTAX_WINDOW) - | (((guint32) route->lock_cwnd) << RTAX_CWND) - | (((guint32) route->lock_initcwnd) << RTAX_INITCWND) - | (((guint32) route->lock_initrwnd) << RTAX_INITRWND) - | (((guint32) route->lock_mtu) << RTAX_MTU); -} - -/* Copied and modified from libnl3's build_route_msg() and rtnl_route_build_msg(). */ -static struct nl_msg * -_nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - const NMPClass * klass = NMP_OBJECT_GET_CLASS(obj); - gboolean is_v4 = klass->addr_family == AF_INET; - const guint32 lock = ip_route_get_lock_flag(NMP_OBJECT_CAST_IP_ROUTE(obj)); - const guint32 table = - nm_platform_route_table_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced, TRUE); - const struct rtmsg rtmsg = { - .rtm_family = klass->addr_family, - .rtm_tos = is_v4 ? obj->ip4_route.tos : 0, - .rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC, - .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot(obj->ip_route.rt_source), - .rtm_scope = - is_v4 ? nm_platform_route_scope_inv(obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, - .rtm_type = nm_platform_route_type_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced), - .rtm_flags = obj->ip_route.r_rtm_flags & ((unsigned) (RTNH_F_ONLINK)), - .rtm_dst_len = obj->ip_route.plen, - .rtm_src_len = is_v4 ? 0 : NMP_OBJECT_CAST_IP6_ROUTE(obj)->src_plen, - }; - - gsize addr_len; - - nm_assert( - 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, (int) nlmsgflags); - - if (nlmsg_append_struct(msg, &rtmsg) < 0) - goto nla_put_failure; - - addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); - - NLA_PUT(msg, - RTA_DST, - addr_len, - is_v4 ? (gconstpointer) &obj->ip4_route.network - : (gconstpointer) &obj->ip6_route.network); - - if (!is_v4) { - if (!IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(obj)->src)) - NLA_PUT(msg, RTA_SRC, addr_len, &obj->ip6_route.src); - } - - NLA_PUT_U32(msg, - RTA_PRIORITY, - is_v4 ? nm_platform_ip4_route_get_effective_metric(&obj->ip4_route) - : nm_platform_ip6_route_get_effective_metric(&obj->ip6_route)); - - if (table > 0xFF) - NLA_PUT_U32(msg, RTA_TABLE, table); - - if (is_v4) { - if (NMP_OBJECT_CAST_IP4_ROUTE(obj)->pref_src) - NLA_PUT(msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src); - } else { - if (!IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(obj)->pref_src)) - NLA_PUT(msg, RTA_PREFSRC, addr_len, &obj->ip6_route.pref_src); - } - - if (obj->ip_route.mss || obj->ip_route.window || obj->ip_route.cwnd || obj->ip_route.initcwnd - || obj->ip_route.initrwnd || obj->ip_route.mtu || lock) { - struct nlattr *metrics; - - metrics = nla_nest_start(msg, RTA_METRICS); - if (!metrics) - goto nla_put_failure; - - if (obj->ip_route.mss) - NLA_PUT_U32(msg, RTAX_ADVMSS, obj->ip_route.mss); - if (obj->ip_route.window) - NLA_PUT_U32(msg, RTAX_WINDOW, obj->ip_route.window); - if (obj->ip_route.cwnd) - NLA_PUT_U32(msg, RTAX_CWND, obj->ip_route.cwnd); - if (obj->ip_route.initcwnd) - NLA_PUT_U32(msg, RTAX_INITCWND, obj->ip_route.initcwnd); - if (obj->ip_route.initrwnd) - NLA_PUT_U32(msg, RTAX_INITRWND, obj->ip_route.initrwnd); - if (obj->ip_route.mtu) - NLA_PUT_U32(msg, RTAX_MTU, obj->ip_route.mtu); - if (lock) - NLA_PUT_U32(msg, RTAX_LOCK, lock); - - nla_nest_end(msg, metrics); - } - - /* We currently don't have need for multi-hop routes... */ - if (is_v4) { - NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway); - } else { - if (!IN6_IS_ADDR_UNSPECIFIED(&obj->ip6_route.gateway)) - NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip6_route.gateway); - } - NLA_PUT_U32(msg, RTA_OIF, obj->ip_route.ifindex); - - if (!is_v4 && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM) - NLA_PUT_U8(msg, RTA_PREF, obj->ip6_route.rt_pref); - - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static struct nl_msg * -_nl_msg_new_routing_rule(int nlmsg_type, int nlmsg_flags, const NMPlatformRoutingRule *routing_rule) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - const guint8 addr_size = nm_utils_addr_family_to_size(routing_rule->addr_family); - guint32 table; - - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); - - table = routing_rule->table; - - if (NM_IN_SET(routing_rule->addr_family, AF_INET, AF_INET6) - && routing_rule->action == FR_ACT_TO_TBL && routing_rule->l3mdev == 0 - && table == RT_TABLE_UNSPEC) { - /* for IPv6, this setting is invalid and rejected by kernel. That's fine. - * - * for IPv4, kernel will automatically assign an unused table. That's not - * fine, because we don't know what we will get. - * - * The caller must not allow that to happen. */ - nm_assert_not_reached(); - } - - { - const struct fib_rule_hdr frh = { - .family = routing_rule->addr_family, - .src_len = routing_rule->src_len, - .dst_len = routing_rule->dst_len, - .tos = routing_rule->tos, - .table = table < 0x100u ? (guint8) table : (guint8) RT_TABLE_UNSPEC, - .action = routing_rule->action, - - /* we only allow setting the "not" flag. */ - .flags = routing_rule->flags & ((guint32) FIB_RULE_INVERT), - }; - - if (nlmsg_append_struct(msg, &frh) < 0) - goto nla_put_failure; - } - - if (table > G_MAXINT8) - NLA_PUT_U32(msg, FRA_TABLE, table); - - if (routing_rule->suppress_prefixlen_inverse != 0) - NLA_PUT_U32(msg, FRA_SUPPRESS_PREFIXLEN, ~routing_rule->suppress_prefixlen_inverse); - - if (routing_rule->suppress_ifgroup_inverse != 0) - NLA_PUT_U32(msg, FRA_SUPPRESS_IFGROUP, ~routing_rule->suppress_ifgroup_inverse); - - if (routing_rule->iifname[0] != '\0') - NLA_PUT_STRING(msg, FRA_IIFNAME, routing_rule->iifname); - - if (routing_rule->oifname[0] != '\0') - NLA_PUT_STRING(msg, FRA_OIFNAME, routing_rule->oifname); - - /* we always set the priority and don't support letting kernel pick one. */ - NLA_PUT_U32(msg, FRA_PRIORITY, routing_rule->priority); - - if (routing_rule->fwmark != 0 || routing_rule->fwmask != 0) { - NLA_PUT_U32(msg, FRA_FWMARK, routing_rule->fwmark); - NLA_PUT_U32(msg, FRA_FWMASK, routing_rule->fwmask); - } - - if (routing_rule->src_len > 0) - NLA_PUT(msg, FRA_SRC, addr_size, &routing_rule->src); - - if (routing_rule->dst_len > 0) - NLA_PUT(msg, FRA_DST, addr_size, &routing_rule->dst); - - if (routing_rule->flow != 0) { - /* only relevant for IPv4. */ - NLA_PUT_U32(msg, FRA_FLOW, routing_rule->flow); - } - - if (routing_rule->tun_id != 0) - NLA_PUT_U64(msg, FRA_TUN_ID, htobe64(routing_rule->tun_id)); - - if (routing_rule->l3mdev) - NLA_PUT_U8(msg, FRA_L3MDEV, routing_rule->l3mdev); - - if (routing_rule->protocol != RTPROT_UNSPEC) - NLA_PUT_U8(msg, FRA_PROTOCOL, routing_rule->protocol); - - if (routing_rule->ip_proto != 0) - NLA_PUT_U8(msg, FRA_IP_PROTO, routing_rule->ip_proto); - - if (routing_rule->sport_range.start || routing_rule->sport_range.end) - NLA_PUT(msg, - FRA_SPORT_RANGE, - sizeof(routing_rule->sport_range), - &routing_rule->sport_range); - - if (routing_rule->dport_range.start || routing_rule->dport_range.end) - NLA_PUT(msg, - FRA_DPORT_RANGE, - sizeof(routing_rule->dport_range), - &routing_rule->dport_range); - - if (routing_rule->uid_range_has) - NLA_PUT(msg, FRA_UID_RANGE, sizeof(routing_rule->uid_range), &routing_rule->uid_range); - - switch (routing_rule->action) { - case FR_ACT_GOTO: - NLA_PUT_U32(msg, FRA_GOTO, routing_rule->goto_target); - break; - } - - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static struct nl_msg * -_nl_msg_new_qdisc(int nlmsg_type, int nlmsg_flags, const NMPlatformQdisc *qdisc) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr * tc_options; - const struct tcmsg tcm = { - .tcm_family = qdisc->addr_family, - .tcm_ifindex = qdisc->ifindex, - .tcm_handle = qdisc->handle, - .tcm_parent = qdisc->parent, - .tcm_info = qdisc->info, - }; - - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); - - if (nlmsg_append_struct(msg, &tcm) < 0) - goto nla_put_failure; - - NLA_PUT_STRING(msg, TCA_KIND, qdisc->kind); - - if (nm_streq(qdisc->kind, "sfq")) { - struct tc_sfq_qopt_v1 opt = {}; - - opt.v0.quantum = qdisc->sfq.quantum; - opt.v0.limit = qdisc->sfq.limit; - opt.v0.perturb_period = qdisc->sfq.perturb_period; - opt.v0.flows = qdisc->sfq.flows; - opt.v0.divisor = qdisc->sfq.divisor; - opt.depth = qdisc->sfq.depth; - - NLA_PUT(msg, TCA_OPTIONS, sizeof(opt), &opt); - } else if (nm_streq(qdisc->kind, "tbf")) { - struct tc_tbf_qopt opt = {}; - - if (!(tc_options = nla_nest_start(msg, TCA_OPTIONS))) - goto nla_put_failure; - - opt.rate.rate = (qdisc->tbf.rate >= (1ULL << 32)) ? ~0U : (guint32) qdisc->tbf.rate; - if (qdisc->tbf.limit) - opt.limit = qdisc->tbf.limit; - else if (qdisc->tbf.latency) { - opt.limit = qdisc->tbf.rate * (double) qdisc->tbf.latency / PSCHED_TIME_UNITS_PER_SEC - + qdisc->tbf.burst; - } - - NLA_PUT(msg, TCA_TBF_PARMS, sizeof(opt), &opt); - if (qdisc->tbf.rate >= (1ULL << 32)) - NLA_PUT_U64(msg, TCA_TBF_RATE64, qdisc->tbf.rate); - NLA_PUT_U32(msg, TCA_TBF_BURST, qdisc->tbf.burst); - - nla_nest_end(msg, tc_options); - } else if (nm_streq(qdisc->kind, "prio")) { - struct tc_prio_qopt opt = {3, {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}}; - - NLA_PUT(msg, TCA_OPTIONS, sizeof(opt), &opt); - } else { - if (!(tc_options = nla_nest_start(msg, TCA_OPTIONS))) - goto nla_put_failure; - - if (nm_streq(qdisc->kind, "fq_codel")) { - if (qdisc->fq_codel.limit) - NLA_PUT_U32(msg, TCA_FQ_CODEL_LIMIT, qdisc->fq_codel.limit); - if (qdisc->fq_codel.flows) - NLA_PUT_U32(msg, TCA_FQ_CODEL_FLOWS, qdisc->fq_codel.flows); - if (qdisc->fq_codel.target) - NLA_PUT_U32(msg, TCA_FQ_CODEL_TARGET, qdisc->fq_codel.target); - if (qdisc->fq_codel.interval) - NLA_PUT_U32(msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval); - if (qdisc->fq_codel.quantum) - NLA_PUT_U32(msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); - if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) - NLA_PUT_U32(msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); - if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) - NLA_PUT_U32(msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory_limit); - if (qdisc->fq_codel.ecn) - NLA_PUT_U32(msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); - } - - nla_nest_end(msg, tc_options); - } - - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static struct nl_msg * -_nl_msg_new_tfilter(int nlmsg_type, int nlmsg_flags, const NMPlatformTfilter *tfilter) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr * tc_options; - struct nlattr * act_tab; - const struct tcmsg tcm = { - .tcm_family = tfilter->addr_family, - .tcm_ifindex = tfilter->ifindex, - .tcm_handle = tfilter->handle, - .tcm_parent = tfilter->parent, - .tcm_info = tfilter->info, - }; - - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); - - if (nlmsg_append_struct(msg, &tcm) < 0) - goto nla_put_failure; - - NLA_PUT_STRING(msg, TCA_KIND, tfilter->kind); - - if (!(tc_options = nla_nest_start(msg, TCA_OPTIONS))) - goto nla_put_failure; - - if (!(act_tab = nla_nest_start(msg, TCA_OPTIONS))) // 3 TCA_ACT_KIND TCA_ACT_KIND - goto nla_put_failure; - - if (tfilter->action.kind) { - const NMPlatformAction *action = &tfilter->action; - struct nlattr * prio; - struct nlattr * act_options; - - if (!(prio = nla_nest_start(msg, 1 /* priority */))) - goto nla_put_failure; - - NLA_PUT_STRING(msg, TCA_ACT_KIND, action->kind); - - if (nm_streq(action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - const NMPlatformActionSimple *simple = &action->simple; - struct tc_defact sel = { - 0, - }; - - if (!(act_options = nla_nest_start(msg, TCA_ACT_OPTIONS))) - goto nla_put_failure; - - NLA_PUT(msg, TCA_DEF_PARMS, sizeof(sel), &sel); - NLA_PUT(msg, TCA_DEF_DATA, sizeof(simple->sdata), simple->sdata); - - nla_nest_end(msg, act_options); - - } else if (nm_streq(action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - const NMPlatformActionMirred *mirred = &action->mirred; - struct tc_mirred sel = { - 0, - }; - - if (!(act_options = nla_nest_start(msg, TCA_ACT_OPTIONS))) - goto nla_put_failure; - - if (mirred->egress && mirred->redirect) - sel.eaction = TCA_EGRESS_REDIR; - else if (mirred->egress && mirred->mirror) - sel.eaction = TCA_EGRESS_MIRROR; - else if (mirred->ingress && mirred->redirect) - sel.eaction = TCA_INGRESS_REDIR; - else if (mirred->ingress && mirred->mirror) - sel.eaction = TCA_INGRESS_MIRROR; - sel.ifindex = mirred->ifindex; - - NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(sel), &sel); - - nla_nest_end(msg, act_options); - } - - nla_nest_end(msg, prio); - } - - nla_nest_end(msg, tc_options); - - nla_nest_end(msg, act_tab); - - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -/*****************************************************************************/ - -static struct nl_sock * -_genl_sock(NMLinuxPlatform *platform) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - - return priv->genl; -} - -#define ASSERT_SYSCTL_ARGS(pathid, dirfd, path) \ - G_STMT_START \ - { \ - const char *const _pathid = (pathid); \ - const int _dirfd = (dirfd); \ - const char *const _path = (path); \ - \ - nm_assert(_path &&_path[0]); \ - g_assert(!strstr(_path, "/../")); \ - if (_dirfd < 0) { \ - nm_assert(!_pathid); \ - nm_assert(_path[0] == '/'); \ - nm_assert(g_str_has_prefix(_path, "/proc/sys/") || g_str_has_prefix(_path, "/sys/") \ - || g_str_has_prefix(_path, "/proc/net")); \ - } else { \ - nm_assert(_pathid &&_pathid[0] && _pathid[0] != '/'); \ - nm_assert(_path[0] != '/'); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -/* core sysctl-set functions can be called from a non-main thread. - * Hence, we require locking from nm-logging. Indicate that by - * setting NM_THREAD_SAFE_ON_MAIN_THREAD to zero. */ -#undef NM_THREAD_SAFE_ON_MAIN_THREAD -#define NM_THREAD_SAFE_ON_MAIN_THREAD 0 - -static void -_log_dbg_sysctl_set_impl(NMPlatform *platform, - const char *pathid, - int dirfd, - const char *path, - const char *value) -{ - GError * error = NULL; - gs_free char *contents = NULL; - gs_free char *value_escaped = g_strescape(value, NULL); - - if (!nm_utils_file_get_contents(dirfd, - path, - 1 * 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - NULL, - NULL, - &error)) { - _LOGD("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", - pathid ?: path, - value_escaped, - error->message); - g_clear_error(&error); - return; - } - - g_strstrip(contents); - if (nm_streq(contents, value)) - _LOGD("sysctl: setting '%s' to '%s' (current value is identical)", - pathid ?: path, - value_escaped); - else { - gs_free char *contents_escaped = g_strescape(contents, NULL); - - _LOGD("sysctl: setting '%s' to '%s' (current value is '%s')", - pathid ?: path, - value_escaped, - contents_escaped); - } -} - -#define _log_dbg_sysctl_set(platform, pathid, dirfd, path, value) \ - G_STMT_START \ - { \ - if (_LOGD_ENABLED()) { \ - _log_dbg_sysctl_set_impl(platform, pathid, dirfd, path, value); \ - } \ - } \ - G_STMT_END - -static gboolean -sysctl_set_internal(NMPlatform *platform, - const char *pathid, - int dirfd, - const char *path, - const char *value) -{ - int fd, tries; - gssize nwrote; - gssize len; - char * actual; - gs_free char *actual_free = NULL; - int errsv; - - if (dirfd < 0) { - pathid = path; - - fd = open(path, O_WRONLY | O_TRUNC | O_CLOEXEC); - if (fd == -1) { - errsv = errno; - if (errsv == ENOENT) { - _LOGD("sysctl: failed to open '%s': (%d) %s", - pathid, - errsv, - nm_strerror_native(errsv)); - } else { - _LOGE("sysctl: failed to open '%s': (%d) %s", - pathid, - errsv, - nm_strerror_native(errsv)); - } - errno = errsv; - return FALSE; - } - } else { - fd = openat(dirfd, path, O_WRONLY | O_TRUNC | O_CLOEXEC); - if (fd == -1) { - errsv = errno; - if (errsv == ENOENT) { - _LOGD("sysctl: failed to openat '%s': (%d) %s", - pathid, - errsv, - nm_strerror_native(errsv)); - } else { - _LOGE("sysctl: failed to openat '%s': (%d) %s", - pathid, - errsv, - nm_strerror_native(errsv)); - } - errno = errsv; - return FALSE; - } - } - - _log_dbg_sysctl_set(platform, pathid, dirfd, path, value); - - /* Most sysfs and sysctl options don't care about a trailing LF, while some - * (like infiniband) do. So always add the LF. Also, neither sysfs nor - * sysctl support partial writes so the LF must be added to the string we're - * about to write. - */ - len = strlen(value) + 1; - nm_assert(len > 0); - if (len > 512) - actual = actual_free = g_malloc(len + 1); - else - actual = g_alloca(len + 1); - memcpy(actual, value, len - 1); - actual[len - 1] = '\n'; - actual[len] = '\0'; - - /* Try to write the entire value three times if a partial write occurs */ - errsv = 0; - for (tries = 0, nwrote = 0; tries < 3 && nwrote < len - 1; tries++) { - nwrote = write(fd, actual, len); - if (nwrote == -1) { - errsv = errno; - if (errsv == EINTR) { - _LOGD("sysctl: interrupted, will try again"); - continue; - } - break; - } - } - if (nwrote == -1) { - NMLogLevel level = LOGL_ERR; - - if (errsv == EEXIST) { - level = LOGL_DEBUG; - } else if (errsv == EINVAL - && nm_utils_sysctl_ip_conf_is_path(AF_INET6, path, NULL, "mtu")) { - /* setting the MTU can fail under regular conditions. Suppress - * logging a warning. */ - level = LOGL_DEBUG; - } - - _NMLOG(level, - "sysctl: failed to set '%s' to '%s': (%d) %s", - path, - value, - errsv, - nm_strerror_native(errsv)); - } else if (nwrote < len - 1) { - _LOGE("sysctl: failed to set '%s' to '%s' after three attempts", path, value); - } - - if (nwrote < len - 1) { - if (nm_close(fd) != 0) { - if (errsv != 0) - errno = errsv; - } else if (errsv != 0) - errno = errsv; - else - errno = EIO; - return FALSE; - } - if (nm_close(fd) != 0) { - /* errno is already properly set. */ - return FALSE; - } - - /* success. errno is undefined (no need to set). */ - return TRUE; -} - -#undef NM_THREAD_SAFE_ON_MAIN_THREAD -#define NM_THREAD_SAFE_ON_MAIN_THREAD 1 - -/*****************************************************************************/ - -static gboolean -sysctl_set(NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - - g_return_val_if_fail(path, FALSE); - g_return_val_if_fail(value, FALSE); - - ASSERT_SYSCTL_ARGS(pathid, dirfd, path); - - if (dirfd < 0 && !nm_platform_netns_push(platform, &netns)) { - errno = ENETDOWN; - return FALSE; - } - - return sysctl_set_internal(platform, pathid, dirfd, path, value); -} - -typedef struct { - NMPlatform * platform; - char * pathid; - int dirfd; - char * path; - char ** values; - GCancellable * cancellable; - NMPlatformAsyncCallback callback; - gpointer callback_data; -} SysctlAsyncInfo; - -static void -sysctl_async_info_free(SysctlAsyncInfo *info) -{ - g_object_unref(info->platform); - g_free(info->pathid); - if (info->dirfd >= 0) - nm_close(info->dirfd); - g_free(info->path); - g_strfreev(info->values); - g_object_unref(info->cancellable); - g_slice_free(SysctlAsyncInfo, info); -} - -static void -sysctl_async_cb(GObject *object, GAsyncResult *res, gpointer user_data) -{ - NMPlatform * platform; - GTask * task = G_TASK(res); - SysctlAsyncInfo *info; - gs_free_error GError *error = NULL; - gs_free char * values_str = NULL; - - info = g_task_get_task_data(task); - - if (g_task_propagate_boolean(task, &error)) { - platform = info->platform; - _LOGD("sysctl: successfully set-async '%s' to values '%s'", - info->pathid ?: info->path, - (values_str = g_strjoinv(", ", info->values))); - } - - if (info->callback) - info->callback(error, info->callback_data); -} - -static void -sysctl_async_thread_fn(GTask * task, - gpointer source_object, - gpointer task_data, - GCancellable *cancellable) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - SysctlAsyncInfo * info = task_data; - GError * error = NULL; - char ** value; - - if (g_task_return_error_if_cancelled(task)) - return; - - if (info->dirfd < 0 && !nm_platform_netns_push(info->platform, &netns)) { - g_set_error_literal(&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "sysctl: failed changing namespace"); - g_task_return_error(task, error); - return; - } - - for (value = info->values; *value; value++) { - if (!sysctl_set_internal(info->platform, info->pathid, info->dirfd, info->path, *value)) { - g_set_error(&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "sysctl: failed setting '%s' to value '%s': %s", - info->pathid ?: info->path, - *value, - nm_strerror_native(errno)); - g_task_return_error(task, error); - return; - } - if (g_task_return_error_if_cancelled(task)) - return; - } - g_task_return_boolean(task, TRUE); -} - -static void -sysctl_set_async_return_idle(gpointer user_data, GCancellable *cancellable) -{ - gs_unref_object NMPlatform *platform = NULL; - gs_free_error GError *cancelled_error = NULL; - gs_free_error GError * error = NULL; - NMPlatformAsyncCallback callback; - gpointer callback_data; - - nm_utils_user_data_unpack(user_data, &platform, &callback, &callback_data, &error); - g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); - callback(cancelled_error ?: error, callback_data); -} - -static void -sysctl_set_async(NMPlatform * platform, - const char * pathid, - int dirfd, - const char * path, - const char *const * values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable * cancellable) -{ - SysctlAsyncInfo *info; - GTask * task; - int dirfd_dup, errsv; - gpointer packed; - GError * error = NULL; - - g_return_if_fail(platform); - g_return_if_fail(path); - g_return_if_fail(values && values[0]); - g_return_if_fail(cancellable); - g_return_if_fail(!data || callback); - - ASSERT_SYSCTL_ARGS(pathid, dirfd, path); - - if (dirfd >= 0) { - dirfd_dup = fcntl(dirfd, F_DUPFD_CLOEXEC, 0); - if (dirfd_dup < 0) { - if (!callback) - return; - errsv = errno; - g_set_error(&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "sysctl: failure duplicating directory fd: %s", - nm_strerror_native(errsv)); - packed = nm_utils_user_data_pack(g_object_ref(platform), callback, data, error); - nm_utils_invoke_on_idle(cancellable, sysctl_set_async_return_idle, packed); - return; - } - } else - dirfd_dup = -1; - - info = g_slice_new0(SysctlAsyncInfo); - info->platform = g_object_ref(platform); - info->pathid = g_strdup(pathid); - info->dirfd = dirfd_dup; - info->path = g_strdup(path); - info->values = g_strdupv((char **) values); - info->callback = callback; - info->callback_data = data; - info->cancellable = g_object_ref(cancellable); - - task = g_task_new(platform, cancellable, sysctl_async_cb, NULL); - g_task_set_task_data(task, info, (GDestroyNotify) sysctl_async_info_free); - g_task_set_return_on_cancel(task, FALSE); - g_task_run_in_thread(task, sysctl_async_thread_fn); - g_object_unref(task); -} - -static GSList *sysctl_clear_cache_list; - -void -_nm_logging_clear_platform_logging_cache(void) -{ - while (sysctl_clear_cache_list) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(sysctl_clear_cache_list->data); - - sysctl_clear_cache_list = - g_slist_delete_link(sysctl_clear_cache_list, sysctl_clear_cache_list); - - g_hash_table_destroy(priv->sysctl_get_prev_values); - priv->sysctl_get_prev_values = NULL; - } -} - -typedef struct { - const char *path; - CList lst; - char * value; - char path_data[]; -} SysctlCacheEntry; - -static void -sysctl_cache_entry_free(SysctlCacheEntry *entry) -{ - c_list_unlink_stale(&entry->lst); - g_free(entry->value); - g_free(entry); -} - -static void -_log_dbg_sysctl_get_impl(NMPlatform *platform, const char *pathid, const char *contents) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - SysctlCacheEntry * entry = NULL; - - if (!priv->sysctl_get_prev_values) { - sysctl_clear_cache_list = g_slist_prepend(sysctl_clear_cache_list, platform); - c_list_init(&priv->sysctl_list); - priv->sysctl_get_prev_values = - g_hash_table_new_full(nm_pstr_hash, - nm_pstr_equal, - (GDestroyNotify) sysctl_cache_entry_free, - NULL); - } else - entry = g_hash_table_lookup(priv->sysctl_get_prev_values, &pathid); - - if (entry) { - if (!nm_streq(entry->value, contents)) { - gs_free char *contents_escaped = g_strescape(contents, NULL); - gs_free char *prev_value_escaped = g_strescape(entry->value, NULL); - - _LOGD("sysctl: reading '%s': '%s' (changed from '%s' on last read)", - pathid, - contents_escaped, - prev_value_escaped); - g_free(entry->value); - entry->value = g_strdup(contents); - } - nm_c_list_move_front(&priv->sysctl_list, &entry->lst); - } else { - gs_free char * contents_escaped = g_strescape(contents, NULL); - SysctlCacheEntry *old; - size_t len; - - len = strlen(pathid); - entry = g_malloc(sizeof(SysctlCacheEntry) + len + 1); - entry->value = g_strdup(contents); - entry->path = entry->path_data; - memcpy(entry->path_data, pathid, len + 1); - - /* Remove oldest entry when the cache becomes too big */ - if (g_hash_table_size(priv->sysctl_get_prev_values) > 1000) { - old = c_list_last_entry(&priv->sysctl_list, SysctlCacheEntry, lst); - g_hash_table_remove(priv->sysctl_get_prev_values, old); - } - - _LOGD("sysctl: reading '%s': '%s'", pathid, contents_escaped); - - g_hash_table_add(priv->sysctl_get_prev_values, entry); - c_list_link_front(&priv->sysctl_list, &entry->lst); - } -} - -#define _log_dbg_sysctl_get(platform, pathid, contents) \ - G_STMT_START \ - { \ - if (_LOGD_ENABLED()) \ - _log_dbg_sysctl_get_impl(platform, pathid, contents); \ - } \ - G_STMT_END - -static char * -sysctl_get(NMPlatform *platform, const char *pathid, int dirfd, const char *path) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - GError * error = NULL; - gs_free char * contents = NULL; - - ASSERT_SYSCTL_ARGS(pathid, dirfd, path); - - if (dirfd < 0) { - if (!nm_platform_netns_push(platform, &netns)) { - errno = EBUSY; - return NULL; - } - pathid = path; - } - - if (!nm_utils_file_get_contents(dirfd, - path, - 1 * 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - NULL, - NULL, - &error)) { - NMLogLevel log_level = LOGL_ERR; - int errsv = EBUSY; - - if (g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { - errsv = ENOENT; - log_level = LOGL_DEBUG; - } else if (g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NODEV) - || g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_FAILED)) { - /* We assume FAILED means EOPNOTSUP and don't log a error message. */ - log_level = LOGL_DEBUG; - } - - _NMLOG(log_level, "error reading %s: %s", pathid, error->message); - g_clear_error(&error); - errno = errsv; - return NULL; - } - - g_strstrip(contents); - - _log_dbg_sysctl_get(platform, pathid, contents); - - /* errno is left undefined (as we don't return NULL). */ - return g_steal_pointer(&contents); -} - -/*****************************************************************************/ - -static void -process_events(NMPlatform *platform) -{ - delayed_action_handle_all(platform, TRUE); -} - -/*****************************************************************************/ - -static const RefreshAllInfo * -refresh_all_type_get_info(RefreshAllType refresh_all_type) -{ - static const RefreshAllInfo infos[] = { -#define R(_refresh_all_type, _obj_type, _addr_family) \ - [_refresh_all_type] = { \ - .obj_type = _obj_type, \ - .addr_family = _addr_family, \ - } - R(REFRESH_ALL_TYPE_LINKS, NMP_OBJECT_TYPE_LINK, AF_UNSPEC), - R(REFRESH_ALL_TYPE_IP4_ADDRESSES, NMP_OBJECT_TYPE_IP4_ADDRESS, AF_UNSPEC), - R(REFRESH_ALL_TYPE_IP6_ADDRESSES, NMP_OBJECT_TYPE_IP6_ADDRESS, AF_UNSPEC), - R(REFRESH_ALL_TYPE_IP4_ROUTES, NMP_OBJECT_TYPE_IP4_ROUTE, AF_UNSPEC), - R(REFRESH_ALL_TYPE_IP6_ROUTES, NMP_OBJECT_TYPE_IP6_ROUTE, AF_UNSPEC), - R(REFRESH_ALL_TYPE_ROUTING_RULES_IP4, NMP_OBJECT_TYPE_ROUTING_RULE, AF_INET), - R(REFRESH_ALL_TYPE_ROUTING_RULES_IP6, NMP_OBJECT_TYPE_ROUTING_RULE, AF_INET6), - R(REFRESH_ALL_TYPE_QDISCS, NMP_OBJECT_TYPE_QDISC, AF_UNSPEC), - R(REFRESH_ALL_TYPE_TFILTERS, NMP_OBJECT_TYPE_TFILTER, AF_UNSPEC), -#undef R - }; - - nm_assert(_NM_INT_NOT_NEGATIVE(refresh_all_type)); - nm_assert(refresh_all_type < G_N_ELEMENTS(infos)); - nm_assert(nmp_class_from_type(infos[refresh_all_type].obj_type)); - - return &infos[refresh_all_type]; -} - -static NM_UTILS_LOOKUP_DEFINE( - delayed_action_type_to_refresh_all_type, - DelayedActionType, - RefreshAllType, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(0), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, REFRESH_ALL_TYPE_LINKS), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, - REFRESH_ALL_TYPE_IP4_ADDRESSES), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, - REFRESH_ALL_TYPE_IP6_ADDRESSES), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, REFRESH_ALL_TYPE_IP4_ROUTES), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, REFRESH_ALL_TYPE_IP6_ROUTES), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4, - REFRESH_ALL_TYPE_ROUTING_RULES_IP4), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, - REFRESH_ALL_TYPE_ROUTING_RULES_IP6), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS, REFRESH_ALL_TYPE_QDISCS), - NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, REFRESH_ALL_TYPE_TFILTERS), - NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), ); - -static DelayedActionType -delayed_action_type_from_refresh_all_type(RefreshAllType refresh_all_type) -{ - DelayedActionType t; - - nm_assert(refresh_all_type_get_info(refresh_all_type)); - - t = (((DelayedActionType) 1) << refresh_all_type); - - nm_assert(refresh_all_type == delayed_action_type_to_refresh_all_type(t)); - - return t; -} - -static RefreshAllType -refresh_all_type_from_needle_object(const NMPObject *obj_needle) -{ - switch (NMP_OBJECT_GET_TYPE(obj_needle)) { - case NMP_OBJECT_TYPE_LINK: - return REFRESH_ALL_TYPE_LINKS; - case NMP_OBJECT_TYPE_IP4_ADDRESS: - return REFRESH_ALL_TYPE_IP4_ADDRESSES; - case NMP_OBJECT_TYPE_IP6_ADDRESS: - return REFRESH_ALL_TYPE_IP6_ADDRESSES; - case NMP_OBJECT_TYPE_IP4_ROUTE: - return REFRESH_ALL_TYPE_IP4_ROUTES; - case NMP_OBJECT_TYPE_IP6_ROUTE: - return REFRESH_ALL_TYPE_IP6_ROUTES; - case NMP_OBJECT_TYPE_QDISC: - return REFRESH_ALL_TYPE_QDISCS; - case NMP_OBJECT_TYPE_TFILTER: - return REFRESH_ALL_TYPE_TFILTERS; - case NMP_OBJECT_TYPE_ROUTING_RULE: - switch (NMP_OBJECT_CAST_ROUTING_RULE(obj_needle)->addr_family) { - case AF_INET: - return REFRESH_ALL_TYPE_ROUTING_RULES_IP4; - case AF_INET6: - return REFRESH_ALL_TYPE_ROUTING_RULES_IP6; - } - nm_assert_not_reached(); - return 0; - default: - nm_assert_not_reached(); - return 0; - } -} - -static const NMPLookup * -refresh_all_type_init_lookup(RefreshAllType refresh_all_type, NMPLookup *lookup) -{ - const RefreshAllInfo *refresh_all_info; - - nm_assert(lookup); - - refresh_all_info = refresh_all_type_get_info(refresh_all_type); - - nm_assert(refresh_all_info); - - if (NM_IN_SET(refresh_all_info->obj_type, NMP_OBJECT_TYPE_ROUTING_RULE)) { - return nmp_lookup_init_object_by_addr_family(lookup, - refresh_all_info->obj_type, - refresh_all_info->addr_family); - } - - /* not yet implemented. */ - nm_assert(refresh_all_info->addr_family == AF_UNSPEC); - - return nmp_lookup_init_obj_type(lookup, refresh_all_info->obj_type); -} - -static DelayedActionType -delayed_action_refresh_from_needle_object(const NMPObject *obj_needle) -{ - return delayed_action_type_from_refresh_all_type( - refresh_all_type_from_needle_object(obj_needle)); -} - -static NM_UTILS_LOOKUP_STR_DEFINE( - delayed_action_to_string, - DelayedActionType, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, "refresh-all-links"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, - "refresh-all-ip4-addresses"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, - "refresh-all-ip6-addresses"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, "refresh-all-ip4-routes"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, "refresh-all-ip6-routes"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4, - "refresh-all-routing-rules-ip4"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, - "refresh-all-routing-rules-ip6"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS, "refresh-all-qdiscs"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, "refresh-all-tfilters"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_LINK, "refresh-link"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_MASTER_CONNECTED, "master-connected"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_READ_NETLINK, "read-netlink"), - NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, "wait-for-nl-response"), - NM_UTILS_LOOKUP_ITEM_IGNORE(DELAYED_ACTION_TYPE_NONE), - NM_UTILS_LOOKUP_ITEM_IGNORE(DELAYED_ACTION_TYPE_REFRESH_ALL), - NM_UTILS_LOOKUP_ITEM_IGNORE(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL), - NM_UTILS_LOOKUP_ITEM_IGNORE(__DELAYED_ACTION_TYPE_MAX), ); - -static const char * -delayed_action_to_string_full(DelayedActionType action_type, - gpointer user_data, - char * buf, - gsize buf_size) -{ - char * buf0 = buf; - const DelayedActionWaitForNlResponseData *data; - - nm_utils_strbuf_append_str(&buf, &buf_size, delayed_action_to_string(action_type)); - switch (action_type) { - case DELAYED_ACTION_TYPE_MASTER_CONNECTED: - nm_utils_strbuf_append(&buf, &buf_size, " (master-ifindex %d)", GPOINTER_TO_INT(user_data)); - break; - case DELAYED_ACTION_TYPE_REFRESH_LINK: - nm_utils_strbuf_append(&buf, &buf_size, " (ifindex %d)", GPOINTER_TO_INT(user_data)); - break; - case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE: - data = user_data; - - if (data) { - gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_nsec(); - char b[255]; - - nm_utils_strbuf_append( - &buf, - &buf_size, - " (seq %u, timeout in %s%" G_GINT64_FORMAT ".%09" G_GINT64_FORMAT - ", response-type %d%s%s)", - data->seq_number, - timeout < 0 ? "-" : "", - (timeout < 0 ? -timeout : timeout) / NM_UTILS_NSEC_PER_SEC, - (timeout < 0 ? -timeout : timeout) % NM_UTILS_NSEC_PER_SEC, - (int) data->response_type, - data->seq_result ? ", " : "", - data->seq_result - ? wait_for_nl_response_to_string(data->seq_result, NULL, b, sizeof(b)) - : ""); - } else - nm_utils_strbuf_append_str(&buf, &buf_size, " (any)"); - break; - default: - nm_assert(!user_data); - break; - } - return buf0; -} - -#define _LOGt_delayed_action(action_type, user_data, operation) \ - G_STMT_START \ - { \ - char _buf[255]; \ - \ - _LOGt("delayed-action: %s %s", \ - "" operation, \ - delayed_action_to_string_full(action_type, user_data, _buf, sizeof(_buf))); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static gboolean -delayed_action_refresh_all_in_progress(NMPlatform *platform, DelayedActionType action_type) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - RefreshAllType refresh_all_type; - - nm_assert(nm_utils_is_power_of_two(action_type)); - nm_assert(NM_FLAGS_ANY(action_type, DELAYED_ACTION_TYPE_REFRESH_ALL)); - nm_assert(!NM_FLAGS_ANY(action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL)); - - if (NM_FLAGS_ANY(priv->delayed_action.flags, action_type)) - return TRUE; - - refresh_all_type = delayed_action_type_to_refresh_all_type(action_type); - return (priv->delayed_action.refresh_all_in_progress[refresh_all_type] > 0); -} - -static void -delayed_action_wait_for_nl_response_complete(NMPlatform * platform, - guint idx, - WaitForNlResponseResult seq_result) -{ - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - DelayedActionWaitForNlResponseData *data; - - nm_assert(NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); - nm_assert(idx < priv->delayed_action.list_wait_for_nl_response->len); - nm_assert(seq_result); - - data = &g_array_index(priv->delayed_action.list_wait_for_nl_response, - DelayedActionWaitForNlResponseData, - idx); - - _LOGt_delayed_action(DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, data, "complete"); - - if (priv->delayed_action.list_wait_for_nl_response->len <= 1) - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE; - if (data->out_seq_result) - *data->out_seq_result = seq_result; - switch (data->response_type) { - case DELAYED_ACTION_RESPONSE_TYPE_VOID: - break; - case DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS: - if (data->response.out_refresh_all_in_progress) { - nm_assert(*data->response.out_refresh_all_in_progress > 0); - *data->response.out_refresh_all_in_progress -= 1; - data->response.out_refresh_all_in_progress = NULL; - } - break; - case DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET: - if (data->response.out_route_get) { - nm_assert(!*data->response.out_route_get); - data->response.out_route_get = NULL; - } - break; - } - - g_array_remove_index_fast(priv->delayed_action.list_wait_for_nl_response, idx); -} - -static void -delayed_action_wait_for_nl_response_complete_check(NMPlatform * platform, - WaitForNlResponseResult force_result, - guint32 * out_next_seq_number, - gint64 * out_next_timeout_abs_ns, - gint64 * p_now_ns) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - guint i; - guint32 next_seq_number = 0; - gint64 next_timeout_abs_ns = 0; - int now_ns = 0; - - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len;) { - const DelayedActionWaitForNlResponseData *data = - &g_array_index(priv->delayed_action.list_wait_for_nl_response, - DelayedActionWaitForNlResponseData, - i); - - if (data->seq_result) - delayed_action_wait_for_nl_response_complete(platform, i, data->seq_result); - else if (p_now_ns - && ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_nsec())) - >= data->timeout_abs_ns)) { - /* the caller can optionally check for timeout by providing a p_now_ns argument. */ - delayed_action_wait_for_nl_response_complete( - platform, - i, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT); - } else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) - delayed_action_wait_for_nl_response_complete(platform, i, force_result); - else { - if (next_seq_number == 0 || next_timeout_abs_ns > data->timeout_abs_ns) { - next_seq_number = data->seq_number; - next_timeout_abs_ns = data->timeout_abs_ns; - } - i++; - } - } - - if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) { - nm_assert( - !NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); - nm_assert(priv->delayed_action.list_wait_for_nl_response->len == 0); - } - - NM_SET_OUT(out_next_seq_number, next_seq_number); - NM_SET_OUT(out_next_timeout_abs_ns, next_timeout_abs_ns); - NM_SET_OUT(p_now_ns, now_ns); -} - -static void -delayed_action_wait_for_nl_response_complete_all(NMPlatform * platform, - WaitForNlResponseResult fallback_result) -{ - delayed_action_wait_for_nl_response_complete_check(platform, fallback_result, NULL, NULL, NULL); -} - -/*****************************************************************************/ - -static void -delayed_action_handle_MASTER_CONNECTED(NMPlatform *platform, int master_ifindex) -{ - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - NMPCacheOpsType cache_op; - - cache_op = nmp_cache_update_link_master_connected(nm_platform_get_cache(platform), - master_ifindex, - &obj_old, - &obj_new); - if (cache_op == NMP_CACHE_OPS_UNCHANGED) - return; - cache_on_change(platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); -} - -static void -delayed_action_handle_REFRESH_LINK(NMPlatform *platform, int ifindex) -{ - do_request_link_no_delayed_actions(platform, ifindex, NULL); -} - -static void -delayed_action_handle_REFRESH_ALL(NMPlatform *platform, DelayedActionType flags) -{ - do_request_all_no_delayed_actions(platform, flags); -} - -static void -delayed_action_handle_READ_NETLINK(NMPlatform *platform) -{ - event_handler_read_netlink(platform, FALSE); -} - -static void -delayed_action_handle_WAIT_FOR_NL_RESPONSE(NMPlatform *platform) -{ - event_handler_read_netlink(platform, TRUE); -} - -static gboolean -delayed_action_handle_one(NMPlatform *platform) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - gpointer user_data; - - if (priv->delayed_action.flags == DELAYED_ACTION_TYPE_NONE) - return FALSE; - - /* First process DELAYED_ACTION_TYPE_MASTER_CONNECTED actions. - * This type of action is entirely cache-internal and is here to resolve a - * cache inconsistency. It should be fixed right away. */ - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_MASTER_CONNECTED)) { - nm_assert(priv->delayed_action.list_master_connected->len > 0); - - user_data = priv->delayed_action.list_master_connected->pdata[0]; - g_ptr_array_remove_index_fast(priv->delayed_action.list_master_connected, 0); - if (priv->delayed_action.list_master_connected->len == 0) - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_MASTER_CONNECTED; - nm_assert(_nm_utils_ptrarray_find_first( - (gconstpointer *) priv->delayed_action.list_master_connected->pdata, - priv->delayed_action.list_master_connected->len, - user_data) - < 0); - - _LOGt_delayed_action(DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle"); - delayed_action_handle_MASTER_CONNECTED(platform, GPOINTER_TO_INT(user_data)); - return TRUE; - } - nm_assert(priv->delayed_action.list_master_connected->len == 0); - - /* Next we prefer read-netlink, because the buffer size is limited and we want to process events - * from netlink early. */ - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_READ_NETLINK)) { - _LOGt_delayed_action(DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle"); - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_READ_NETLINK; - delayed_action_handle_READ_NETLINK(platform); - return TRUE; - } - - if (NM_FLAGS_ANY(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_ALL)) { - DelayedActionType flags, iflags; - - flags = priv->delayed_action.flags & DELAYED_ACTION_TYPE_REFRESH_ALL; - - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL; - - if (_LOGt_ENABLED()) { - FOR_EACH_DELAYED_ACTION(iflags, flags) - _LOGt_delayed_action(iflags, NULL, "handle"); - } - - delayed_action_handle_REFRESH_ALL(platform, flags); - return TRUE; - } - - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) { - nm_assert(priv->delayed_action.list_refresh_link->len > 0); - - user_data = priv->delayed_action.list_refresh_link->pdata[0]; - g_ptr_array_remove_index_fast(priv->delayed_action.list_refresh_link, 0); - if (priv->delayed_action.list_refresh_link->len == 0) - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; - nm_assert(_nm_utils_ptrarray_find_first( - (gconstpointer *) priv->delayed_action.list_refresh_link->pdata, - priv->delayed_action.list_refresh_link->len, - user_data) - < 0); - - _LOGt_delayed_action(DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle"); - - delayed_action_handle_REFRESH_LINK(platform, GPOINTER_TO_INT(user_data)); - - return TRUE; - } - - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); - _LOGt_delayed_action(DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, NULL, "handle"); - delayed_action_handle_WAIT_FOR_NL_RESPONSE(platform); - return TRUE; - } - - return FALSE; -} - -static gboolean -delayed_action_handle_all(NMPlatform *platform, gboolean read_netlink) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - gboolean any = FALSE; - - g_return_val_if_fail(priv->delayed_action.is_handling == 0, FALSE); - - priv->delayed_action.is_handling++; - if (read_netlink) - delayed_action_schedule(platform, DELAYED_ACTION_TYPE_READ_NETLINK, NULL); - while (delayed_action_handle_one(platform)) - any = TRUE; - priv->delayed_action.is_handling--; - - cache_prune_all(platform); - - return any; -} - -static void -delayed_action_schedule(NMPlatform *platform, DelayedActionType action_type, gpointer user_data) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - DelayedActionType iflags; - - nm_assert(action_type != DELAYED_ACTION_TYPE_NONE); - - switch (action_type) { - case DELAYED_ACTION_TYPE_REFRESH_LINK: - if (_nm_utils_ptrarray_find_first( - (gconstpointer *) priv->delayed_action.list_refresh_link->pdata, - priv->delayed_action.list_refresh_link->len, - user_data) - < 0) - g_ptr_array_add(priv->delayed_action.list_refresh_link, user_data); - break; - case DELAYED_ACTION_TYPE_MASTER_CONNECTED: - if (_nm_utils_ptrarray_find_first( - (gconstpointer *) priv->delayed_action.list_master_connected->pdata, - priv->delayed_action.list_master_connected->len, - user_data) - < 0) - g_ptr_array_add(priv->delayed_action.list_master_connected, user_data); - break; - case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE: - g_array_append_vals(priv->delayed_action.list_wait_for_nl_response, user_data, 1); - break; - default: - nm_assert(!user_data); - nm_assert(!NM_FLAGS_HAS(action_type, DELAYED_ACTION_TYPE_REFRESH_LINK)); - nm_assert(!NM_FLAGS_HAS(action_type, DELAYED_ACTION_TYPE_MASTER_CONNECTED)); - nm_assert(!NM_FLAGS_HAS(action_type, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); - break; - } - - priv->delayed_action.flags |= action_type; - - if (_LOGt_ENABLED()) { - FOR_EACH_DELAYED_ACTION(iflags, action_type) - _LOGt_delayed_action(iflags, user_data, "schedule"); - } -} - -static void -delayed_action_schedule_WAIT_FOR_NL_RESPONSE(NMPlatform * platform, - guint32 seq_number, - WaitForNlResponseResult * out_seq_result, - char ** out_errmsg, - DelayedActionWaitForNlResponseType response_type, - gpointer response_out_data) -{ - DelayedActionWaitForNlResponseData data = { - .seq_number = seq_number, - .timeout_abs_ns = - nm_utils_get_monotonic_timestamp_nsec() + (200 * (NM_UTILS_NSEC_PER_SEC / 1000)), - .out_seq_result = out_seq_result, - .out_errmsg = out_errmsg, - .response_type = response_type, - .response.out_data = response_out_data, - }; - - delayed_action_schedule(platform, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, &data); -} - -/*****************************************************************************/ - -static void -cache_prune_one_type(NMPlatform *platform, const NMPLookup *lookup) -{ - NMDedupMultiIter iter; - const NMPObject *obj; - NMPCacheOpsType cache_op; - NMPCache * cache = nm_platform_get_cache(platform); - - nm_dedup_multi_iter_init(&iter, nmp_cache_lookup(cache, lookup)); - while (nm_dedup_multi_iter_next(&iter)) { - const NMDedupMultiEntry *main_entry; - - /* we only track the dirty flag for the OBJECT-TYPE index. That means, - * for other lookup types we need to check the dirty flag of the main-entry. */ - main_entry = nmp_cache_reresolve_main_entry(cache, iter.current, lookup); - if (!main_entry->dirty) - continue; - - obj = main_entry->obj; - - _LOGt("cache-prune: prune %s", - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); - - { - nm_auto_nmpobj const NMPObject *obj_old = NULL; - - cache_op = nmp_cache_remove(cache, obj, TRUE, TRUE, &obj_old); - nm_assert(cache_op == NMP_CACHE_OPS_REMOVED); - cache_on_change(platform, cache_op, obj_old, NULL); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, NULL); - } - } -} - -static void -cache_prune_all(NMPlatform *platform) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - RefreshAllType refresh_all_type; - - for (refresh_all_type = _REFRESH_ALL_TYPE_FIRST; refresh_all_type < _REFRESH_ALL_TYPE_NUM; - refresh_all_type++) { - NMPLookup lookup; - - if (priv->pruning[refresh_all_type] == 0) - continue; - priv->pruning[refresh_all_type] -= 1; - if (priv->pruning[refresh_all_type] > 0) - continue; - refresh_all_type_init_lookup(refresh_all_type, &lookup); - cache_prune_one_type(platform, &lookup); - } -} - -static void -cache_on_change(NMPlatform * platform, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new) -{ - const NMPClass *klass; - char str_buf[sizeof(_nm_utils_to_string_buffer)]; - char str_buf2[sizeof(_nm_utils_to_string_buffer)]; - NMPCache * cache = nm_platform_get_cache(platform); - - ASSERT_nmp_cache_ops(cache, cache_op, obj_old, obj_new); - nm_assert(cache_op != NMP_CACHE_OPS_UNCHANGED); - - klass = obj_old ? NMP_OBJECT_GET_CLASS(obj_old) : NMP_OBJECT_GET_CLASS(obj_new); - - _LOGt( - "update-cache-%s: %s: %s%s%s", - klass->obj_type_name, - (cache_op == NMP_CACHE_OPS_UPDATED ? "UPDATE" - : (cache_op == NMP_CACHE_OPS_REMOVED ? "REMOVE" - : (cache_op == NMP_CACHE_OPS_ADDED) ? "ADD" - : "???")), - (cache_op != NMP_CACHE_OPS_ADDED - ? nmp_object_to_string(obj_old, NMP_OBJECT_TO_STRING_ALL, str_buf2, sizeof(str_buf2)) - : nmp_object_to_string(obj_new, NMP_OBJECT_TO_STRING_ALL, str_buf2, sizeof(str_buf2))), - (cache_op == NMP_CACHE_OPS_UPDATED) ? " -> " : "", - (cache_op == NMP_CACHE_OPS_UPDATED - ? nmp_object_to_string(obj_new, NMP_OBJECT_TO_STRING_ALL, str_buf, sizeof(str_buf)) - : "")); - - switch (klass->obj_type) { - case NMP_OBJECT_TYPE_LINK: - { - /* check whether changing a slave link can cause a master link (bridge or bond) to go up/down */ - if (obj_old - && nmp_cache_link_connected_needs_toggle_by_ifindex(cache, - obj_old->link.master, - obj_new, - obj_old)) - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_MASTER_CONNECTED, - GINT_TO_POINTER(obj_old->link.master)); - if (obj_new && (!obj_old || obj_old->link.master != obj_new->link.master) - && nmp_cache_link_connected_needs_toggle_by_ifindex(cache, - obj_new->link.master, - obj_new, - obj_old)) - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_MASTER_CONNECTED, - GINT_TO_POINTER(obj_new->link.master)); - } - { - /* check whether we are about to change a master link that needs toggling connected state. */ - if (obj_new /* <-- nonsensical, make coverity happy */ - && nmp_cache_link_connected_needs_toggle(cache, obj_new, obj_new, obj_old)) - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_MASTER_CONNECTED, - GINT_TO_POINTER(obj_new->link.ifindex)); - } - { - int ifindex = 0; - - /* if we remove a link (from netlink), we must refresh the addresses, routes, qdiscs and tfilters */ - if (cache_op == NMP_CACHE_OPS_REMOVED - && obj_old /* <-- nonsensical, make coverity happy */) - ifindex = obj_old->link.ifindex; - else if (cache_op == NMP_CACHE_OPS_UPDATED && obj_old - && obj_new /* <-- nonsensical, make coverity happy */ - && !obj_new->_link.netlink.is_in_netlink - && obj_new->_link.netlink.is_in_netlink - != obj_old->_link.netlink.is_in_netlink) - ifindex = obj_new->link.ifindex; - - if (ifindex > 0) { - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL - | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS - | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - NULL); - } - } - { - int ifindex = -1; - - /* removal of a link could be caused by moving the link to another netns. - * In this case, we potentially have to update other links that have this link as parent. - * Currently, kernel misses to sent us a notification in this case - * (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */ - - if (cache_op == NMP_CACHE_OPS_REMOVED - && obj_old /* <-- nonsensical, make coverity happy */ - && obj_old->_link.netlink.is_in_netlink) - ifindex = obj_old->link.ifindex; - else if (cache_op == NMP_CACHE_OPS_UPDATED && obj_old - && obj_new /* <-- nonsensical, make coverity happy */ - && obj_old->_link.netlink.is_in_netlink - && !obj_new->_link.netlink.is_in_netlink) - ifindex = obj_new->link.ifindex; - - if (ifindex > 0) { - NMPLookup lookup; - NMDedupMultiIter iter; - const NMPlatformLink *l; - - nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); - nmp_cache_iter_for_each_link (&iter, nmp_cache_lookup(cache, &lookup), &l) { - if (l->parent == ifindex) - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER(l->ifindex)); - } - } - } - { - /* if a link goes down, we must refresh routes */ - if (cache_op == NMP_CACHE_OPS_UPDATED && obj_old - && obj_new /* <-- nonsensical, make coverity happy */ - && obj_old->_link.netlink.is_in_netlink && obj_new->_link.netlink.is_in_netlink - && ((NM_FLAGS_HAS(obj_old->link.n_ifi_flags, IFF_UP) - && !NM_FLAGS_HAS(obj_new->link.n_ifi_flags, IFF_UP)) - || (NM_FLAGS_HAS(obj_old->link.n_ifi_flags, IFF_LOWER_UP) - && !NM_FLAGS_HAS(obj_new->link.n_ifi_flags, IFF_LOWER_UP)))) { - /* FIXME: I suspect that IFF_LOWER_UP must not be considered, and I - * think kernel does send RTM_DELROUTE events for IPv6 routes, so - * we might not need to refresh IPv6 routes. */ - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, - NULL); - } - } - if (NM_IN_SET(cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED) - && (obj_new && obj_new->_link.netlink.is_in_netlink) - && (!obj_old || !obj_old->_link.netlink.is_in_netlink)) { - gboolean re_request_link = FALSE; - const NMPlatformLnkTun *lnk_tun; - - if (!obj_new->_link.netlink.lnk - && NM_IN_SET(obj_new->link.type, - NM_LINK_TYPE_GRE, - NM_LINK_TYPE_GRETAP, - NM_LINK_TYPE_IP6TNL, - NM_LINK_TYPE_IP6GRE, - NM_LINK_TYPE_IP6GRETAP, - NM_LINK_TYPE_INFINIBAND, - NM_LINK_TYPE_MACVLAN, - NM_LINK_TYPE_MACVLAN, - NM_LINK_TYPE_SIT, - NM_LINK_TYPE_TUN, - NM_LINK_TYPE_VLAN, - NM_LINK_TYPE_VXLAN)) { - /* certain link-types also come with a IFLA_INFO_DATA/lnk_data. It may happen that - * kernel didn't send this notification, thus when we first learn about a link - * that lacks an lnk_data we re-request it again. - * - * For example https://bugzilla.redhat.com/show_bug.cgi?id=1284001 */ - re_request_link = TRUE; - } else if (obj_new->link.type == NM_LINK_TYPE_TUN && obj_new->_link.netlink.lnk - && (lnk_tun = &(obj_new->_link.netlink.lnk)->lnk_tun) && !lnk_tun->persist - && lnk_tun->pi && !lnk_tun->vnet_hdr && !lnk_tun->multi_queue - && !lnk_tun->owner_valid && !lnk_tun->group_valid) { - /* kernel has/had a know issue that the first notification for TUN device would - * be sent with invalid parameters. The message looks like that kind, so refetch - * it. */ - re_request_link = TRUE; - } else if (obj_new->link.type == NM_LINK_TYPE_VETH && obj_new->link.parent == 0) { - /* the initial notification when adding a veth pair can lack the parent/IFLA_LINK - * (https://bugzilla.redhat.com/show_bug.cgi?id=1285827). - * Request it again. */ - re_request_link = TRUE; - } else if (obj_new->link.type == NM_LINK_TYPE_ETHERNET - && obj_new->link.l_address.len == 0) { - /* Due to a kernel bug, we sometimes receive spurious NEWLINK - * messages after a wifi interface has disappeared. Since the - * link is not present anymore we can't determine its type and - * thus it will show up as a Ethernet one, with no address - * specified. Request the link again to check if it really - * exists. https://bugzilla.redhat.com/show_bug.cgi?id=1302037 - */ - re_request_link = TRUE; - } - if (re_request_link) { - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER(obj_new->link.ifindex)); - } - } - { - /* on enslave/release, we also refresh the master. */ - int ifindex1 = 0, ifindex2 = 0; - gboolean changed_master, changed_connected; - - changed_master = - (obj_new && obj_new->_link.netlink.is_in_netlink && obj_new->link.master > 0 - ? obj_new->link.master - : 0) - != (obj_old && obj_old->_link.netlink.is_in_netlink && obj_old->link.master > 0 - ? obj_old->link.master - : 0); - changed_connected = (obj_new && obj_new->_link.netlink.is_in_netlink - ? NM_FLAGS_HAS(obj_new->link.n_ifi_flags, IFF_LOWER_UP) - : 2) - != (obj_old && obj_old->_link.netlink.is_in_netlink - ? NM_FLAGS_HAS(obj_old->link.n_ifi_flags, IFF_LOWER_UP) - : 2); - - if (changed_master || changed_connected) { - ifindex1 = - (obj_old && obj_old->_link.netlink.is_in_netlink && obj_old->link.master > 0) - ? obj_old->link.master - : 0; - ifindex2 = - (obj_new && obj_new->_link.netlink.is_in_netlink && obj_new->link.master > 0) - ? obj_new->link.master - : 0; - - if (ifindex1 > 0) - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER(ifindex1)); - if (ifindex2 > 0 && ifindex1 != ifindex2) - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER(ifindex2)); - } - } - break; - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - { - /* Address deletion is sometimes accompanied by route deletion. We need to - * check all routes belonging to the same interface. */ - if (cache_op == NMP_CACHE_OPS_REMOVED) { - delayed_action_schedule(platform, - (klass->obj_type == NMP_OBJECT_TYPE_IP4_ADDRESS) - ? DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - : DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, - NULL); - } - } break; - default: - break; - } -} - -/*****************************************************************************/ - -static guint32 -_nlh_seq_next_get(NMLinuxPlatformPrivate *priv) -{ - /* generate a new sequence number, but never return zero. - * Wrapping numbers are not a problem, because we don't rely - * on strictly increasing sequence numbers. */ - return (++priv->nlh_seq_next) ?: (++priv->nlh_seq_next); -} - -/** - * _nl_send_nlmsghdr: - * @platform: - * @nlhdr: - * @out_seq_result: - * @response_type: - * @response_out_data: - * - * Returns: 0 on success or a negative errno. - */ -static int -_nl_send_nlmsghdr(NMPlatform * platform, - struct nlmsghdr * nlhdr, - WaitForNlResponseResult * out_seq_result, - char ** out_errmsg, - DelayedActionWaitForNlResponseType response_type, - gpointer response_out_data) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - guint32 seq; - int errsv; - - nm_assert(nlhdr); - - seq = _nlh_seq_next_get(priv); - nlhdr->nlmsg_seq = seq; - - { - struct sockaddr_nl nladdr = { - .nl_family = AF_NETLINK, - }; - struct iovec iov = {.iov_base = nlhdr, .iov_len = nlhdr->nlmsg_len}; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - int try_count; - - if (!nlhdr->nlmsg_pid) - nlhdr->nlmsg_pid = nl_socket_get_local_port(priv->nlh); - nlhdr->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK); - - try_count = 0; -again: - errsv = sendmsg(nl_socket_get_fd(priv->nlh), &msg, 0); - if (errsv < 0) { - errsv = errno; - if (errsv == EINTR && try_count++ < 100) - goto again; - _LOGD("netlink: nl-send-nlmsghdr: failed sending message: %s (%d)", - nm_strerror_native(errsv), - errsv); - return -nm_errno_from_native(errsv); - } - } - - delayed_action_schedule_WAIT_FOR_NL_RESPONSE(platform, - seq, - out_seq_result, - out_errmsg, - response_type, - response_out_data); - return 0; -} - -/** - * _nl_send_nlmsg: - * @platform: - * @nlmsg: - * @out_seq_result: - * @response_type: - * @response_out_data: - * - * Returns: 0 on success, or a negative libnl3 error code (beware, it's not an errno). - */ -static int -_nl_send_nlmsg(NMPlatform * platform, - struct nl_msg * nlmsg, - WaitForNlResponseResult * out_seq_result, - char ** out_errmsg, - DelayedActionWaitForNlResponseType response_type, - gpointer response_out_data) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - struct nlmsghdr * nlhdr; - guint32 seq; - int nle; - - nlhdr = nlmsg_hdr(nlmsg); - seq = _nlh_seq_next_get(priv); - nlhdr->nlmsg_seq = seq; - - nle = nl_send_auto(priv->nlh, nlmsg); - if (nle < 0) { - _LOGD("netlink: nl-send-nlmsg: failed sending message: %s (%d)", nm_strerror(nle), nle); - return nle; - } - - delayed_action_schedule_WAIT_FOR_NL_RESPONSE(platform, - seq, - out_seq_result, - out_errmsg, - response_type, - response_out_data); - return 0; -} - -static void -do_request_link_no_delayed_actions(NMPlatform *platform, int ifindex, const char *name) -{ - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int nle; - - if (name && !name[0]) - name = NULL; - - g_return_if_fail(ifindex > 0 || name); - - _LOGD("do-request-link: %d %s", ifindex, name ?: ""); - - if (ifindex > 0) { - const NMDedupMultiEntry *entry; - - entry = nmp_cache_lookup_entry_link(nm_platform_get_cache(platform), ifindex); - if (entry) { - priv->pruning[REFRESH_ALL_TYPE_LINKS] += 1; - nm_dedup_multi_entry_set_dirty(entry, TRUE); - } - } - - event_handler_read_netlink(platform, FALSE); - - nlmsg = _nl_msg_new_link(RTM_GETLINK, 0, ifindex, name); - if (nlmsg) { - nle = _nl_send_nlmsg(platform, nlmsg, NULL, NULL, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE("do-request-link: %d %s: failed sending netlink request \"%s\" (%d)", - ifindex, - name ?: "", - nm_strerror(nle), - -nle); - return; - } - } -} - -static void -do_request_link(NMPlatform *platform, int ifindex, const char *name) -{ - do_request_link_no_delayed_actions(platform, ifindex, name); - delayed_action_handle_all(platform, FALSE); -} - -static struct nl_msg * -_nl_msg_new_dump(NMPObjectType obj_type, int preferred_addr_family) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const NMPClass * klass; - - klass = nmp_class_from_type(obj_type); - - nm_assert(klass); - nm_assert(klass->rtm_gettype > 0); - - nlmsg = nlmsg_alloc_simple(klass->rtm_gettype, NLM_F_DUMP); - - if (klass->addr_family != AF_UNSPEC) { - /* if the class specifies a particular address family, then it is preferred. */ - nm_assert(NM_IN_SET(preferred_addr_family, AF_UNSPEC, klass->addr_family)); - preferred_addr_family = klass->addr_family; - } - - switch (klass->obj_type) { - case NMP_OBJECT_TYPE_QDISC: - case NMP_OBJECT_TYPE_TFILTER: - { - const struct tcmsg tcmsg = { - .tcm_family = preferred_addr_family, - }; - - if (nlmsg_append_struct(nlmsg, &tcmsg) < 0) - g_return_val_if_reached(NULL); - } break; - case NMP_OBJECT_TYPE_LINK: - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - case NMP_OBJECT_TYPE_ROUTING_RULE: - { - const struct rtgenmsg gmsg = { - .rtgen_family = preferred_addr_family, - }; - - if (nlmsg_append_struct(nlmsg, &gmsg) < 0) - g_return_val_if_reached(NULL); - } break; - default: - g_return_val_if_reached(NULL); - } - - return g_steal_pointer(&nlmsg); -} - -static void -do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action_type) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - DelayedActionType action_type_prune; - DelayedActionType iflags; - - nm_assert(!NM_FLAGS_ANY(action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL)); - action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL; - - action_type_prune = action_type; - - /* calling nmp_cache_dirty_set_all_main() with a non-main lookup-index requires an extra - * cache lookup for every entry. - * - * Avoid that, by special casing routing-rules here. */ - if (NM_FLAGS_ALL(action_type_prune, DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL)) { - NMPLookup lookup; - - priv->pruning[REFRESH_ALL_TYPE_ROUTING_RULES_IP4] += 1; - priv->pruning[REFRESH_ALL_TYPE_ROUTING_RULES_IP6] += 1; - nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - nmp_cache_dirty_set_all_main(nm_platform_get_cache(platform), &lookup); - action_type_prune &= ~DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL; - } - - FOR_EACH_DELAYED_ACTION(iflags, action_type_prune) - { - RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type(iflags); - NMPLookup lookup; - - priv->pruning[refresh_all_type] += 1; - refresh_all_type_init_lookup(refresh_all_type, &lookup); - nmp_cache_dirty_set_all_main(nm_platform_get_cache(platform), &lookup); - } - - FOR_EACH_DELAYED_ACTION(iflags, action_type) - { - RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type(iflags); - const RefreshAllInfo *refresh_all_info = refresh_all_type_get_info(refresh_all_type); - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int * out_refresh_all_in_progress; - - out_refresh_all_in_progress = - &priv->delayed_action.refresh_all_in_progress[refresh_all_type]; - nm_assert(*out_refresh_all_in_progress >= 0); - *out_refresh_all_in_progress += 1; - - /* clear any delayed action that request a refresh of this object type. */ - priv->delayed_action.flags &= ~iflags; - _LOGt_delayed_action(iflags, NULL, "handle (do-request-all)"); - - if (refresh_all_type == REFRESH_ALL_TYPE_LINKS) { - nm_assert( - (priv->delayed_action.list_refresh_link->len > 0) - == NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)); - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) { - _LOGt_delayed_action(DELAYED_ACTION_TYPE_REFRESH_LINK, - NULL, - "clear (do-request-all)"); - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; - g_ptr_array_set_size(priv->delayed_action.list_refresh_link, 0); - } - } - - event_handler_read_netlink(platform, FALSE); - - nlmsg = _nl_msg_new_dump(refresh_all_info->obj_type, refresh_all_info->addr_family); - if (!nlmsg) - goto next_after_fail; - - if (_nl_send_nlmsg(platform, - nlmsg, - NULL, - NULL, - DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS, - out_refresh_all_in_progress) - < 0) - goto next_after_fail; - - continue; - -next_after_fail: - nm_assert(*out_refresh_all_in_progress > 0); - *out_refresh_all_in_progress -= 1; - } -} - -static void -do_request_one_type_by_needle_object(NMPlatform *platform, const NMPObject *obj_needle) -{ - do_request_all_no_delayed_actions(platform, - delayed_action_refresh_from_needle_object(obj_needle)); - delayed_action_handle_all(platform, FALSE); -} - -static void -event_seq_check_refresh_all(NMPlatform *platform, guint32 seq_number) -{ - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - DelayedActionWaitForNlResponseData *data; - guint i; - - if (NM_IN_SET(seq_number, 0, priv->nlh_seq_last_seen)) - return; - - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); - - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { - data = &g_array_index(priv->delayed_action.list_wait_for_nl_response, - DelayedActionWaitForNlResponseData, - i); - - if (data->response_type == DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS - && data->response.out_refresh_all_in_progress - && data->seq_number == priv->nlh_seq_last_seen) { - *data->response.out_refresh_all_in_progress -= 1; - data->response.out_refresh_all_in_progress = NULL; - break; - } - } - } - - priv->nlh_seq_last_seen = seq_number; -} - -static void -event_seq_check(NMPlatform * platform, - guint32 seq_number, - WaitForNlResponseResult seq_result, - const char * msg) -{ - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - DelayedActionWaitForNlResponseData *data; - guint i; - - if (seq_number == 0) - return; - - if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); - - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { - data = &g_array_index(priv->delayed_action.list_wait_for_nl_response, - DelayedActionWaitForNlResponseData, - i); - - if (data->seq_number == seq_number) { - /* We potentially receive many parts partial responses for the same sequence number. - * Thus, we only remember the result, and collect it later. */ - if (data->seq_result < 0) { - /* we already saw an error for this sequence number. - * Preserve it. */ - } else if (seq_result != WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN - || data->seq_result == WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) - data->seq_result = seq_result; - if (data->out_errmsg && !*data->out_errmsg) - *data->out_errmsg = g_strdup(msg); - return; - } - } - } - -#if NM_MORE_LOGGING - if (seq_number != priv->nlh_seq_last_handled) - _LOGt("netlink: recvmsg: unwaited sequence number %u", seq_number); - priv->nlh_seq_last_handled = seq_number; -#endif -} - -static void -event_valid_msg(NMPlatform *platform, struct nl_msg *msg, gboolean handle_events) -{ - NMLinuxPlatformPrivate *priv; - nm_auto_nmpobj NMPObject *obj = NULL; - NMPCacheOpsType cache_op; - struct nlmsghdr * msghdr; - char buf_nlmsghdr[400]; - gboolean is_del = FALSE; - gboolean is_dump = FALSE; - NMPCache * cache = nm_platform_get_cache(platform); - - msghdr = nlmsg_hdr(msg); - - if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) - && msghdr->nlmsg_type == RTM_NEWADDR) { - /* IFA_FLAGS is set for IPv4 and IPv6 addresses. It was added first to IPv6, - * but if we encounter an IPv4 address with IFA_FLAGS, we surely have support. */ - if (nlmsg_valid_hdr(msghdr, sizeof(struct ifaddrmsg)) - && NM_IN_SET(((struct ifaddrmsg *) nlmsg_data(msghdr))->ifa_family, - AF_INET, - AF_INET6)) { - /* see if the nl_msg contains the IFA_FLAGS attribute. If it does, - * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR - * and IFA_F_NOPREFIXROUTE for IPv6. They were added together in kernel 3.14, - * dated 30 March, 2014. - * - * For IPv4, IFA_F_NOPREFIXROUTE was added later, but there is no easy - * way to detect kernel support. */ - _nm_platform_kernel_support_init( - NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS, - !!nlmsg_find_attr(msghdr, sizeof(struct ifaddrmsg), IFA_FLAGS) ? 1 : -1); - } - } - - if (!handle_events) - return; - - if (NM_IN_SET(msghdr->nlmsg_type, - RTM_DELLINK, - RTM_DELADDR, - RTM_DELROUTE, - RTM_DELRULE, - RTM_DELQDISC, - RTM_DELTFILTER)) { - /* The event notifies about a deleted object. We don't need to initialize all - * fields of the object. */ - is_del = TRUE; - } - - obj = nmp_object_new_from_nl(platform, cache, msg, is_del); - if (!obj) { - _LOGT("event-notification: %s: ignore", - nl_nlmsghdr_to_str(msghdr, buf_nlmsghdr, sizeof(buf_nlmsghdr))); - return; - } - - if (!is_del - && NM_IN_SET(msghdr->nlmsg_type, - RTM_NEWADDR, - RTM_NEWLINK, - RTM_NEWROUTE, - RTM_NEWRULE, - RTM_NEWQDISC, - RTM_NEWTFILTER)) { - is_dump = - delayed_action_refresh_all_in_progress(platform, - delayed_action_refresh_from_needle_object(obj)); - } - - _LOGT("event-notification: %s%s: %s", - nl_nlmsghdr_to_str(msghdr, buf_nlmsghdr, sizeof(buf_nlmsghdr)), - is_dump ? ", in-dump" : "", - nmp_object_to_string(obj, - is_del ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC, - NULL, - 0)); - - { - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - - switch (msghdr->nlmsg_type) { - case RTM_GETLINK: - case RTM_NEWADDR: - case RTM_NEWLINK: - case RTM_NEWQDISC: - case RTM_NEWRULE: - case RTM_NEWTFILTER: - cache_op = nmp_cache_update_netlink(cache, obj, is_dump, &obj_old, &obj_new); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - cache_on_change(platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); - } - break; - - case RTM_NEWROUTE: - { - nm_auto_nmpobj const NMPObject *obj_replace = NULL; - gboolean resync_required = FALSE; - gboolean only_dirty = FALSE; - gboolean is_ipv6; - - /* IPv4 routes that are a response to RTM_GETROUTE must have - * the cloned flag while IPv6 routes don't have to. */ - is_ipv6 = NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP6_ROUTE; - if (is_ipv6 || NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, RTM_F_CLONED)) { - nm_assert(is_ipv6 || !nmp_object_is_alive(obj)); - priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - if (NM_FLAGS_HAS(priv->delayed_action.flags, - DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - guint i; - - nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { - DelayedActionWaitForNlResponseData *data = - &g_array_index(priv->delayed_action.list_wait_for_nl_response, - DelayedActionWaitForNlResponseData, - i); - - if (data->response_type == DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET - && data->response.out_route_get) { - nm_assert(!*data->response.out_route_get); - if (data->seq_number == nlmsg_hdr(msg)->nlmsg_seq) { - *data->response.out_route_get = nmp_object_clone(obj, FALSE); - data->response.out_route_get = NULL; - break; - } - } - } - } - } - - cache_op = nmp_cache_update_netlink_route(cache, - obj, - is_dump, - msghdr->nlmsg_flags, - &obj_old, - &obj_new, - &obj_replace, - &resync_required); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - if (obj_replace) { - const NMDedupMultiEntry *entry_replace; - - /* we found an object that is to be replaced by the RTM_NEWROUTE message. - * While we invoke the signal, the platform cache might change and invalidate - * the findings. Mitigate that (for the most part), by marking the entry as - * dirty and only delete @obj_replace if it is still dirty afterwards. - * - * Yes, there is a tiny tiny chance for still getting it wrong. But in practice, - * the signal handlers do not cause to call the platform again, so the cache - * is not really changing. -- if they would, it would anyway be dangerous to overflow - * the stack and it's not ensured that the processing of netlink messages is - * reentrant (maybe it is). - */ - entry_replace = nmp_cache_lookup_entry(cache, obj_replace); - nm_assert(entry_replace && entry_replace->obj == obj_replace); - nm_dedup_multi_entry_set_dirty(entry_replace, TRUE); - only_dirty = TRUE; - } - cache_on_change(platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); - } - - if (obj_replace) { - /* the RTM_NEWROUTE message indicates that another route was replaced. - * Remove it now. */ - cache_op = nmp_cache_remove(cache, obj_replace, TRUE, only_dirty, NULL); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - nm_assert(cache_op == NMP_CACHE_OPS_REMOVED); - cache_on_change(platform, cache_op, obj_replace, NULL); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_replace, NULL); - } - } - - if (resync_required) { - /* we'd like to avoid such resyncs as they are expensive and we should only rely on the - * netlink events. This needs investigation. */ - _LOGT("schedule resync of routes after RTM_NEWROUTE"); - delayed_action_schedule(platform, - delayed_action_refresh_from_needle_object(obj), - NULL); - } - break; - } - - case RTM_DELADDR: - case RTM_DELLINK: - case RTM_DELQDISC: - case RTM_DELROUTE: - case RTM_DELRULE: - case RTM_DELTFILTER: - cache_op = nmp_cache_remove_netlink(cache, obj, &obj_old, &obj_new); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - cache_on_change(platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); - } - break; - default: - break; - } - } -} - -/*****************************************************************************/ - -static int -do_add_link_with_lookup(NMPlatform * platform, - NMLinkType link_type, - const char * name, - struct nl_msg * nlmsg, - const NMPlatformLink **out_link) -{ - const NMPObject * obj = NULL; - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; - int nle; - char s_buf[256]; - NMPCache * cache = nm_platform_get_cache(platform); - - event_handler_read_netlink(platform, FALSE); - - nle = _nl_send_nlmsg(platform, - nlmsg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - _LOGE("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)", - name, - nm_link_type_to_string(link_type), - nm_strerror(nle), - -nle); - NM_SET_OUT(out_link, NULL); - return nle; - } - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, - "do-add-link[%s/%s]: %s", - name, - nm_link_type_to_string(link_type), - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - - if (out_link) { - obj = nmp_cache_lookup_link_full(cache, 0, name, FALSE, link_type, NULL, NULL); - *out_link = NMP_OBJECT_CAST_LINK(obj); - } - - return wait_for_nl_response_to_nmerr(seq_result); -} - -static int -do_add_addrroute(NMPlatform * platform, - const NMPObject *obj_id, - struct nl_msg * nlmsg, - gboolean suppress_netlink_failure) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; - int nle; - char s_buf[256]; - - nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - - event_handler_read_netlink(platform, FALSE); - - nle = _nl_send_nlmsg(platform, - nlmsg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - _LOGE("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)", - NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, - nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - nm_strerror(nle), - -nle); - return -NME_PL_NETLINK; - } - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - _NMLOG((seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK - || (suppress_netlink_failure && seq_result < 0)) - ? LOGL_DEBUG - : LOGL_WARN, - "do-add-%s[%s]: %s", - NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, - nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - - if (NMP_OBJECT_GET_TYPE(obj_id) == NMP_OBJECT_TYPE_IP6_ADDRESS) { - /* In rare cases, the object is not yet ready as we received the ACK from - * kernel. Need to refetch. - * - * We want to safe the expensive refetch, thus we look first into the cache - * whether the object exists. - * - * rh#1484434 */ - if (!nmp_cache_lookup_obj(nm_platform_get_cache(platform), obj_id)) - do_request_one_type_by_needle_object(platform, obj_id); - } - - return wait_for_nl_response_to_nmerr(seq_result); -} - -static gboolean -do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *nlmsg) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; - int nle; - char s_buf[256]; - gboolean success; - const char * log_detail = ""; - - event_handler_read_netlink(platform, FALSE); - - nle = _nl_send_nlmsg(platform, - nlmsg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - _LOGE("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)", - NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, - nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - nm_strerror(nle), - -nle); - return FALSE; - } - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - success = TRUE; - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { - /* ok */ - } else if (NM_IN_SET(-((int) seq_result), ESRCH, ENOENT)) - log_detail = ", meaning the object was already removed"; - else if (NM_IN_SET(-((int) seq_result), ENXIO) - && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), NMP_OBJECT_TYPE_IP6_ADDRESS)) { - /* On RHEL7 kernel, deleting a non existing address fails with ENXIO */ - log_detail = ", meaning the address was already removed"; - } else if (NM_IN_SET(-((int) seq_result), EADDRNOTAVAIL) - && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS)) - log_detail = ", meaning the address was already removed"; - else - success = FALSE; - - _NMLOG(success ? LOGL_DEBUG : LOGL_WARN, - "do-delete-%s[%s]: %s%s", - NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, - nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)), - log_detail); - - if (NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER)) { - /* In rare cases, the object is still there after we receive the ACK from - * kernel. Need to refetch. - * - * We want to safe the expensive refetch, thus we look first into the cache - * whether the object exists. - * - * rh#1484434 */ - if (nmp_cache_lookup_obj(nm_platform_get_cache(platform), obj_id)) - do_request_one_type_by_needle_object(platform, obj_id); - } - - return success; -} - -static int -do_change_link(NMPlatform * platform, - ChangeLinkType change_link_type, - int ifindex, - struct nl_msg * nlmsg, - const ChangeLinkData *data) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - int nle; - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; - char s_buf[256]; - int result = 0; - NMLogLevel log_level = LOGL_DEBUG; - const char * log_result = "failure"; - const char * log_detail = ""; - gs_free char * log_detail_free = NULL; - const NMPObject * obj_cache; - - if (!nm_platform_netns_push(platform, &netns)) { - log_level = LOGL_ERR; - log_detail = ", failure to change network namespace"; - goto out; - } - -retry: - nle = _nl_send_nlmsg(platform, - nlmsg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - log_level = LOGL_ERR; - log_detail_free = - g_strdup_printf(", failure sending netlink request: %s (%d)", nm_strerror(nle), -nle); - log_detail = log_detail_free; - goto out; - } - - /* always refetch the link after changing it. There seems to be issues - * and we sometimes lack events. Nuke it from the orbit... */ - delayed_action_schedule(platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER(ifindex)); - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - if (NM_IN_SET(-((int) seq_result), EOPNOTSUPP) && nlmsg_hdr(nlmsg)->nlmsg_type == RTM_NEWLINK) { - nlmsg_hdr(nlmsg)->nlmsg_type = RTM_SETLINK; - goto retry; - } - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { - log_result = "success"; - } else if (NM_IN_SET(-((int) seq_result), EEXIST, EADDRINUSE)) { - /* */ - } else if (NM_IN_SET(-((int) seq_result), ESRCH, ENOENT)) { - log_detail = ", firmware not found"; - result = -NME_PL_NO_FIRMWARE; - } else if (NM_IN_SET(-((int) seq_result), ERANGE) - && change_link_type == CHANGE_LINK_TYPE_SET_MTU) { - log_detail = ", setting MTU to requested size is not possible"; - result = -NME_PL_CANT_SET_MTU; - } else if (NM_IN_SET(-((int) seq_result), ENFILE) - && change_link_type == CHANGE_LINK_TYPE_SET_ADDRESS - && (obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex)) - && obj_cache->link.l_address.len == data->set_address.length - && memcmp(obj_cache->link.l_address.data, - data->set_address.address, - data->set_address.length) - == 0) { - /* workaround ENFILE which may be wrongly returned (bgo #770456). - * If the MAC address is as expected, assume success? */ - log_result = "success"; - log_detail = " (assume success changing address)"; - result = 0; - } else if (NM_IN_SET(-((int) seq_result), ENODEV)) { - log_level = LOGL_DEBUG; - result = -NME_PL_NOT_FOUND; - } else if (-((int) seq_result) == EAFNOSUPPORT) { - log_level = LOGL_DEBUG; - result = -NME_PL_OPNOTSUPP; - } else { - log_level = LOGL_WARN; - result = -NME_UNSPEC; - } - -out: - _NMLOG(log_level, - "do-change-link[%d]: %s changing link: %s%s", - ifindex, - log_result, - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)), - log_detail); - return result; -} - -static int -link_add(NMPlatform * platform, - NMLinkType type, - const char * name, - int parent, - const void * address, - size_t address_len, - guint32 mtu, - gconstpointer extra_data, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - if (type == NM_LINK_TYPE_BOND) { - /* When the kernel loads the bond module, either via explicit modprobe - * or automatically in response to creating a bond master, it will also - * create a 'bond0' interface. Since the bond we're about to create may - * or may not be named 'bond0' prevent potential confusion about a bond - * that the user didn't want by telling the bonding module not to create - * bond0 automatically. - */ - if (!g_file_test("/sys/class/net/bonding_masters", G_FILE_TEST_EXISTS)) - (void) nm_utils_modprobe(NULL, TRUE, "bonding", "max_bonds=0", NULL); - } - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, name); - if (!nlmsg) - return -NME_UNSPEC; - - if (parent > 0) - NLA_PUT_U32(nlmsg, IFLA_LINK, parent); - - if (address && address_len) - NLA_PUT(nlmsg, IFLA_ADDRESS, address_len, address); - - if (mtu) - NLA_PUT_U32(nlmsg, IFLA_MTU, mtu); - - if (!_nl_msg_new_link_set_linkinfo(nlmsg, type, extra_data)) - return -NME_UNSPEC; - - return do_add_link_with_lookup(platform, type, name, nlmsg, out_link); -nla_put_failure: - g_return_val_if_reached(-NME_BUG); -} - -static gboolean -link_delete(NMPlatform *platform, int ifindex) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj_id; - const NMPObject * obj; - - obj = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); - if (!obj || !obj->_link.netlink.is_in_netlink) - return FALSE; - - nlmsg = _nl_msg_new_link(RTM_DELLINK, 0, ifindex, NULL); - - nmp_object_stackinit_id_link(&obj_id, ifindex); - return do_delete_object(platform, &obj_id, nlmsg); -} - -static gboolean -link_refresh(NMPlatform *platform, int ifindex) -{ - do_request_link(platform, ifindex, NULL); - return !!nm_platform_link_get_obj(platform, ifindex, TRUE); -} - -static gboolean -link_set_netns(NMPlatform *platform, int ifindex, int netns_fd) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg) - return FALSE; - - NLA_PUT(nlmsg, IFLA_NET_NS_FD, 4, &netns_fd); - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static int -link_change_flags(NMPlatform *platform, int ifindex, unsigned flags_mask, unsigned flags_set) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - char s_flags[100]; - - _LOGD("link: change %d: flags: set 0x%x/0x%x ([%s] / [%s])", - ifindex, - flags_set, - flags_mask, - nm_platform_link_flags2str(flags_set, s_flags, sizeof(s_flags)), - nm_platform_link_flags2str(flags_mask, NULL, 0)); - - nlmsg = _nl_msg_new_link_full(RTM_NEWLINK, 0, ifindex, NULL, AF_UNSPEC, flags_mask, flags_set); - if (!nlmsg) - return -NME_UNSPEC; - return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); -} - -static gboolean -link_set_up(NMPlatform *platform, int ifindex, gboolean *out_no_firmware) -{ - int r; - - r = link_change_flags(platform, ifindex, IFF_UP, IFF_UP); - NM_SET_OUT(out_no_firmware, (r == -NME_PL_NO_FIRMWARE)); - return r >= 0; -} - -static gboolean -link_set_down(NMPlatform *platform, int ifindex) -{ - return (link_change_flags(platform, ifindex, IFF_UP, 0) >= 0); -} - -static gboolean -link_set_arp(NMPlatform *platform, int ifindex) -{ - return (link_change_flags(platform, ifindex, IFF_NOARP, 0) >= 0); -} - -static gboolean -link_set_noarp(NMPlatform *platform, int ifindex) -{ - return (link_change_flags(platform, ifindex, IFF_NOARP, IFF_NOARP) >= 0); -} - -static int -link_set_user_ipv6ll_enabled(NMPlatform *platform, int ifindex, gboolean enabled) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - guint8 mode = enabled ? NM_IN6_ADDR_GEN_MODE_NONE : NM_IN6_ADDR_GEN_MODE_EUI64; - - _LOGD("link: change %d: user-ipv6ll: set IPv6 address generation mode to %s", - ifindex, - nm_platform_link_inet6_addrgenmode2str(mode, NULL, 0)); - - if (!nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { - _LOGD("link: change %d: user-ipv6ll: not supported", ifindex); - return -NME_PL_OPNOTSUPP; - } - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg || !_nl_msg_new_link_set_afspec(nlmsg, mode, NULL)) - g_return_val_if_reached(-NME_BUG); - - return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); -} - -static gboolean -link_set_token(NMPlatform *platform, int ifindex, NMUtilsIPv6IfaceId iid) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - _LOGD("link: change %d: token: set IPv6 address generation token to %s", - ifindex, - nm_utils_inet6_interface_identifier_to_token(iid, sbuf)); - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg || !_nl_msg_new_link_set_afspec(nlmsg, -1, &iid)) - g_return_val_if_reached(FALSE); - - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); -} - -static gboolean -link_supports_carrier_detect(NMPlatform *platform, int ifindex) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - - if (!nm_platform_netns_push(platform, &netns)) - return FALSE; - - /* We use netlink for the actual carrier detection, but netlink can't tell - * us whether the device actually supports carrier detection in the first - * place. We assume any device that does implements one of these two APIs. - */ - return nmp_utils_ethtool_supports_carrier_detect(ifindex) - || nmp_utils_mii_supports_carrier_detect(ifindex); -} - -static gboolean -link_supports_vlans(NMPlatform *platform, int ifindex) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - const NMPObject * obj; - - obj = nm_platform_link_get_obj(platform, ifindex, TRUE); - - /* Only ARPHRD_ETHER links can possibly support VLANs. */ - if (!obj || obj->link.arptype != ARPHRD_ETHER) - return FALSE; - - if (!nm_platform_netns_push(platform, &netns)) - return FALSE; - - return nmp_utils_ethtool_supports_vlans(ifindex); -} - -static gboolean -link_supports_sriov(NMPlatform *platform, int ifindex) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - nm_auto_close int dirfd = -1; - char ifname[IFNAMSIZ]; - int num = -1; - - if (!nm_platform_netns_push(platform, &netns)) - return FALSE; - - dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname); - if (dirfd < 0) - return FALSE; - - num = - nm_platform_sysctl_get_int32(platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_numvfs"), - -1); - - return num != -1; -} - -static int -link_set_address(NMPlatform *platform, int ifindex, gconstpointer address, size_t length) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const ChangeLinkData d = { - .set_address = - { - .address = address, - .length = length, - }, - }; - - if (!address || !length) - g_return_val_if_reached(-NME_BUG); - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg) - g_return_val_if_reached(-NME_BUG); - - NLA_PUT(nlmsg, IFLA_ADDRESS, length, address); - - return do_change_link(platform, CHANGE_LINK_TYPE_SET_ADDRESS, ifindex, nlmsg, &d); -nla_put_failure: - g_return_val_if_reached(-NME_BUG); -} - -static int -link_set_name(NMPlatform *platform, int ifindex, const char *name) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg) - g_return_val_if_reached(-NME_BUG); - - NLA_PUT(nlmsg, IFLA_IFNAME, strlen(name) + 1, name); - - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -link_get_permanent_address(NMPlatform *platform, int ifindex, guint8 *buf, size_t *length) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - - if (!nm_platform_netns_push(platform, &netns)) - return FALSE; - - return nmp_utils_ethtool_get_permanent_address(ifindex, buf, length); -} - -static int -link_set_mtu(NMPlatform *platform, int ifindex, guint32 mtu) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg) - return FALSE; - - NLA_PUT_U32(nlmsg, IFLA_MTU, mtu); - - return do_change_link(platform, CHANGE_LINK_TYPE_SET_MTU, ifindex, nlmsg, NULL); -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static void -sriov_idle_cb(gpointer user_data, GCancellable *cancellable) -{ - gs_unref_object NMPlatform *platform = NULL; - gs_free_error GError *cancelled_error = NULL; - gs_free_error GError * error = NULL; - NMPlatformAsyncCallback callback; - gpointer callback_data; - - g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); - nm_utils_user_data_unpack(user_data, &platform, &error, &callback, &callback_data); - callback(cancelled_error ?: error, callback_data); -} - -static void -link_set_sriov_params_async(NMPlatform * platform, - int ifindex, - guint num_vfs, - NMOptionBool autoprobe, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable * cancellable) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - gs_free_error GError *error = NULL; - nm_auto_close int dirfd = -1; - int current_autoprobe; - guint i, total; - gint64 current_num; - char ifname[IFNAMSIZ]; - gpointer packed; - const char * values[3]; - char buf[64]; - - g_return_if_fail(callback || !data); - g_return_if_fail(cancellable); - - if (!nm_platform_netns_push(platform, &netns)) { - g_set_error_literal(&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "couldn't change namespace"); - goto out_idle; - } - - dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname); - if (!dirfd) { - g_set_error_literal(&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "couldn't open netdir"); - goto out_idle; - } - - total = nm_platform_sysctl_get_int_checked( - platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_totalvfs"), - 10, - 0, - G_MAXUINT, - 0); - if (!errno && num_vfs > total) { - _LOGW("link: %d only supports %u VFs (requested %u)", ifindex, total, num_vfs); - num_vfs = total; - } - - /* - * Take special care when setting new values: - * - don't touch anything if the right values are already set - * - to change the number of VFs or autoprobe we need to destroy existing VFs - * - the autoprobe setting is irrelevant when numvfs is zero - */ - current_num = nm_platform_sysctl_get_int_checked( - platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_numvfs"), - 10, - 0, - G_MAXUINT, - -1); - current_autoprobe = nm_platform_sysctl_get_int_checked( - platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_drivers_autoprobe"), - 10, - 0, - 1, - -1); - - if (current_autoprobe == -1 && errno == ENOENT) { - /* older kernel versions don't have this sysctl. Assume the value is - * "1". */ - current_autoprobe = 1; - } - - if (current_num == num_vfs - && (autoprobe == NM_OPTION_BOOL_DEFAULT || current_autoprobe == autoprobe)) - goto out_idle; - - if (NM_IN_SET(autoprobe, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE) - && current_autoprobe != autoprobe - && !nm_platform_sysctl_set( - NM_PLATFORM_GET, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_drivers_autoprobe"), - nm_sprintf_buf(buf, "%d", (int) autoprobe))) { - g_set_error(&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "couldn't set SR-IOV drivers-autoprobe to %d: %s", - (int) autoprobe, - nm_strerror_native(errno)); - goto out_idle; - } - - if (current_num == 0 && num_vfs == 0) - goto out_idle; - - i = 0; - if (current_num != 0) - values[i++] = "0"; - if (num_vfs != 0) - values[i++] = nm_sprintf_bufa(32, "%u", num_vfs); - values[i++] = NULL; - - sysctl_set_async(platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_numvfs"), - values, - callback, - data, - cancellable); - return; - -out_idle: - if (callback) { - packed = nm_utils_user_data_pack(g_object_ref(platform), - g_steal_pointer(&error), - callback, - data); - nm_utils_invoke_on_idle(cancellable, sriov_idle_cb, packed); - } -} - -static gboolean -link_set_sriov_vfs(NMPlatform *platform, int ifindex, const NMPlatformVF *const *vfs) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr * list, *info, *vlan_list; - guint i; - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - 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++) { - const NMPlatformVF *vf = vfs[i]; - - if (!(info = nla_nest_start(nlmsg, IFLA_VF_INFO))) - goto nla_put_failure; - - if (vf->spoofchk >= 0) { - struct _ifla_vf_setting ivs = {0}; - - ivs.vf = vf->index; - ivs.setting = vf->spoofchk; - NLA_PUT(nlmsg, IFLA_VF_SPOOFCHK, sizeof(ivs), &ivs); - } - - if (vf->trust >= 0) { - struct _ifla_vf_setting ivs = {0}; - - ivs.vf = vf->index; - ivs.setting = vf->trust; - NLA_PUT(nlmsg, IFLA_VF_TRUST, sizeof(ivs), &ivs); - } - - if (vf->mac.len) { - struct ifla_vf_mac ivm = {0}; - - ivm.vf = vf->index; - memcpy(ivm.mac, vf->mac.data, vf->mac.len); - NLA_PUT(nlmsg, IFLA_VF_MAC, sizeof(ivm), &ivm); - } - - if (vf->min_tx_rate || vf->max_tx_rate) { - struct _ifla_vf_rate ivr = {0}; - - ivr.vf = vf->index; - ivr.min_tx_rate = vf->min_tx_rate; - ivr.max_tx_rate = vf->max_tx_rate; - NLA_PUT(nlmsg, IFLA_VF_RATE, sizeof(ivr), &ivr); - } - - /* Kernel only supports one VLAN per VF now. If this - * changes in the future, we need to figure out how to - * clear existing VLANs and set new ones in one message - * with the new API.*/ - if (vf->num_vlans > 1) { - _LOGW("multiple VLANs per VF are not supported at the moment"); - return FALSE; - } else { - struct _ifla_vf_vlan_info ivvi = {0}; - - if (!(vlan_list = nla_nest_start(nlmsg, IFLA_VF_VLAN_LIST))) - goto nla_put_failure; - - ivvi.vf = vf->index; - if (vf->num_vlans == 1) { - ivvi.vlan = vf->vlans[0].id; - ivvi.qos = vf->vlans[0].qos; - ivvi.vlan_proto = htons(vf->vlans[0].proto_ad ? ETH_P_8021AD : ETH_P_8021Q); - } else { - /* Clear existing VLAN */ - ivvi.vlan = 0; - ivvi.qos = 0; - ivvi.vlan_proto = htons(ETH_P_8021Q); - } - - NLA_PUT(nlmsg, IFLA_VF_VLAN_INFO, sizeof(ivvi), &ivvi); - nla_nest_end(nlmsg, vlan_list); - } - nla_nest_end(nlmsg, info); - } - nla_nest_end(nlmsg, list); - - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -link_set_bridge_vlans(NMPlatform * platform, - int ifindex, - gboolean on_master, - const NMPlatformBridgeVlan *const *vlans) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr * list; - 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); - if (!nlmsg) - g_return_val_if_reached(-NME_BUG); - - if (!(list = nla_nest_start(nlmsg, IFLA_AF_SPEC))) - goto nla_put_failure; - - NLA_PUT_U16(nlmsg, IFLA_BRIDGE_FLAGS, on_master ? BRIDGE_FLAGS_MASTER : BRIDGE_FLAGS_SELF); - - if (vlans) { - /* Add VLANs */ - for (i = 0; vlans[i]; i++) { - const NMPlatformBridgeVlan *vlan = vlans[i]; - gboolean is_range = vlan->vid_start != vlan->vid_end; - - vinfo.vid = vlan->vid_start; - vinfo.flags = is_range ? BRIDGE_VLAN_INFO_RANGE_BEGIN : 0; - - if (vlan->untagged) - vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; - if (vlan->pvid) - vinfo.flags |= BRIDGE_VLAN_INFO_PVID; - - NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); - - if (is_range) { - vinfo.vid = vlan->vid_end; - vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END; - NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); - } - } - } else { - /* Flush existing VLANs */ - vinfo.vid = 1; - vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN; - NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); - - vinfo.vid = 4094; - vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END; - NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); - } - - nla_nest_end(nlmsg, list); - - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static char * -link_get_physical_port_id(NMPlatform *platform, int ifindex) -{ - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - - dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname_verified); - if (dirfd < 0) - return NULL; - return sysctl_get(platform, NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "phys_port_id")); -} - -static guint -link_get_dev_id(NMPlatform *platform, int ifindex) -{ - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - - dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname_verified); - if (dirfd < 0) - return 0; - return nm_platform_sysctl_get_int_checked( - platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "dev_id"), - 16, - 0, - G_MAXUINT16, - 0); -} - -static gboolean -link_tun_add(NMPlatform * platform, - const char * name, - const NMPlatformLnkTun *props, - const NMPlatformLink ** out_link, - int * out_fd) -{ - const NMPObject * obj; - struct ifreq ifr = {}; - nm_auto_close int fd = -1; - - nm_assert(NM_IN_SET(props->type, IFF_TAP, IFF_TUN)); - nm_assert(props->persist || out_fd); - - fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC); - if (fd < 0) - return FALSE; - - nm_utils_ifname_cpy(ifr.ifr_name, name); - ifr.ifr_flags = ((short) props->type) | ((short) IFF_TUN_EXCL) - | (!props->pi ? (short) IFF_NO_PI : (short) 0) - | (props->vnet_hdr ? (short) IFF_VNET_HDR : (short) 0) - | (props->multi_queue ? (short) NM_IFF_MULTI_QUEUE : (short) 0); - if (ioctl(fd, TUNSETIFF, &ifr)) - return FALSE; - - if (props->owner_valid) { - if (ioctl(fd, TUNSETOWNER, (uid_t) props->owner)) - return FALSE; - } - - if (props->group_valid) { - if (ioctl(fd, TUNSETGROUP, (gid_t) props->group)) - return FALSE; - } - - if (props->persist) { - if (ioctl(fd, TUNSETPERSIST, 1)) - return FALSE; - } - - do_request_link(platform, 0, name); - obj = nmp_cache_lookup_link_full(nm_platform_get_cache(platform), - 0, - name, - FALSE, - NM_LINK_TYPE_TUN, - NULL, - NULL); - - if (!obj) - return FALSE; - - NM_SET_OUT(out_link, &obj->link); - NM_SET_OUT(out_fd, nm_steal_fd(&fd)); - return TRUE; -} - -static void -_vlan_change_vlan_qos_mapping_create(gboolean is_ingress_map, - gboolean reset_all, - const NMVlanQosMapping *current_map, - guint current_n_map, - const NMVlanQosMapping *set_map, - guint set_n_map, - NMVlanQosMapping ** out_map, - guint * out_n_map) -{ - NMVlanQosMapping *map; - guint i, j, len; - const guint INGRESS_RANGE_LEN = 8; - - nm_assert(out_map && !*out_map); - nm_assert(out_n_map && !*out_n_map); - - if (!reset_all) - current_n_map = 0; - else if (is_ingress_map) - current_n_map = INGRESS_RANGE_LEN; - - len = current_n_map + set_n_map; - - if (len == 0) - return; - - map = g_new(NMVlanQosMapping, len); - - if (current_n_map) { - if (is_ingress_map) { - /* For the ingress-map, there are only 8 entries (0 to 7). - * When the user requests to reset all entries, we don't actually - * need the cached entries, we can just explicitly clear all possible - * ones. - * - * That makes only a real difference in case our cache is out-of-date. - * - * For the egress map we cannot do that, because there are far too - * many. There we can only clear the entries that we know about. */ - for (i = 0; i < INGRESS_RANGE_LEN; i++) { - map[i].from = i; - map[i].to = 0; - } - } else { - for (i = 0; i < current_n_map; i++) { - map[i].from = current_map[i].from; - map[i].to = 0; - } - } - } - if (set_n_map) - memcpy(&map[current_n_map], set_map, sizeof(*set_map) * set_n_map); - - g_qsort_with_data(map, len, sizeof(*map), _vlan_qos_mapping_cmp_from, NULL); - - for (i = 0, j = 0; i < len; i++) { - if ((is_ingress_map && !VLAN_XGRESS_PRIO_VALID(map[i].from)) - || (!is_ingress_map && !VLAN_XGRESS_PRIO_VALID(map[i].to))) - continue; - if (j > 0 && map[j - 1].from == map[i].from) - map[j - 1] = map[i]; - else - map[j++] = map[i]; - } - - *out_map = map; - *out_n_map = j; -} - -static gboolean -link_vlan_change(NMPlatform * platform, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map) -{ - const NMPObject * obj_cache; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const NMPObjectLnkVlan * lnk; - guint new_n_ingress_map = 0; - guint new_n_egress_map = 0; - gs_free NMVlanQosMapping *new_ingress_map = NULL; - gs_free NMVlanQosMapping *new_egress_map = NULL; - - obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); - if (!obj_cache || !obj_cache->_link.netlink.is_in_netlink) { - _LOGD("link: change %d: %s: link does not exist", ifindex, "vlan"); - return FALSE; - } - - lnk = obj_cache->_link.netlink.lnk ? &obj_cache->_link.netlink.lnk->_lnk_vlan : NULL; - - flags_set &= flags_mask; - - _vlan_change_vlan_qos_mapping_create(TRUE, - ingress_reset_all, - lnk ? lnk->ingress_qos_map : NULL, - lnk ? lnk->n_ingress_qos_map : 0, - ingress_map, - n_ingress_map, - &new_ingress_map, - &new_n_ingress_map); - - _vlan_change_vlan_qos_mapping_create(FALSE, - egress_reset_all, - lnk ? lnk->egress_qos_map : NULL, - lnk ? lnk->n_egress_qos_map : 0, - egress_map, - n_egress_map, - &new_egress_map, - &new_n_egress_map); - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg - || !_nl_msg_new_link_set_linkinfo_vlan(nlmsg, - -1, - flags_mask, - flags_set, - new_ingress_map, - new_n_ingress_map, - new_egress_map, - new_n_egress_map)) - g_return_val_if_reached(FALSE); - - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); -} - -static gboolean -link_enslave(NMPlatform *platform, int master, int slave) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int ifindex = slave; - - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg) - return FALSE; - - NLA_PUT_U32(nlmsg, IFLA_MASTER, master); - - return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -link_release(NMPlatform *platform, int master, int slave) -{ - return link_enslave(platform, 0, slave); -} - -/*****************************************************************************/ - -static gboolean -_infiniband_partition_action(NMPlatform * platform, - InfinibandAction action, - int parent, - int p_key, - const NMPlatformLink **out_link) -{ - nm_auto_close int dirfd = -1; - char ifname_parent[IFNAMSIZ]; - const NMPObject * obj; - char id[20]; - char name[IFNAMSIZ]; - gboolean success; - - nm_assert(NM_IN_SET(action, INFINIBAND_ACTION_CREATE_CHILD, INFINIBAND_ACTION_DELETE_CHILD)); - nm_assert(p_key > 0 && p_key <= 0xffff && p_key != 0x8000); - - dirfd = nm_platform_sysctl_open_netdir(platform, parent, ifname_parent); - if (dirfd < 0) { - errno = ENOENT; - return FALSE; - } - - nm_sprintf_buf(id, "0x%04x", p_key); - if (action == INFINIBAND_ACTION_CREATE_CHILD) - success = - nm_platform_sysctl_set(platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_parent, "create_child"), - id); - else - success = - nm_platform_sysctl_set(platform, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_parent, "delete_child"), - id); - - if (!success) { - if (action == INFINIBAND_ACTION_DELETE_CHILD && errno == ENODEV) - return TRUE; - return FALSE; - } - - nm_utils_new_infiniband_name(name, ifname_parent, p_key); - do_request_link(platform, 0, name); - - if (action == INFINIBAND_ACTION_DELETE_CHILD) - return TRUE; - - obj = nmp_cache_lookup_link_full(nm_platform_get_cache(platform), - 0, - name, - FALSE, - NM_LINK_TYPE_INFINIBAND, - NULL, - NULL); - if (out_link) - *out_link = obj ? &obj->link : NULL; - return !!obj; -} - -static gboolean -infiniband_partition_add(NMPlatform * platform, - int parent, - int p_key, - const NMPlatformLink **out_link) -{ - return _infiniband_partition_action(platform, - INFINIBAND_ACTION_CREATE_CHILD, - parent, - p_key, - out_link); -} - -static gboolean -infiniband_partition_delete(NMPlatform *platform, int parent, int p_key) -{ - return _infiniband_partition_action(platform, - INFINIBAND_ACTION_DELETE_CHILD, - parent, - p_key, - NULL); -} - -/*****************************************************************************/ - -static GObject * -get_ext_data(NMPlatform *platform, int ifindex) -{ - const NMPObject *obj; - - obj = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); - if (!obj) - return NULL; - - return obj->_link.ext_data; -} - -/*****************************************************************************/ - -#define WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, retval) \ - nm_auto_pop_netns NMPNetns *netns = NULL; \ - NMWifiUtils * wifi_data; \ - if (!nm_platform_netns_push(platform, &netns)) \ - return retval; \ - wifi_data = NM_WIFI_UTILS(get_ext_data(platform, ifindex)); \ - if (!wifi_data) \ - return retval; - -static gboolean -wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - if (caps) - *caps = nm_wifi_utils_get_caps(wifi_data); - return TRUE; -} - -static guint32 -wifi_get_frequency(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, 0); - return nm_wifi_utils_get_freq(wifi_data); -} - -static gboolean -wifi_get_station(NMPlatform * platform, - int ifindex, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_station(wifi_data, out_bssid, out_quality, out_rate); -} - -static NM80211Mode -wifi_get_mode(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, NM_802_11_MODE_UNKNOWN); - return nm_wifi_utils_get_mode(wifi_data); -} - -static void -wifi_set_mode(NMPlatform *platform, int ifindex, NM80211Mode mode) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, ); - nm_wifi_utils_set_mode(wifi_data, mode); -} - -static void -wifi_set_powersave(NMPlatform *platform, int ifindex, guint32 powersave) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, ); - nm_wifi_utils_set_powersave(wifi_data, powersave); -} - -static guint32 -wifi_find_frequency(NMPlatform *platform, int ifindex, const guint32 *freqs) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, 0); - return nm_wifi_utils_find_freq(wifi_data, freqs); -} - -static void -wifi_indicate_addressing_running(NMPlatform *platform, int ifindex, gboolean running) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, ); - nm_wifi_utils_indicate_addressing_running(wifi_data, running); -} - -static NMSettingWirelessWakeOnWLan -wifi_get_wake_on_wlan(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_wake_on_wlan(wifi_data); -} - -static gboolean -wifi_set_wake_on_wlan(NMPlatform *platform, int ifindex, NMSettingWirelessWakeOnWLan wowl) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_set_wake_on_wlan(wifi_data, wowl); -} - -/*****************************************************************************/ - -static gboolean -link_can_assume(NMPlatform *platform, int ifindex) -{ - NMPLookup lookup; - const NMPObject *link, *o; - NMDedupMultiIter iter; - NMPCache * cache = nm_platform_get_cache(platform); - - if (ifindex <= 0) - return FALSE; - - link = nm_platform_link_get_obj(platform, ifindex, TRUE); - if (!link) - return FALSE; - - if (!NM_FLAGS_HAS(link->link.n_ifi_flags, IFF_UP)) - return FALSE; - - if (link->link.master > 0) - return TRUE; - - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex); - if (nmp_cache_lookup(cache, &lookup)) - return TRUE; - - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex); - nmp_cache_iter_for_each (&iter, nmp_cache_lookup(cache, &lookup), &o) { - nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_TYPE_IP6_ADDRESS); - if (!IN6_IS_ADDR_LINKLOCAL(&o->ip6_address.address)) - return TRUE; - } - return FALSE; -} - -/*****************************************************************************/ - -static guint32 -mesh_get_channel(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, 0); - return nm_wifi_utils_get_mesh_channel(wifi_data); -} - -static gboolean -mesh_set_channel(NMPlatform *platform, int ifindex, guint32 channel) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_set_mesh_channel(wifi_data, channel); -} - -static gboolean -mesh_set_ssid(NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_set_mesh_ssid(wifi_data, ssid, len); -} - -/*****************************************************************************/ - -#define WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, retval) \ - NMWpanUtils *wpan_data = NM_WPAN_UTILS(get_ext_data(platform, ifindex)); \ - if (!wpan_data) \ - return retval; - -static guint16 -wpan_get_pan_id(NMPlatform *platform, int ifindex) -{ - WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, G_MAXINT16); - return nm_wpan_utils_get_pan_id(wpan_data); -} - -static gboolean -wpan_set_pan_id(NMPlatform *platform, int ifindex, guint16 pan_id) -{ - WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, FALSE); - return nm_wpan_utils_set_pan_id(wpan_data, pan_id); -} - -static guint16 -wpan_get_short_addr(NMPlatform *platform, int ifindex) -{ - WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, G_MAXINT16); - return nm_wpan_utils_get_short_addr(wpan_data); -} - -static gboolean -wpan_set_short_addr(NMPlatform *platform, int ifindex, guint16 short_addr) -{ - WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, FALSE); - return nm_wpan_utils_set_short_addr(wpan_data, short_addr); -} - -static gboolean -wpan_set_channel(NMPlatform *platform, int ifindex, guint8 page, guint8 channel) -{ - WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, FALSE); - return nm_wpan_utils_set_channel(wpan_data, page, channel); -} - -/*****************************************************************************/ - -static gboolean -link_get_wake_on_lan(NMPlatform *platform, int ifindex) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - NMLinkType type = nm_platform_link_get_type(platform, ifindex); - - if (!nm_platform_netns_push(platform, &netns)) - return FALSE; - - if (type == NM_LINK_TYPE_ETHERNET) - return nmp_utils_ethtool_get_wake_on_lan(ifindex); - else if (type == NM_LINK_TYPE_WIFI) { - NMWifiUtils *wifi_data = NM_WIFI_UTILS(get_ext_data(platform, ifindex)); - - if (!wifi_data) - return FALSE; - - return !NM_IN_SET(nm_wifi_utils_get_wake_on_wlan(wifi_data), - NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE); - - } else - return FALSE; -} - -static gboolean -link_get_driver_info(NMPlatform *platform, - int ifindex, - char ** out_driver_name, - char ** out_driver_version, - char ** out_fw_version) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - NMPUtilsEthtoolDriverInfo driver_info; - - if (!nm_platform_netns_push(platform, &netns)) - return FALSE; - - if (!nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) - return FALSE; - NM_SET_OUT(out_driver_name, g_strdup(driver_info.driver)); - NM_SET_OUT(out_driver_version, g_strdup(driver_info.version)); - NM_SET_OUT(out_fw_version, g_strdup(driver_info.fw_version)); - return TRUE; -} - -/*****************************************************************************/ - -static gboolean -ip4_address_add(NMPlatform *platform, - int ifindex, - in_addr_t addr, - guint8 plen, - in_addr_t peer_addr, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - NMPObject obj_id; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_address(RTM_NEWADDR, - NLM_F_CREATE | NLM_F_REPLACE, - AF_INET, - ifindex, - &addr, - plen, - &peer_addr, - flags, - nm_utils_ip4_address_is_link_local(addr) ? RT_SCOPE_LINK - : RT_SCOPE_UNIVERSE, - lifetime, - preferred, - broadcast_address, - label); - - nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, addr, plen, peer_addr); - return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE) >= 0); -} - -static gboolean -ip6_address_add(NMPlatform * platform, - int ifindex, - struct in6_addr addr, - guint8 plen, - struct in6_addr peer_addr, - guint32 lifetime, - guint32 preferred, - guint32 flags) -{ - NMPObject obj_id; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_address(RTM_NEWADDR, - NLM_F_CREATE | NLM_F_REPLACE, - AF_INET6, - ifindex, - &addr, - plen, - IN6_IS_ADDR_UNSPECIFIED(&peer_addr) ? NULL : &peer_addr, - flags, - RT_SCOPE_UNIVERSE, - lifetime, - preferred, - 0, - NULL); - - nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, &addr); - return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE) >= 0); -} - -static gboolean -ip4_address_delete(NMPlatform *platform, - int ifindex, - in_addr_t addr, - guint8 plen, - in_addr_t peer_address) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj_id; - - nlmsg = _nl_msg_new_address(RTM_DELADDR, - 0, - AF_INET, - ifindex, - &addr, - plen, - &peer_address, - 0, - RT_SCOPE_NOWHERE, - NM_PLATFORM_LIFETIME_PERMANENT, - NM_PLATFORM_LIFETIME_PERMANENT, - 0, - NULL); - if (!nlmsg) - g_return_val_if_reached(FALSE); - - nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, addr, plen, peer_address); - return do_delete_object(platform, &obj_id, nlmsg); -} - -static gboolean -ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj_id; - - nlmsg = _nl_msg_new_address(RTM_DELADDR, - 0, - AF_INET6, - ifindex, - &addr, - plen, - NULL, - 0, - RT_SCOPE_NOWHERE, - NM_PLATFORM_LIFETIME_PERMANENT, - NM_PLATFORM_LIFETIME_PERMANENT, - 0, - NULL); - if (!nlmsg) - g_return_val_if_reached(FALSE); - - nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, &addr); - return do_delete_object(platform, &obj_id, nlmsg); -} - -/*****************************************************************************/ - -static int -ip_route_add(NMPlatform * platform, - NMPNlmFlags flags, - int addr_family, - const NMPlatformIPRoute *route) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj; - - nmp_object_stackinit(&obj, - NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)), - (const NMPlatformObject *) route); - - nm_platform_ip_route_normalize(addr_family, NMP_OBJECT_CAST_IP_ROUTE(&obj)); - - nlmsg = _nl_msg_new_route(RTM_NEWROUTE, flags & NMP_NLM_FLAG_FMASK, &obj); - if (!nlmsg) - g_return_val_if_reached(-NME_BUG); - return do_add_addrroute(platform, - &obj, - nlmsg, - NM_FLAGS_HAS(flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE)); -} - -static gboolean -object_delete(NMPlatform *platform, const NMPObject *obj) -{ - nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL; - nm_auto_nlmsg struct nl_msg * nlmsg = NULL; - - if (!NMP_OBJECT_IS_STACKINIT(obj)) - obj_keep_alive = nmp_object_ref(obj); - - switch (NMP_OBJECT_GET_TYPE(obj)) { - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - nlmsg = _nl_msg_new_route(RTM_DELROUTE, 0, obj); - break; - case NMP_OBJECT_TYPE_ROUTING_RULE: - nlmsg = _nl_msg_new_routing_rule(RTM_DELRULE, 0, NMP_OBJECT_CAST_ROUTING_RULE(obj)); - break; - case NMP_OBJECT_TYPE_QDISC: - nlmsg = _nl_msg_new_qdisc(RTM_DELQDISC, 0, NMP_OBJECT_CAST_QDISC(obj)); - break; - case NMP_OBJECT_TYPE_TFILTER: - nlmsg = _nl_msg_new_tfilter(RTM_DELTFILTER, 0, NMP_OBJECT_CAST_TFILTER(obj)); - break; - default: - break; - } - - if (!nlmsg) - g_return_val_if_reached(FALSE); - return do_delete_object(platform, obj, nlmsg); -} - -/*****************************************************************************/ - -static int -ip_route_get(NMPlatform * platform, - int addr_family, - gconstpointer address, - int oif_ifindex, - NMPObject ** out_route) -{ - const gboolean is_v4 = (addr_family == AF_INET); - const int addr_len = is_v4 ? 4 : 16; - int try_count = 0; - WaitForNlResponseResult seq_result; - int nle; - nm_auto_nmpobj NMPObject *route = NULL; - - nm_assert(NM_IS_LINUX_PLATFORM(platform)); - nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - nm_assert(address); - - do { - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[64]; - } req = { - .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), - .n.nlmsg_flags = NLM_F_REQUEST, - .n.nlmsg_type = RTM_GETROUTE, - .r.rtm_family = addr_family, - .r.rtm_tos = 0, - .r.rtm_dst_len = is_v4 ? 32 : 128, - .r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */, - }; - - nm_clear_pointer(&route, nmp_object_unref); - - if (!_nl_addattr_l(&req.n, sizeof(req), RTA_DST, address, addr_len)) - nm_assert_not_reached(); - - if (oif_ifindex > 0) { - gint32 ii = oif_ifindex; - - if (!_nl_addattr_l(&req.n, sizeof(req), RTA_OIF, &ii, sizeof(ii))) - nm_assert_not_reached(); - } - - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - nle = _nl_send_nlmsghdr(platform, - &req.n, - &seq_result, - NULL, - DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET, - &route); - if (nle < 0) { - _LOGE("get-route: failure sending netlink request \"%s\" (%d)", - nm_strerror_native(-nle), - -nle); - return -NME_UNSPEC; - } - - delayed_action_handle_all(platform, FALSE); - - /* Retry, if we failed due to a cache resync. That can happen when the netlink - * socket fills up and we lost the response. */ - } while (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC && ++try_count < 10); - - if (seq_result < 0) { - /* negative seq_result is an errno from kernel. Map it to negative - * int (which are also errno). */ - return (int) seq_result; - } - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { - if (route) { - NM_SET_OUT(out_route, g_steal_pointer(&route)); - return 0; - } - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN; - } - - return -NME_UNSPEC; -} - -/*****************************************************************************/ - -static int -routing_rule_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformRoutingRule *routing_rule) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - nm_auto_nlmsg struct nl_msg *msg = NULL; - gs_free char * errmsg = NULL; - char s_buf[256]; - int nle; - - msg = _nl_msg_new_routing_rule(RTM_NEWRULE, flags, routing_rule); - - event_handler_read_netlink(platform, FALSE); - - nle = _nl_send_nlmsg(platform, - msg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - _LOGE("do-add-rule: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle); - return -NME_PL_NETLINK; - } - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, - "do-add-rule: %s", - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - if (seq_result < 0) - return seq_result; - return -NME_UNSPEC; -} - -/*****************************************************************************/ - -static int -qdisc_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformQdisc *qdisc) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; - int nle; - char s_buf[256]; - nm_auto_nlmsg struct nl_msg *msg = NULL; - - /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind - * is undefined. */ - - msg = _nl_msg_new_qdisc(RTM_NEWQDISC, flags, qdisc); - - event_handler_read_netlink(platform, FALSE); - - nle = _nl_send_nlmsg(platform, - msg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - _LOGE("do-add-qdisc: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle); - return -NME_PL_NETLINK; - } - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, - "do-add-qdisc: %s", - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - if (seq_result < 0) - return seq_result; - return -NME_UNSPEC; -} - -/*****************************************************************************/ - -static int -tfilter_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformTfilter *tfilter) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char * errmsg = NULL; - int nle; - char s_buf[256]; - nm_auto_nlmsg struct nl_msg *msg = NULL; - - /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind - * and tfilter.action.kind is undefined. */ - - msg = _nl_msg_new_tfilter(RTM_NEWTFILTER, flags, tfilter); - - event_handler_read_netlink(platform, FALSE); - - nle = _nl_send_nlmsg(platform, - msg, - &seq_result, - &errmsg, - DELAYED_ACTION_RESPONSE_TYPE_VOID, - NULL); - if (nle < 0) { - _LOGE("do-add-tfilter: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle); - return -NME_PL_NETLINK; - } - - delayed_action_handle_all(platform, FALSE); - - nm_assert(seq_result); - - _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, - "do-add-tfilter: %s", - wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - - return -NME_UNSPEC; -} - -/*****************************************************************************/ - -static gboolean -event_handler(int fd, GIOCondition io_condition, gpointer user_data) -{ - delayed_action_handle_all(NM_PLATFORM(user_data), TRUE); - return TRUE; -} - -/*****************************************************************************/ - -/* copied from libnl3's recvmsgs() */ -static int -event_handler_recvmsgs(NMPlatform *platform, gboolean handle_events) -{ - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - struct nl_sock * sk = priv->nlh; - int n; - int err = 0; - gboolean multipart = 0; - gboolean interrupted = FALSE; - struct nlmsghdr * hdr; - WaitForNlResponseResult seq_result; - struct sockaddr_nl nla = {0}; - struct ucred creds; - gboolean creds_has; - nm_auto_free unsigned char *buf = NULL; - -continue_reading: - nm_clear_pointer(&buf, free); - n = nl_recv(sk, &nla, &buf, &creds, &creds_has); - - if (n <= 0) { - if (n == -NME_NL_MSG_TRUNC) { - int buf_size; - - /* the message receive buffer was too small. We lost one message, which - * is unfortunate. Try to double the buffer size for the next time. */ - buf_size = nl_socket_get_msg_buf_size(sk); - if (buf_size < 512 * 1024) { - buf_size *= 2; - _LOGT("netlink: recvmsg: increase message buffer size for recvmsg() to %d bytes", - buf_size); - if (nl_socket_set_msg_buf_size(sk, buf_size) < 0) - nm_assert_not_reached(); - if (!handle_events) - goto continue_reading; - } - } - - return n; - } - - hdr = (struct nlmsghdr *) buf; - while (nlmsg_ok(hdr, n)) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - gboolean abort_parsing = FALSE; - gboolean process_valid_msg = FALSE; - guint32 seq_number; - char buf_nlmsghdr[400]; - const char * extack_msg = NULL; - - msg = nlmsg_alloc_convert(hdr); - - nlmsg_set_proto(msg, NETLINK_ROUTE); - nlmsg_set_src(msg, &nla); - - if (!creds_has || creds.pid) { - if (!creds_has) - _LOGT("netlink: recvmsg: received message without credentials"); - else - _LOGT("netlink: recvmsg: received non-kernel message (pid %d)", creds.pid); - err = 0; - goto stop; - } - - _LOGt("netlink: recvmsg: new message %s", - nl_nlmsghdr_to_str(hdr, buf_nlmsghdr, sizeof(buf_nlmsghdr))); - - nlmsg_set_creds(msg, &creds); - - if (hdr->nlmsg_flags & NLM_F_MULTI) - multipart = TRUE; - - if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { - /* - * We have to continue reading to clear - * all messages until a NLMSG_DONE is - * received and report the inconsistency. - */ - interrupted = TRUE; - } - - /* Other side wishes to see an ack for this message */ - if (hdr->nlmsg_flags & NLM_F_ACK) { - /* FIXME: implement */ - } - - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN; - - if (hdr->nlmsg_type == NLMSG_DONE) { - /* messages terminates a multipart message, this is - * usually the end of a message and therefore we slip - * out of the loop by default. the user may overrule - * this action by skipping this packet. */ - multipart = FALSE; - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; - } else if (hdr->nlmsg_type == NLMSG_NOOP) { - /* Message to be ignored, the default action is to - * skip this message if no callback is specified. The - * user may overrule this action by returning - * NL_PROCEED. */ - } else if (hdr->nlmsg_type == NLMSG_OVERRUN) { - /* Data got lost, report back to user. The default action is to - * quit parsing. The user may overrule this action by returning - * NL_SKIP or NL_PROCEED (dangerous) */ - err = -NME_NL_MSG_OVERFLOW; - abort_parsing = TRUE; - } else if (hdr->nlmsg_type == NLMSG_ERROR) { - /* Message carries a nlmsgerr */ - struct nlmsgerr *e = nlmsg_data(hdr); - - if (hdr->nlmsg_len < nlmsg_size(sizeof(*e))) { - /* Truncated error message, the default action - * is to stop parsing. The user may overrule - * this action by returning NL_SKIP or - * NL_PROCEED (dangerous) */ - err = -NME_NL_MSG_TRUNC; - abort_parsing = TRUE; - } else if (e->error) { - int errsv = nm_errno_native(e->error); - - if (NM_FLAGS_HAS(hdr->nlmsg_flags, NLM_F_ACK_TLVS) - && hdr->nlmsg_len >= sizeof(*e) + e->msg.nlmsg_len) { - static const struct nla_policy policy[] = { - [NLMSGERR_ATTR_MSG] = {.type = NLA_STRING}, - [NLMSGERR_ATTR_OFFS] = {.type = NLA_U32}, - }; - struct nlattr *tb[G_N_ELEMENTS(policy)]; - struct nlattr *tlvs; - - tlvs = (struct nlattr *) ((char *) e + sizeof(*e) + e->msg.nlmsg_len - - NLMSG_HDRLEN); - if (nla_parse_arr(tb, - tlvs, - hdr->nlmsg_len - sizeof(*e) - e->msg.nlmsg_len, - policy) - >= 0) { - if (tb[NLMSGERR_ATTR_MSG]) - extack_msg = nla_get_string(tb[NLMSGERR_ATTR_MSG]); - } - } - - /* Error message reported back from kernel. */ - _LOGD("netlink: recvmsg: error message from kernel: %s (%d)%s%s%s for request %d", - nm_strerror_native(errsv), - errsv, - NM_PRINT_FMT_QUOTED(extack_msg, " \"", extack_msg, "\"", ""), - nlmsg_hdr(msg)->nlmsg_seq); - seq_result = -NM_ERRNO_NATIVE(errsv); - } else - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; - } else - process_valid_msg = TRUE; - - seq_number = nlmsg_hdr(msg)->nlmsg_seq; - - /* check whether the seq number is different from before, and - * whether the previous number (@nlh_seq_last_seen) is a pending - * refresh-all request. In that case, the pending request is thereby - * completed. - * - * We must do that before processing the message with event_valid_msg(), - * because we must track the completion of the pending request before that. */ - event_seq_check_refresh_all(platform, seq_number); - - if (process_valid_msg) { - /* Valid message (not checking for MULTIPART bit to - * get along with broken kernels. NL_SKIP has no - * effect on this. */ - - event_valid_msg(platform, msg, handle_events); - - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; - } - - event_seq_check(platform, seq_number, seq_result, extack_msg); - - if (abort_parsing) - goto stop; - - err = 0; - hdr = nlmsg_next(hdr, &n); - } - - if (multipart) { - /* Multipart message not yet complete, continue reading */ - goto continue_reading; - } -stop: - if (!handle_events) { - /* when we don't handle events, we want to drain all messages from the socket - * without handling the messages (but still check for sequence numbers). - * Repeat reading. */ - goto continue_reading; - } - - if (interrupted) - return -NME_NL_DUMP_INTR; - return err; -} - -/*****************************************************************************/ - -static gboolean -event_handler_read_netlink(NMPlatform *platform, gboolean wait_for_acks) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - int r; - struct pollfd pfd; - gboolean any = FALSE; - int timeout_msec; - struct { - guint32 seq_number; - gint64 timeout_abs_ns; - gint64 now_ns; - } next; - - if (!nm_platform_netns_push(platform, &netns)) { - delayed_action_wait_for_nl_response_complete_all(platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS); - return FALSE; - } - - for (;;) { - for (;;) { - int nle; - - nle = event_handler_recvmsgs(platform, TRUE); - - if (nle < 0) { - switch (nle) { - case -EAGAIN: - goto after_read; - case -NME_NL_DUMP_INTR: - _LOGD("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", - nm_strerror(nle), - nle); - break; - case -NME_NL_MSG_TRUNC: - case -ENOBUFS: - _LOGI("netlink: read: %s. Need to resynchronize platform cache", ({ - const char *_reason = "unknown"; - switch (nle) { - case -NME_NL_MSG_TRUNC: - _reason = "message truncated"; - break; - case -ENOBUFS: - _reason = "too many netlink events"; - break; - } - _reason; - })); - event_handler_recvmsgs(platform, FALSE); - delayed_action_wait_for_nl_response_complete_all( - platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC); - - delayed_action_schedule(platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL - | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS - | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - NULL); - break; - default: - _LOGE("netlink: read: failed to retrieve incoming events: %s (%d)", - nm_strerror(nle), - nle); - break; - } - } - any = TRUE; - } - -after_read: - - if (!NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) - return any; - - delayed_action_wait_for_nl_response_complete_check(platform, - WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN, - &next.seq_number, - &next.timeout_abs_ns, - &next.now_ns); - - if (!wait_for_acks - || !NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) - return any; - - nm_assert(next.seq_number); - nm_assert(next.now_ns > 0); - nm_assert(next.timeout_abs_ns > next.now_ns); - - _LOGT("netlink: read: wait for ACK for sequence number %u...", next.seq_number); - - timeout_msec = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NSEC_PER_SEC / 1000); - - memset(&pfd, 0, sizeof(pfd)); - pfd.fd = nl_socket_get_fd(priv->nlh); - pfd.events = POLLIN; - r = poll(&pfd, 1, MAX(1, timeout_msec)); - - if (r == 0) { - /* timeout and there is nothing to read. */ - goto after_read; - } - - if (r < 0) { - int errsv = errno; - - if (errsv != EINTR) { - _LOGE("netlink: read: poll failed with %s", nm_strerror_native(errsv)); - delayed_action_wait_for_nl_response_complete_all( - platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL); - return any; - } - /* Continue to read again, even if there might be nothing to read after EINTR. */ - } - } -} - -/*****************************************************************************/ - -static void -cache_update_link_udev(NMPlatform *platform, int ifindex, struct udev_device *udevice) -{ - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - NMPCacheOpsType cache_op; - - cache_op = nmp_cache_update_link_udev(nm_platform_get_cache(platform), - ifindex, - udevice, - &obj_old, - &obj_new); - - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - nm_auto_pop_netns NMPNetns *netns = NULL; - - cache_on_change(platform, cache_op, obj_old, obj_new); - if (!nm_platform_netns_push(platform, &netns)) - return; - nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); - } -} - -static void -udev_device_added(NMPlatform *platform, struct udev_device *udevice) -{ - const char *ifname; - const char *ifindex_s; - int ifindex; - - ifname = udev_device_get_sysname(udevice); - if (!ifname) { - _LOGD("udev-add: failed to get device's interface"); - return; - } - - ifindex_s = udev_device_get_property_value(udevice, "IFINDEX"); - if (!ifindex_s) { - _LOGW("udev-add[%s]failed to get device's ifindex", ifname); - return; - } - ifindex = _nm_utils_ascii_str_to_int64(ifindex_s, 10, 1, G_MAXINT, 0); - if (ifindex <= 0) { - _LOGW("udev-add[%s]: retrieved invalid IFINDEX=%d", ifname, ifindex); - return; - } - - if (!udev_device_get_syspath(udevice)) { - _LOGD("udev-add[%s,%d]: couldn't determine device path; ignoring...", ifname, ifindex); - return; - } - - _LOGT("udev-add[%s,%d]: device added", ifname, ifindex); - cache_update_link_udev(platform, ifindex, udevice); -} - -static gboolean -_udev_device_removed_match_link(const NMPObject *obj, gpointer udevice) -{ - return obj->_link.udev.device == udevice; -} - -static void -udev_device_removed(NMPlatform *platform, struct udev_device *udevice) -{ - const char *ifindex_s; - int ifindex = 0; - - ifindex_s = udev_device_get_property_value(udevice, "IFINDEX"); - ifindex = _nm_utils_ascii_str_to_int64(ifindex_s, 10, 1, G_MAXINT, 0); - if (ifindex <= 0) { - const NMPObject *obj; - - obj = nmp_cache_lookup_link_full(nm_platform_get_cache(platform), - 0, - NULL, - FALSE, - NM_LINK_TYPE_NONE, - _udev_device_removed_match_link, - udevice); - if (obj) - ifindex = obj->link.ifindex; - } - - _LOGD("udev-remove: IFINDEX=%d", ifindex); - if (ifindex <= 0) - return; - - cache_update_link_udev(platform, ifindex, NULL); -} - -static void -handle_udev_event(NMUdevClient *udev_client, struct udev_device *udevice, gpointer user_data) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - NMPlatform * platform = NM_PLATFORM(user_data); - const char * subsys; - const char * ifindex; - guint64 seqnum; - const char * action; - - action = udev_device_get_action(udevice); - g_return_if_fail(action); - - subsys = udev_device_get_subsystem(udevice); - g_return_if_fail(nm_streq0(subsys, "net")); - - if (!nm_platform_netns_push(platform, &netns)) - return; - - ifindex = udev_device_get_property_value(udevice, "IFINDEX"); - seqnum = udev_device_get_seqnum(udevice); - _LOGD("UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, - action, - subsys, - udev_device_get_sysname(udevice), - ifindex ?: "unknown", - seqnum); - - if (NM_IN_STRSET(action, "add", "move")) - udev_device_added(platform, udevice); - else if (NM_IN_STRSET(action, "remove")) - udev_device_removed(platform, udevice); -} - -/*****************************************************************************/ - -void -nm_linux_platform_setup(void) -{ - nm_platform_setup(nm_linux_platform_new(FALSE, FALSE)); -} - -/*****************************************************************************/ - -static void -nm_linux_platform_init(NMLinuxPlatform *self) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(self); - - priv->delayed_action.list_master_connected = g_ptr_array_new(); - priv->delayed_action.list_refresh_link = g_ptr_array_new(); - priv->delayed_action.list_wait_for_nl_response = - g_array_new(FALSE, TRUE, sizeof(DelayedActionWaitForNlResponseData)); -} - -static void -constructed(GObject *_object) -{ - NMPlatform * platform = NM_PLATFORM(_object); - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - int nle; - int fd; - - nm_assert(!platform->_netns || platform->_netns == nmp_netns_get_current()); - - if (nm_platform_get_use_udev(platform)) { - priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("net"), handle_udev_event, platform); - } - - _LOGD("create (%s netns, %s, %s udev)", - !platform->_netns ? "ignore" : "use", - !platform->_netns && nmp_netns_is_initial() - ? "initial netns" - : (!nmp_netns_get_current() - ? "no netns support" - : nm_sprintf_bufa(100, - "in netns[%p]%s", - nmp_netns_get_current(), - nmp_netns_get_current() == nmp_netns_get_initial() ? "/main" - : "")), - nm_platform_get_use_udev(platform) ? "use" : "no"); - - priv->genl = nl_socket_alloc(); - g_assert(priv->genl); - - nle = nl_connect(priv->genl, NETLINK_GENERIC); - if (nle) { - _LOGE("unable to connect the generic netlink socket \"%s\" (%d)", nm_strerror(nle), -nle); - nl_socket_free(priv->genl); - priv->genl = NULL; - } - - priv->nlh = nl_socket_alloc(); - g_assert(priv->nlh); - - nle = nl_connect(priv->nlh, NETLINK_ROUTE); - g_assert(!nle); - nle = nl_socket_set_passcred(priv->nlh, 1); - g_assert(!nle); - - /* No blocking for event socket, so that we can drain it safely. */ - nle = nl_socket_set_nonblocking(priv->nlh); - g_assert(!nle); - - /* use 8 MB for receive socket kernel queue. */ - nle = nl_socket_set_buffer_size(priv->nlh, 8 * 1024 * 1024, 0); - g_assert(!nle); - - nle = nl_socket_set_ext_ack(priv->nlh, TRUE); - if (nle) - _LOGD("could not enable extended acks on netlink socket"); - - /* explicitly set the msg buffer size and disable MSG_PEEK. - * If we later encounter NME_NL_MSG_TRUNC, we will adjust the buffer size. */ - nl_socket_disable_msg_peek(priv->nlh); - nle = nl_socket_set_msg_buf_size(priv->nlh, 32 * 1024); - g_assert(!nle); - - nle = nl_socket_add_memberships(priv->nlh, - RTNLGRP_IPV4_IFADDR, - RTNLGRP_IPV4_ROUTE, - RTNLGRP_IPV4_RULE, - RTNLGRP_IPV6_RULE, - RTNLGRP_IPV6_IFADDR, - RTNLGRP_IPV6_ROUTE, - RTNLGRP_LINK, - RTNLGRP_TC, - 0); - g_assert(!nle); - - fd = nl_socket_get_fd(priv->nlh); - - _LOGD("Netlink socket for events established: port=%u, fd=%d", - nl_socket_get_local_port(priv->nlh), - fd); - - priv->event_source = - nm_g_unix_fd_source_new(fd, - G_IO_IN | G_IO_NVAL | G_IO_PRI | G_IO_ERR | G_IO_HUP, - G_PRIORITY_DEFAULT, - event_handler, - platform, - NULL); - g_source_attach(priv->event_source, NULL); - - /* complete construction of the GObject instance before populating the cache. */ - G_OBJECT_CLASS(nm_linux_platform_parent_class)->constructed(_object); - - _LOGD("populate platform cache"); - delayed_action_schedule( - platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES - | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL - | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - NULL); - - delayed_action_handle_all(platform, FALSE); - - /* Set up udev monitoring */ - if (priv->udev_client) { - struct udev_enumerate * enumerator; - struct udev_list_entry *devices, *l; - - /* And read initial device list */ - enumerator = nm_udev_client_enumerate_new(priv->udev_client); - - udev_enumerate_add_match_is_initialized(enumerator); - - udev_enumerate_scan_devices(enumerator); - - devices = udev_enumerate_get_list_entry(enumerator); - for (l = devices; l; l = udev_list_entry_get_next(l)) { - struct udev_device *udevice; - - udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), - udev_list_entry_get_name(l)); - if (!udevice) - continue; - - udev_device_added(platform, udevice); - udev_device_unref(udevice); - } - - udev_enumerate_unref(enumerator); - } -} - -/* Similar to systemd's path_is_read_only_fs(), at - * https://github.com/systemd/systemd/blob/v246/src/basic/stat-util.c#L132 */ -static int -path_is_read_only_fs(const char *path) -{ - struct statvfs st; - - if (statvfs(path, &st) < 0) - return -errno; - - if (st.f_flag & ST_RDONLY) - return TRUE; - - /* On NFS, statvfs() might not reflect whether we can actually - * write to the remote share. Let's try again with - * access(W_OK) which is more reliable, at least sometimes. */ - if (access(path, W_OK) < 0 && errno == EROFS) - return TRUE; - - return FALSE; -} - -NMPlatform * -nm_linux_platform_new(gboolean log_with_ptr, gboolean netns_support) -{ - gboolean use_udev = FALSE; - - if (nmp_netns_is_initial() && path_is_read_only_fs("/sys") == FALSE) - use_udev = TRUE; - - return g_object_new(NM_TYPE_LINUX_PLATFORM, - NM_PLATFORM_LOG_WITH_PTR, - log_with_ptr, - NM_PLATFORM_USE_UDEV, - use_udev, - NM_PLATFORM_NETNS_SUPPORT, - netns_support, - NULL); -} - -static void -dispose(GObject *object) -{ - NMPlatform * platform = NM_PLATFORM(object); - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - - _LOGD("dispose"); - - delayed_action_wait_for_nl_response_complete_all(platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING); - - priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE; - g_ptr_array_set_size(priv->delayed_action.list_master_connected, 0); - g_ptr_array_set_size(priv->delayed_action.list_refresh_link, 0); - - G_OBJECT_CLASS(nm_linux_platform_parent_class)->dispose(object); -} - -static void -finalize(GObject *object) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(object); - - g_ptr_array_unref(priv->delayed_action.list_master_connected); - g_ptr_array_unref(priv->delayed_action.list_refresh_link); - g_array_unref(priv->delayed_action.list_wait_for_nl_response); - - nl_socket_free(priv->genl); - - nm_clear_g_source_inst(&priv->event_source); - - nl_socket_free(priv->nlh); - - if (priv->sysctl_get_prev_values) { - sysctl_clear_cache_list = g_slist_remove(sysctl_clear_cache_list, object); - g_hash_table_destroy(priv->sysctl_get_prev_values); - } - - priv->udev_client = nm_udev_client_destroy(priv->udev_client); - - G_OBJECT_CLASS(nm_linux_platform_parent_class)->finalize(object); -} - -static void -nm_linux_platform_class_init(NMLinuxPlatformClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMPlatformClass *platform_class = NM_PLATFORM_CLASS(klass); - - object_class->constructed = constructed; - object_class->dispose = dispose; - object_class->finalize = finalize; - - platform_class->sysctl_set = sysctl_set; - platform_class->sysctl_set_async = sysctl_set_async; - platform_class->sysctl_get = sysctl_get; - - platform_class->link_add = link_add; - platform_class->link_delete = link_delete; - - platform_class->link_refresh = link_refresh; - - platform_class->link_set_netns = link_set_netns; - - platform_class->link_set_up = link_set_up; - platform_class->link_set_down = link_set_down; - platform_class->link_set_arp = link_set_arp; - platform_class->link_set_noarp = link_set_noarp; - - platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled; - platform_class->link_set_token = link_set_token; - - platform_class->link_set_address = link_set_address; - platform_class->link_get_permanent_address = link_get_permanent_address; - platform_class->link_set_mtu = link_set_mtu; - platform_class->link_set_name = link_set_name; - platform_class->link_set_sriov_params_async = link_set_sriov_params_async; - platform_class->link_set_sriov_vfs = link_set_sriov_vfs; - platform_class->link_set_bridge_vlans = link_set_bridge_vlans; - - platform_class->link_get_physical_port_id = link_get_physical_port_id; - platform_class->link_get_dev_id = link_get_dev_id; - platform_class->link_get_wake_on_lan = link_get_wake_on_lan; - platform_class->link_get_driver_info = link_get_driver_info; - - platform_class->link_supports_carrier_detect = link_supports_carrier_detect; - platform_class->link_supports_vlans = link_supports_vlans; - platform_class->link_supports_sriov = link_supports_sriov; - - platform_class->link_enslave = link_enslave; - platform_class->link_release = link_release; - - platform_class->link_can_assume = link_can_assume; - - platform_class->link_vlan_change = link_vlan_change; - platform_class->link_wireguard_change = link_wireguard_change; - - platform_class->infiniband_partition_add = infiniband_partition_add; - platform_class->infiniband_partition_delete = infiniband_partition_delete; - - platform_class->wifi_get_capabilities = wifi_get_capabilities; - platform_class->wifi_get_frequency = wifi_get_frequency; - platform_class->wifi_get_station = wifi_get_station; - platform_class->wifi_get_mode = wifi_get_mode; - platform_class->wifi_set_mode = wifi_set_mode; - platform_class->wifi_set_powersave = wifi_set_powersave; - platform_class->wifi_find_frequency = wifi_find_frequency; - platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; - platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan; - platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; - - platform_class->mesh_get_channel = mesh_get_channel; - platform_class->mesh_set_channel = mesh_set_channel; - platform_class->mesh_set_ssid = mesh_set_ssid; - - platform_class->wpan_get_pan_id = wpan_get_pan_id; - platform_class->wpan_set_pan_id = wpan_set_pan_id; - platform_class->wpan_get_short_addr = wpan_get_short_addr; - platform_class->wpan_set_short_addr = wpan_set_short_addr; - platform_class->wpan_set_channel = wpan_set_channel; - - platform_class->link_tun_add = link_tun_add; - - platform_class->object_delete = object_delete; - platform_class->ip4_address_add = ip4_address_add; - platform_class->ip6_address_add = ip6_address_add; - platform_class->ip4_address_delete = ip4_address_delete; - platform_class->ip6_address_delete = ip6_address_delete; - - platform_class->ip_route_add = ip_route_add; - platform_class->ip_route_get = ip_route_get; - - platform_class->routing_rule_add = routing_rule_add; - - platform_class->qdisc_add = qdisc_add; - platform_class->tfilter_add = tfilter_add; - - platform_class->process_events = process_events; -} diff --git a/src/core/platform/nm-linux-platform.h b/src/core/platform/nm-linux-platform.h deleted file mode 100644 index 6837e64a..00000000 --- a/src/core/platform/nm-linux-platform.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2012 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_LINUX_PLATFORM_H__ -#define __NETWORKMANAGER_LINUX_PLATFORM_H__ - -#include "nm-platform.h" - -#define NM_TYPE_LINUX_PLATFORM (nm_linux_platform_get_type()) -#define NM_LINUX_PLATFORM(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatform)) -#define NM_LINUX_PLATFORM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) -#define NM_IS_LINUX_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_LINUX_PLATFORM)) -#define NM_IS_LINUX_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_LINUX_PLATFORM)) -#define NM_LINUX_PLATFORM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) - -typedef struct _NMLinuxPlatform NMLinuxPlatform; -typedef struct _NMLinuxPlatformClass NMLinuxPlatformClass; - -GType nm_linux_platform_get_type(void); - -NMPlatform *nm_linux_platform_new(gboolean log_with_ptr, gboolean netns_support); - -void nm_linux_platform_setup(void); - -#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */ diff --git a/src/core/platform/nm-platform-private.h b/src/core/platform/nm-platform-private.h deleted file mode 100644 index cf805689..00000000 --- a/src/core/platform/nm-platform-private.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#ifndef __NM_PLATFORM_PRIVATE_H__ -#define __NM_PLATFORM_PRIVATE_H__ - -#include "nm-platform.h" -#include "nmp-object.h" - -NMPCache *nm_platform_get_cache(NMPlatform *self); - -#define NMTST_ASSERT_PLATFORM_NETNS_CURRENT(platform) \ - G_STMT_START \ - { \ - NMPlatform *_platform = (platform); \ - \ - nm_assert(NM_IS_PLATFORM(_platform)); \ - nm_assert(NM_IN_SET(nm_platform_netns_get(_platform), NULL, nmp_netns_get_current())); \ - } \ - G_STMT_END - -void nm_platform_cache_update_emit_signal(NMPlatform * platform, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new); - -#endif /* __NM_PLATFORM_PRIVATE_H__ */ diff --git a/src/core/platform/nm-platform.c b/src/core/platform/nm-platform.c deleted file mode 100644 index 459a3307..00000000 --- a/src/core/platform/nm-platform.c +++ /dev/null @@ -1,9066 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2012 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-platform.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nm-utils.h" -#include "nm-core-internal.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-udev-aux/nm-udev-utils.h" -#include "nm-glib-aux/nm-secret-utils.h" - -#include "nm-core-utils.h" -#include "nm-platform/nm-platform-utils.h" -#include "nm-platform-private.h" -#include "nmp-object.h" -#include "nm-platform/nmp-netns.h" - -/*****************************************************************************/ - -G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr) - == G_STRUCT_OFFSET(NMPlatformIP4Address, address)); -G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr) - == G_STRUCT_OFFSET(NMPlatformIP6Address, address)); -G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr) - == G_STRUCT_OFFSET(NMPlatformIP4Route, network)); -G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr) - == G_STRUCT_OFFSET(NMPlatformIP6Route, network)); - -G_STATIC_ASSERT(_nm_alignof(NMPlatformIPRoute) == _nm_alignof(NMPlatformIP4Route)); -G_STATIC_ASSERT(_nm_alignof(NMPlatformIPRoute) == _nm_alignof(NMPlatformIP6Route)); -G_STATIC_ASSERT(_nm_alignof(NMPlatformIPRoute) == _nm_alignof(NMPlatformIPXRoute)); - -G_STATIC_ASSERT(_nm_alignof(NMPlatformIPAddress) == _nm_alignof(NMPlatformIP4Address)); -G_STATIC_ASSERT(_nm_alignof(NMPlatformIPAddress) == _nm_alignof(NMPlatformIP6Address)); -G_STATIC_ASSERT(_nm_alignof(NMPlatformIPAddress) == _nm_alignof(NMPlatformIPXAddress)); - -/*****************************************************************************/ - -G_STATIC_ASSERT(sizeof(((NMPLinkAddress *) NULL)->data) == NM_UTILS_HWADDR_LEN_MAX); -G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_address.data) == NM_UTILS_HWADDR_LEN_MAX); -G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_broadcast.data) == NM_UTILS_HWADDR_LEN_MAX); - -static const char * -_nmp_link_address_to_string(const NMPLinkAddress *addr, - char buf[static(NM_UTILS_HWADDR_LEN_MAX * 3)]) -{ - nm_assert(addr); - - if (addr->len > 0) { - if (!_nm_utils_hwaddr_ntoa(addr->data, addr->len, TRUE, buf, NM_UTILS_HWADDR_LEN_MAX * 3)) { - buf[0] = '\0'; - g_return_val_if_reached(buf); - } - } else - buf[0] = '\0'; - - return buf; -} - -gconstpointer -nmp_link_address_get(const NMPLinkAddress *addr, size_t *length) -{ - if (!addr || addr->len <= 0) { - NM_SET_OUT(length, 0); - return NULL; - } - - if (addr->len > NM_UTILS_HWADDR_LEN_MAX) { - NM_SET_OUT(length, 0); - g_return_val_if_reached(NULL); - } - - NM_SET_OUT(length, addr->len); - return addr->data; -} - -GBytes * -nmp_link_address_get_as_bytes(const NMPLinkAddress *addr) -{ - gconstpointer data; - size_t length; - - data = nmp_link_address_get(addr, &length); - - return length > 0 ? g_bytes_new(data, length) : NULL; -} - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG_PREFIX_NAME "platform" - -#define NMLOG_COMMON(level, name, ...) \ - char __prefix[32]; \ - const char * __p_prefix = _NMLOG_PREFIX_NAME; \ - const NMPlatform *const __self = (self); \ - const char * __name = name; \ - \ - if (__self && NM_PLATFORM_GET_PRIVATE(__self)->log_with_ptr) { \ - g_snprintf(__prefix, sizeof(__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ - __p_prefix = __prefix; \ - } \ - _nm_log(__level, \ - _NMLOG_DOMAIN, \ - 0, \ - __name, \ - NULL, \ - "%s: %s%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __p_prefix, \ - NM_PRINT_FMT_QUOTED(__name, "(", __name, ") ", "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); - -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ - NMLOG_COMMON(level, NULL, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - -#define _NMLOG2(level, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ - NMLOG_COMMON(level, name, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - -#define _NMLOG3(level, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ - NMLOG_COMMON(level, \ - ifindex > 0 ? nm_platform_link_get_name(self, ifindex) : NULL, \ - __VA_ARGS__); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = {0}; - -enum { - PROP_0, - PROP_NETNS_SUPPORT, - PROP_USE_UDEV, - PROP_LOG_WITH_PTR, - LAST_PROP, -}; - -typedef struct _NMPlatformPrivate { - bool use_udev : 1; - bool log_with_ptr : 1; - - guint ip4_dev_route_blacklist_check_id; - guint ip4_dev_route_blacklist_gc_timeout_id; - GHashTable * ip4_dev_route_blacklist_hash; - NMDedupMultiIndex *multi_idx; - NMPCache * cache; -} NMPlatformPrivate; - -G_DEFINE_TYPE(NMPlatform, nm_platform, G_TYPE_OBJECT) - -#define NM_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMPlatform, NM_IS_PLATFORM) - -/*****************************************************************************/ - -static void _ip4_dev_route_blacklist_schedule(NMPlatform *self); - -/*****************************************************************************/ - -gboolean -nm_platform_get_use_udev(NMPlatform *self) -{ - return NM_PLATFORM_GET_PRIVATE(self)->use_udev; -} - -gboolean -nm_platform_get_log_with_ptr(NMPlatform *self) -{ - return NM_PLATFORM_GET_PRIVATE(self)->log_with_ptr; -} - -/*****************************************************************************/ - -guint -_nm_platform_signal_id_get(NMPlatformSignalIdType signal_type) -{ - nm_assert(signal_type > 0 && signal_type != NM_PLATFORM_SIGNAL_ID_NONE - && signal_type < _NM_PLATFORM_SIGNAL_ID_LAST); - - return signals[signal_type]; -} - -/*****************************************************************************/ - -/* Singleton NMPlatform subclass instance and cached class object */ -NM_DEFINE_SINGLETON_INSTANCE(NMPlatform); - -NM_DEFINE_SINGLETON_REGISTER(NMPlatform); - -/* Just always initialize a @klass instance. NM_PLATFORM_GET_CLASS() - * is only a plain read on the self instance, which the compiler - * like can optimize out. - */ -#define _CHECK_SELF_VOID(self, klass) \ - NMPlatformClass *klass; \ - do { \ - g_return_if_fail(NM_IS_PLATFORM(self)); \ - klass = NM_PLATFORM_GET_CLASS(self); \ - (void) klass; \ - } while (0) - -#define _CHECK_SELF(self, klass, err_val) \ - NMPlatformClass *klass; \ - do { \ - g_return_val_if_fail(NM_IS_PLATFORM(self), err_val); \ - klass = NM_PLATFORM_GET_CLASS(self); \ - (void) klass; \ - } while (0) - -#define _CHECK_SELF_NETNS(self, klass, netns, err_val) \ - nm_auto_pop_netns NMPNetns *netns = NULL; \ - NMPlatformClass * klass; \ - do { \ - g_return_val_if_fail(NM_IS_PLATFORM(self), err_val); \ - klass = NM_PLATFORM_GET_CLASS(self); \ - (void) klass; \ - if (!nm_platform_netns_push(self, &netns)) \ - return (err_val); \ - } while (0) - -/** - * nm_platform_setup: - * @instance: the #NMPlatform instance - * - * Failing to set up #NMPlatform singleton results in a fatal error, - * as well as trying to initialize it multiple times without freeing - * it. - * - * NetworkManager will typically use only one platform object during - * its run. Test programs might want to switch platform implementations, - * though. - */ -void -nm_platform_setup(NMPlatform *instance) -{ - g_return_if_fail(NM_IS_PLATFORM(instance)); - g_return_if_fail(!singleton_instance); - - singleton_instance = instance; - - nm_singleton_instance_register(); - - nm_log_dbg(LOGD_CORE, - "setup %s singleton (" NM_HASH_OBFUSCATE_PTR_FMT ")", - "NMPlatform", - NM_HASH_OBFUSCATE_PTR(instance)); -} - -/** - * nm_platform_get: - * @self: platform instance - * - * Retrieve #NMPlatform singleton. Use this whenever you want to connect to - * #NMPlatform signals. It is an error to call it before nm_platform_setup(). - * - * Returns: (transfer none): The #NMPlatform singleton reference. - */ -NMPlatform * -nm_platform_get() -{ - g_assert(singleton_instance); - - return singleton_instance; -} - -/*****************************************************************************/ - -NMDedupMultiIndex * -nm_platform_get_multi_idx(NMPlatform *self) -{ - g_return_val_if_fail(NM_IS_PLATFORM(self), NULL); - - return NM_PLATFORM_GET_PRIVATE(self)->multi_idx; -} - -/*****************************************************************************/ - -static NM_UTILS_LOOKUP_STR_DEFINE( - _nmp_nlm_flag_to_string_lookup, - NMPNlmFlags, - NM_UTILS_LOOKUP_DEFAULT(NULL), - NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_ADD, "add"), - NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_CHANGE, "change"), - NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_REPLACE, "replace"), - NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_PREPEND, "prepend"), - NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_APPEND, "append"), - NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_TEST, "test"), - NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_F_APPEND), - NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_FMASK), - NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE), - NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_F_ECHO), ); - -#define _nmp_nlm_flag_to_string(flags) \ - ({ \ - NMPNlmFlags _flags = (flags); \ - \ - _nmp_nlm_flag_to_string_lookup(flags) \ - ?: nm_sprintf_bufa(100, "new[0x%x]", (unsigned) _flags); \ - }) - -/*****************************************************************************/ - -volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = {}; - -static const struct { - bool compile_time_default; - const char *name; - const char *desc; -} _nm_platform_kernel_support_info[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = { - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS] = - { - .compile_time_default = TRUE, - .name = "EXTENDED_IFA_FLAGS", - .desc = "IPv6 temporary addresses support", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL] = - { - .compile_time_default = TRUE, - .name = "USER_IPV6LL", - .desc = "IFLA_INET6_ADDR_GEN_MODE support", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF] = - { - .compile_time_default = (RTA_MAX >= 20 /* RTA_PREF */), - .name = "RTA_PREF", - .desc = "ability to set router preference for IPv6 routes", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV] = - { - .compile_time_default = (FRA_MAX >= 19 /* FRA_L3MDEV */), - .name = "FRA_L3MDEV", - .desc = "FRA_L3MDEV attribute for policy routing rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE] = - { - .compile_time_default = (FRA_MAX >= 20 /* FRA_UID_RANGE */), - .name = "FRA_UID_RANGE", - .desc = "FRA_UID_RANGE attribute for policy routing rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL] = - { - .compile_time_default = (FRA_MAX >= 21 /* FRA_PROTOCOL */), - .name = "FRA_PROTOCOL", - .desc = "FRA_PROTOCOL attribute for policy routing rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO] = - { - .compile_time_default = (FRA_MAX >= 22 /* FRA_IP_PROTO */), - .name = "FRA_IP_PROTO", - .desc = "FRA_IP_PROTO, FRA_SPORT_RANGE, FRA_DPORT_RANGE attributes for policy routing " - "rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED] = - { - .compile_time_default = (IFLA_BR_MAX >= 41 /* IFLA_BR_VLAN_STATS_ENABLED */), - .name = "IFLA_BR_VLAN_STATS_ENABLE", - .desc = "IFLA_BR_VLAN_STATS_ENABLE bridge link attribute", - }, -}; - -int -_nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value) -{ - volatile int *p_state; - gboolean set_default = FALSE; - - nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(_nm_platform_kernel_support_state)); - - p_state = &_nm_platform_kernel_support_state[type]; - - if (value == 0) { - set_default = TRUE; - value = _nm_platform_kernel_support_info[type].compile_time_default ? 1 : -1; - } - - nm_assert(NM_IN_SET(value, -1, 1)); - - if (!g_atomic_int_compare_and_exchange(p_state, 0, value)) { - value = g_atomic_int_get(p_state); - nm_assert(NM_IN_SET(value, -1, 1)); - return value; - } - -#undef NM_THREAD_SAFE_ON_MAIN_THREAD -#define NM_THREAD_SAFE_ON_MAIN_THREAD 0 - - if (set_default) { - nm_log_dbg(LOGD_PLATFORM, - "platform: kernel-support for %s (%s) not detected: assume %ssupported", - _nm_platform_kernel_support_info[type].name, - _nm_platform_kernel_support_info[type].desc, - value >= 0 ? "" : "not "); - } else { - nm_log_dbg(LOGD_PLATFORM, - "platform: kernel-support for %s (%s) detected: %ssupported", - _nm_platform_kernel_support_info[type].name, - _nm_platform_kernel_support_info[type].desc, - value >= 0 ? "" : "not "); - } - -#undef NM_THREAD_SAFE_ON_MAIN_THREAD -#define NM_THREAD_SAFE_ON_MAIN_THREAD 1 - - return value; -} - -/*****************************************************************************/ - -/** - * nm_platform_process_events: - * @self: platform instance - * - * Process pending events or handle pending delayed-actions. - * Effectively, this reads the netlink socket and processes - * new netlink messages. Possibly it will raise change signals. - */ -void -nm_platform_process_events(NMPlatform *self) -{ - _CHECK_SELF_VOID(self, klass); - - if (klass->process_events) - klass->process_events(self); -} - -const NMPlatformLink * -nm_platform_process_events_ensure_link(NMPlatform *self, int ifindex, const char *ifname) -{ - const NMPObject *obj; - gboolean refreshed = FALSE; - - g_return_val_if_fail(NM_IS_PLATFORM(self), NULL); - - if (ifindex <= 0 && !ifname) - return NULL; - - /* we look into the cache, whether a link for given ifindex/ifname - * exits. If not, we poll the netlink socket, maybe the event - * with the link is waiting. - * - * Then we try again to find the object. - * - * If the link is already cached the first time, we avoid polling - * the netlink socket. */ -again: - obj = nmp_cache_lookup_link_full( - nm_platform_get_cache(self), - ifindex, - ifname, - FALSE, /* also invisible. We don't care here whether udev is ready */ - NM_LINK_TYPE_NONE, - NULL, - NULL); - if (obj) - return NMP_OBJECT_CAST_LINK(obj); - if (!refreshed) { - refreshed = TRUE; - nm_platform_process_events(self); - goto again; - } - - return NULL; -} - -/*****************************************************************************/ - -/** - * nm_platform_sysctl_open_netdir: - * @self: platform instance - * @ifindex: the ifindex for which to open /sys/class/net/%s - * @out_ifname: optional output argument of the found ifname. - * - * Wraps nmp_utils_sysctl_open_netdir() by first changing into the right - * network-namespace. - * - * Returns: on success, the open file descriptor to the /sys/class/net/%s - * directory. - */ -int -nm_platform_sysctl_open_netdir(NMPlatform *self, int ifindex, char *out_ifname) -{ - const char *ifname_guess; - _CHECK_SELF_NETNS(self, klass, netns, -1); - - g_return_val_if_fail(ifindex > 0, -1); - - /* we don't have an @ifname_guess argument to make the API nicer. - * But still do a cache-lookup first. Chances are good that we have - * the right ifname cached and save if_indextoname() */ - ifname_guess = nm_platform_link_get_name(self, ifindex); - - return nmp_utils_sysctl_open_netdir(ifindex, ifname_guess, out_ifname); -} - -/** - * nm_platform_sysctl_set: - * @self: platform instance - * @pathid: if @dirfd is present, this must be the full path that is looked up. - * It is required for logging. - * @dirfd: optional file descriptor for parent directory for openat() - * @path: Absolute option path - * @value: Value to write - * - * This function is intended to be used for writing values to sysctl-style - * virtual runtime configuration files. This includes not only /proc/sys - * but also for example /sys/class. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_sysctl_set(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - const char *value) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(path, FALSE); - g_return_val_if_fail(value, FALSE); - - return klass->sysctl_set(self, pathid, dirfd, path, value); -} - -/** - * nm_platform_sysctl_set_async: - * @self: platform instance - * @pathid: if @dirfd is present, this must be the full path that is looked up - * @dirfd: optional file descriptor for parent directory for openat() - * @path: absolute option path - * @values: NULL-terminated array of strings to be written - * @callback: function called on termination - * @data: data passed to callback function - * @cancellable: to cancel the operation - * - * This function is intended to be used for writing values to sysctl-style - * virtual runtime configuration files. This includes not only /proc/sys - * but also for example /sys/class. The function does not block and returns - * immediately. The callback is always invoked, and asynchronously. The file - * is closed after writing each value and reopened to write the next one so - * that the function can be used safely on all /proc and /sys files, - * independently of how /proc/sys/kernel/sysctl_writes_strict is configured. - */ -void -nm_platform_sysctl_set_async(NMPlatform * self, - const char * pathid, - int dirfd, - const char * path, - const char *const * values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable * cancellable) -{ - _CHECK_SELF_VOID(self, klass); - - klass->sysctl_set_async(self, pathid, dirfd, path, values, callback, data, cancellable); -} - -gboolean -nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(NMPlatform *self, const char *iface, int value) -{ - const char *path; - gint64 cur; - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - - _CHECK_SELF(self, klass, FALSE); - - /* the hop-limit provided via RA is uint8. */ - if (value > 0xFF) - return FALSE; - - /* don't allow unreasonable small values */ - if (value < 10) - return FALSE; - - path = nm_utils_sysctl_ip_conf_path(AF_INET6, buf, iface, "hop_limit"); - cur = nm_platform_sysctl_get_int_checked(self, - NMP_SYSCTL_PATHID_ABSOLUTE(path), - 10, - 1, - G_MAXINT32, - -1); - - /* only allow increasing the hop-limit to avoid DOS by an attacker - * setting a low hop-limit (CVE-2015-2924, rh#1209902) */ - - if (value < cur) - return FALSE; - if (value != cur) { - char svalue[20]; - - sprintf(svalue, "%d", value); - nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), svalue); - } - - return TRUE; -} - -gboolean -nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(NMPlatform *self, - const char *iface, - guint value_ms) -{ - char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - char str[128]; - guint clamped; - - _CHECK_SELF(self, klass, FALSE); - - if (!value_ms) - return TRUE; - - /* RFC 4861 says the value can't be greater than one hour. - * Also use a reasonable lower threshold. */ - clamped = NM_CLAMP(value_ms, 100, 3600000); - nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", iface); - nm_sprintf_buf(str, "%u", clamped); - if (!nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str)) - return FALSE; - - /* Set stale time in the same way as kernel */ - nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/gc_stale_time", iface); - nm_sprintf_buf(str, "%u", clamped * 3 / 1000); - - return nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str); -} - -gboolean -nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(NMPlatform *self, - const char *iface, - guint value_ms) -{ - char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - char str[128]; - - _CHECK_SELF(self, klass, FALSE); - - if (!value_ms) - return TRUE; - - nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms", iface); - nm_sprintf_buf(str, "%u", NM_CLAMP(value_ms, 10, 3600000)); - - return nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str); -} - -/** - * nm_platform_sysctl_get: - * @self: platform instance - * @dirfd: if non-negative, used to lookup the path via openat(). - * @pathid: if @dirfd is present, this must be the full path that is looked up. - * It is required for logging. - * @path: Absolute path to sysctl - * - * Returns: (transfer full): Contents of the virtual sysctl file. - * - * If the path does not exist, %NULL is returned and %errno set to %ENOENT. - */ -char * -nm_platform_sysctl_get(NMPlatform *self, const char *pathid, int dirfd, const char *path) -{ - _CHECK_SELF(self, klass, NULL); - - g_return_val_if_fail(path, NULL); - - return klass->sysctl_get(self, pathid, dirfd, path); -} - -/** - * nm_platform_sysctl_get_int32: - * @self: platform instance - * @pathid: if @dirfd is present, this must be the full path that is looked up. - * It is required for logging. - * @dirfd: if non-negative, used to lookup the path via openat(). - * @path: Absolute path to sysctl - * @fallback: default value, if the content of path could not be read - * as decimal integer. - * - * Returns: contents of the sysctl file parsed as s32 integer, or - * @fallback on error. On error, %errno will be set to a non-zero - * value, on success %errno will be set to zero. - */ -gint32 -nm_platform_sysctl_get_int32(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - gint32 fallback) -{ - return nm_platform_sysctl_get_int_checked(self, - pathid, - dirfd, - path, - 10, - G_MININT32, - G_MAXINT32, - fallback); -} - -/** - * nm_platform_sysctl_get_int_checked: - * @self: platform instance - * @pathid: if @dirfd is present, this must be the full path that is looked up. - * It is required for logging. - * @dirfd: if non-negative, used to lookup the path via openat(). - * @path: Absolute path to sysctl - * @base: base of numeric conversion - * @min: minimal value that is still valid - * @max: maximal value that is still valid - * @fallback: default value, if the content of path could not be read - * as valid integer. - * - * Returns: contents of the sysctl file parsed as s64 integer, or - * @fallback on error. On error, %errno will be set to a non-zero - * value. On success, %errno will be set to zero. The returned value - * will always be in the range between @min and @max - * (inclusive) or @fallback. - * If the file does not exist, the fallback is returned and %errno - * is set to ENOENT. - */ -gint64 -nm_platform_sysctl_get_int_checked(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - guint base, - gint64 min, - gint64 max, - gint64 fallback) -{ - char * value = NULL; - gint32 ret; - int errsv; - - _CHECK_SELF(self, klass, fallback); - - g_return_val_if_fail(path, fallback); - - if (!path) { - errno = EINVAL; - return fallback; - } - - value = nm_platform_sysctl_get(self, pathid, dirfd, path); - if (!value) { - /* nm_platform_sysctl_get() set errno to ENOENT if the file does not exist. - * Propagate/preserve that. */ - if (errno != ENOENT) - errno = EINVAL; - return fallback; - } - - ret = _nm_utils_ascii_str_to_int64(value, base, min, max, fallback); - errsv = errno; - g_free(value); - errno = errsv; - return ret; -} - -/*****************************************************************************/ - -char * -nm_platform_sysctl_ip_conf_get(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property) -{ - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - - return nm_platform_sysctl_get( - self, - NMP_SYSCTL_PATHID_ABSOLUTE( - nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property))); -} - -gint64 -nm_platform_sysctl_ip_conf_get_int_checked(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - guint base, - gint64 min, - gint64 max, - gint64 fallback) -{ - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - - return nm_platform_sysctl_get_int_checked( - self, - NMP_SYSCTL_PATHID_ABSOLUTE( - nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property)), - base, - min, - max, - fallback); -} - -gboolean -nm_platform_sysctl_ip_conf_set(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - const char *value) -{ - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - - return nm_platform_sysctl_set( - self, - NMP_SYSCTL_PATHID_ABSOLUTE( - nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property)), - value); -} - -gboolean -nm_platform_sysctl_ip_conf_set_int64(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - gint64 value) -{ - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - char s[64]; - - return nm_platform_sysctl_set( - self, - NMP_SYSCTL_PATHID_ABSOLUTE( - nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property)), - nm_sprintf_buf(s, "%" G_GINT64_FORMAT, value)); -} - -int -nm_platform_sysctl_ip_conf_get_rp_filter_ipv4(NMPlatform *self, - const char *ifname, - gboolean consider_all, - gboolean * out_due_to_all) -{ - int val, val_all; - - NM_SET_OUT(out_due_to_all, FALSE); - - if (!ifname) - return -1; - - val = nm_platform_sysctl_ip_conf_get_int_checked(self, - AF_INET, - ifname, - "rp_filter", - 10, - 0, - 2, - -1); - if (val == -1) - return -1; - - /* the effectively used value is the rp_filter sysctl value of MAX(all,ifname). - * Note that this is the numerical MAX(), despite rp_filter "1" being more strict - * than "2". */ - if (val < 2 && consider_all && !nm_streq(ifname, "all")) { - val_all = nm_platform_sysctl_ip_conf_get_int_checked(self, - AF_INET, - "all", - "rp_filter", - 10, - 0, - 2, - val); - if (val_all > val) { - val = val_all; - NM_SET_OUT(out_due_to_all, TRUE); - } - } - - return val; -} - -/*****************************************************************************/ - -static int -_link_get_all_presort(gconstpointer p_a, gconstpointer p_b, gpointer sort_by_name) -{ - const NMPlatformLink *a = NMP_OBJECT_CAST_LINK(*((const NMPObject **) p_a)); - const NMPlatformLink *b = NMP_OBJECT_CAST_LINK(*((const NMPObject **) p_b)); - - /* Loopback always first */ - if (a->ifindex == 1) - return -1; - if (b->ifindex == 1) - return 1; - - if (GPOINTER_TO_INT(sort_by_name)) { - /* Initialized links first */ - if (a->initialized > b->initialized) - return -1; - if (a->initialized < b->initialized) - return 1; - - return strcmp(a->name, b->name); - } else - return a->ifindex - b->ifindex; -} - -/** - * nm_platform_link_get_all: - * @self: platform instance - * @sort_by_name: whether to sort by name or ifindex. - * - * Retrieve a snapshot of configuration for all links at once. The result is - * owned by the caller and should be freed with g_ptr_array_unref(). - */ -GPtrArray * -nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name) -{ - gs_unref_ptrarray GPtrArray *links = NULL; - GPtrArray * result; - guint i, nresult; - gs_unref_hashtable GHashTable *unseen = NULL; - const NMPlatformLink * item; - NMPLookup lookup; - - _CHECK_SELF(self, klass, NULL); - - nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); - links = nm_dedup_multi_objs_to_ptr_array_head(nm_platform_lookup(self, &lookup), NULL, NULL); - if (!links) - return NULL; - - for (i = 0; i < links->len;) { - if (!nmp_object_is_visible(links->pdata[i])) - g_ptr_array_remove_index_fast(links, i); - else - i++; - } - - if (links->len == 0) - return NULL; - - /* first sort the links by their ifindex or name. Below we will sort - * further by moving children/slaves to the end. */ - g_ptr_array_sort_with_data(links, _link_get_all_presort, GINT_TO_POINTER(sort_by_name)); - - unseen = g_hash_table_new(nm_direct_hash, NULL); - for (i = 0; i < links->len; i++) { - item = NMP_OBJECT_CAST_LINK(links->pdata[i]); - nm_assert(item->ifindex > 0); - if (!g_hash_table_insert(unseen, GINT_TO_POINTER(item->ifindex), NULL)) - nm_assert_not_reached(); - } - -#if NM_MORE_ASSERTS - /* Ensure that link_get_all returns a consistent and valid result. */ - for (i = 0; i < links->len; i++) { - item = NMP_OBJECT_CAST_LINK(links->pdata[i]); - - if (!item->ifindex) - continue; - if (item->master != 0) { - g_warn_if_fail(item->master > 0); - g_warn_if_fail(item->master != item->ifindex); - g_warn_if_fail(g_hash_table_contains(unseen, GINT_TO_POINTER(item->master))); - } - if (item->parent != 0) { - if (item->parent != NM_PLATFORM_LINK_OTHER_NETNS) { - g_warn_if_fail(item->parent > 0); - g_warn_if_fail(item->parent != item->ifindex); - g_warn_if_fail(g_hash_table_contains(unseen, GINT_TO_POINTER(item->parent))); - } - } - } -#endif - - /* Re-order the links list such that children/slaves come after all ancestors */ - nm_assert(g_hash_table_size(unseen) == links->len); - nresult = links->len; - result = g_ptr_array_new_full(nresult, (GDestroyNotify) nmp_object_unref); - - while (TRUE) { - gboolean found_something = FALSE; - guint first_idx = G_MAXUINT; - - for (i = 0; i < links->len; i++) { - item = NMP_OBJECT_CAST_LINK(links->pdata[i]); - - if (!item) - continue; - - g_assert(g_hash_table_contains(unseen, GINT_TO_POINTER(item->ifindex))); - - if (item->master > 0 && g_hash_table_contains(unseen, GINT_TO_POINTER(item->master))) - goto skip; - if (item->parent > 0 && g_hash_table_contains(unseen, GINT_TO_POINTER(item->parent))) - goto skip; - - g_hash_table_remove(unseen, GINT_TO_POINTER(item->ifindex)); - g_ptr_array_add(result, links->pdata[i]); - links->pdata[i] = NULL; - found_something = TRUE; - continue; -skip: - if (first_idx == G_MAXUINT) - first_idx = i; - } - - if (found_something) { - if (first_idx == G_MAXUINT) - break; - } else { - nm_assert(first_idx != G_MAXUINT); - /* There is a loop, pop the first (remaining) element from the list. - * This can happen for veth pairs where each peer is parent of the other end. */ - item = NMP_OBJECT_CAST_LINK(links->pdata[first_idx]); - nm_assert(item); - g_hash_table_remove(unseen, GINT_TO_POINTER(item->ifindex)); - g_ptr_array_add(result, links->pdata[first_idx]); - links->pdata[first_idx] = NULL; - } - nm_assert(result->len < nresult); - } - nm_assert(result->len == nresult); - - return result; -} - -/*****************************************************************************/ - -const NMPObject * -nm_platform_link_get_obj(NMPlatform *self, int ifindex, gboolean visible_only) -{ - const NMPObject *obj_cache; - - _CHECK_SELF(self, klass, NULL); - - obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(self), ifindex); - if (!obj_cache || (visible_only && !nmp_object_is_visible(obj_cache))) - return NULL; - return obj_cache; -} - -/*****************************************************************************/ - -/** - * nm_platform_link_get: - * @self: platform instance - * @ifindex: ifindex of the link - * - * Lookup the internal NMPlatformLink object. - * - * Returns: %NULL, if such a link exists or the internal - * platform link object. Do not modify the returned value. - * Also, be aware that any subsequent platform call might - * invalidate/modify the returned instance. - **/ -const NMPlatformLink * -nm_platform_link_get(NMPlatform *self, int ifindex) -{ - return NMP_OBJECT_CAST_LINK(nm_platform_link_get_obj(self, ifindex, TRUE)); -} - -/** - * nm_platform_link_get_by_ifname: - * @self: platform instance - * @ifname: the ifname - * - * Returns: the first #NMPlatformLink instance with the given name. - **/ -const NMPlatformLink * -nm_platform_link_get_by_ifname(NMPlatform *self, const char *ifname) -{ - const NMPObject *obj; - - _CHECK_SELF(self, klass, NULL); - - if (!ifname || !*ifname) - return NULL; - - obj = nmp_cache_lookup_link_full(nm_platform_get_cache(self), - 0, - ifname, - TRUE, - NM_LINK_TYPE_NONE, - NULL, - NULL); - return NMP_OBJECT_CAST_LINK(obj); -} - -struct _nm_platform_link_get_by_address_data { - gconstpointer data; - guint8 len; -}; - -static gboolean -_nm_platform_link_get_by_address_match_link(const NMPObject * obj, - struct _nm_platform_link_get_by_address_data *d) -{ - return obj->link.l_address.len == d->len && !memcmp(obj->link.l_address.data, d->data, d->len); -} - -/** - * nm_platform_link_get_by_address: - * @self: platform instance - * @address: a pointer to the binary hardware address - * @length: the size of @address in bytes - * - * Returns: the first #NMPlatformLink object with a matching - * address. - **/ -const NMPlatformLink * -nm_platform_link_get_by_address(NMPlatform * self, - NMLinkType link_type, - gconstpointer address, - size_t length) -{ - const NMPObject * obj; - struct _nm_platform_link_get_by_address_data d = { - .data = address, - .len = length, - }; - - _CHECK_SELF(self, klass, NULL); - - if (length == 0) - return NULL; - - if (length > NM_UTILS_HWADDR_LEN_MAX) - g_return_val_if_reached(NULL); - if (!address) - g_return_val_if_reached(NULL); - - obj = nmp_cache_lookup_link_full(nm_platform_get_cache(self), - 0, - NULL, - TRUE, - link_type, - (NMPObjectMatchFn) _nm_platform_link_get_by_address_match_link, - &d); - return NMP_OBJECT_CAST_LINK(obj); -} - -static int -_link_add_check_existing(NMPlatform * self, - const char * name, - NMLinkType type, - const NMPlatformLink **out_link) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get_by_ifname(self, name); - if (pllink) { - gboolean wrong_type; - - wrong_type = type != NM_LINK_TYPE_NONE && pllink->type != type; - _LOG2D("link: skip adding link due to existing interface of type %s%s%s", - nm_link_type_to_string(pllink->type), - wrong_type ? ", expected " : "", - wrong_type ? nm_link_type_to_string(type) : ""); - if (out_link) - *out_link = pllink; - if (wrong_type) - return -NME_PL_WRONG_TYPE; - return -NME_PL_EXISTS; - } - if (out_link) - *out_link = NULL; - return 0; -} - -/** - * nm_platform_link_add: - * @self: platform instance - * @type: Interface type - * @name: Interface name - * @parent: the IFLA_LINK parameter or 0. - * @address: (allow-none): set the mac address of the link - * @address_len: the length of the @address - * @extra_data: depending on @type, additional data. - * @out_link: on success, the link object - * - * Add a software interface. If the interface already exists and is of type - * @type, return -NME_PL_EXISTS and returns the link - * in @out_link. If the interface already exists and is not of type @type, - * return -NME_PL_WRONG_TYPE. - * - * Any link-changed ADDED signal will be emitted directly, before this - * function finishes. - * - * Returns: the negative nm-error on failure. - */ -int -nm_platform_link_add(NMPlatform * self, - NMLinkType type, - const char * name, - int parent, - const void * address, - size_t address_len, - guint32 mtu, - gconstpointer extra_data, - const NMPlatformLink **out_link) -{ - int r; - char addr_buf[NM_UTILS_HWADDR_LEN_MAX * 3]; - char mtu_buf[16]; - char parent_buf[64]; - char buf[512]; - - _CHECK_SELF(self, klass, -NME_BUG); - - g_return_val_if_fail(name, -NME_BUG); - g_return_val_if_fail((address != NULL) ^ (address_len == 0), -NME_BUG); - g_return_val_if_fail(address_len <= NM_UTILS_HWADDR_LEN_MAX, -NME_BUG); - g_return_val_if_fail(parent >= 0, -NME_BUG); - - r = _link_add_check_existing(self, name, type, out_link); - if (r < 0) - return r; - - _LOG2D("link: adding link: " - "%s " /* type */ - "\"%s\"" /* name */ - "%s%s" /* parent */ - "%s%s" /* address */ - "%s%s" /* mtu */ - "%s" /* extra_data */ - "", - nm_link_type_to_string(type), - name, - parent > 0 ? ", parent " : "", - parent > 0 ? nm_sprintf_buf(parent_buf, "%d", parent) : "", - address ? ", address: " : "", - address ? _nm_utils_hwaddr_ntoa(address, address_len, FALSE, addr_buf, sizeof(addr_buf)) - : "", - mtu ? ", mtu: " : "", - mtu ? nm_sprintf_buf(mtu_buf, "%u", mtu) : "", - ({ - char *buf_p = buf; - gsize buf_len = sizeof(buf); - - buf[0] = '\0'; - - switch (type) { - case NM_LINK_TYPE_BRIDGE: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_bridge_to_string((const NMPlatformLnkBridge *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_VLAN: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_vlan_to_string((const NMPlatformLnkVlan *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_VRF: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_vrf_to_string((const NMPlatformLnkVrf *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_VXLAN: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_vxlan_to_string((const NMPlatformLnkVxlan *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_VETH: - nm_sprintf_buf(buf, ", veth-peer \"%s\"", (const char *) extra_data); - break; - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_gre_to_string((const NMPlatformLnkGre *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_SIT: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_sit_to_string((const NMPlatformLnkSit *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_IP6TNL: - case NM_LINK_TYPE_IP6GRE: - case NM_LINK_TYPE_IP6GRETAP: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_ip6tnl_to_string((const NMPlatformLnkIp6Tnl *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_IPIP: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_ipip_to_string((const NMPlatformLnkIpIp *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_MACSEC: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_macsec_to_string((const NMPlatformLnkMacsec *) extra_data, - buf_p, - buf_len); - break; - case NM_LINK_TYPE_MACVLAN: - case NM_LINK_TYPE_MACVTAP: - nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); - nm_platform_lnk_macvlan_to_string((const NMPlatformLnkMacvlan *) extra_data, - buf_p, - buf_len); - break; - default: - nm_assert(!extra_data); - break; - } - - buf; - })); - - return klass - ->link_add(self, type, name, parent, address, address_len, mtu, extra_data, out_link); -} - -/** - * nm_platform_link_delete: - * @self: platform instance - * @ifindex: Interface index - */ -gboolean -nm_platform_link_delete(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - _LOG3D("link: deleting"); - return klass->link_delete(self, ifindex); -} - -/** - * nm_platform_link_set_netns: - * @self: platform instance - * @ifindex: Interface index - * @netns_fd: the file descriptor for the new netns. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_link_set_netns(NMPlatform *self, int ifindex, int netns_fd) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(netns_fd > 0, FALSE); - - _LOG3D("link: move link to network namespace with fd %d", netns_fd); - return klass->link_set_netns(self, ifindex, netns_fd); -} - -/** - * nm_platform_link_get_index: - * @self: platform instance - * @name: Interface name - * - * Returns: The interface index corresponding to the given interface name - * or 0. Interface name is owned by #NMPlatform, don't free it. - */ -int -nm_platform_link_get_ifindex(NMPlatform *self, const char *name) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get_by_ifname(self, name); - return pllink ? pllink->ifindex : 0; -} - -const char * -nm_platform_if_indextoname(NMPlatform *self, int ifindex, char out_ifname[static 16 /* IFNAMSIZ */]) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - return nmp_utils_if_indextoname(ifindex, out_ifname); -} - -int -nm_platform_if_nametoindex(NMPlatform *self, const char *ifname) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - return nmp_utils_if_nametoindex(ifname); -} - -/** - * nm_platform_link_get_name: - * @self: platform instance - * @name: Interface name - * - * Returns: The interface name corresponding to the given interface index - * or %NULL. - */ -const char * -nm_platform_link_get_name(NMPlatform *self, int ifindex) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, ifindex); - return pllink ? pllink->name : NULL; -} - -/** - * nm_platform_link_get_type: - * @self: platform instance - * @ifindex: Interface index. - * - * Returns: Link type constant as defined in nm-platform.h. On error, - * NM_LINK_TYPE_NONE is returned. - */ -NMLinkType -nm_platform_link_get_type(NMPlatform *self, int ifindex) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, ifindex); - return pllink ? pllink->type : NM_LINK_TYPE_NONE; -} - -/** - * nm_platform_link_get_type_name: - * @self: platform instance - * @ifindex: Interface index. - * - * Returns: A string describing the type of link. In some cases this - * may be more specific than nm_platform_link_get_type(), but in - * other cases it may not. On error, %NULL is returned. - */ -const char * -nm_platform_link_get_type_name(NMPlatform *self, int ifindex) -{ - const NMPObject *obj; - - obj = nm_platform_link_get_obj(self, ifindex, TRUE); - if (!obj) - return NULL; - - if (obj->link.type != NM_LINK_TYPE_UNKNOWN) { - /* We could detect the @link_type. In this case the function returns - * our internal module names, which differs from rtnl_link_get_type(): - * - NM_LINK_TYPE_INFINIBAND (gives "infiniband", instead of "ipoib") - * - NM_LINK_TYPE_TAP (gives "tap", instead of "tun"). - * Note that this functions is only used by NMDeviceGeneric to - * set type_description. */ - return nm_link_type_to_string(obj->link.type); - } - /* Link type not detected. Fallback to rtnl_link_get_type()/IFLA_INFO_KIND. */ - return obj->link.kind ?: "unknown"; -} - -static gboolean -link_get_udev_property(NMPlatform *self, int ifindex, const char *name, const char **out_value) -{ - struct udev_device *udevice = NULL; - const char * uproperty; - - udevice = nm_platform_link_get_udev_device(self, ifindex); - if (!udevice) - return FALSE; - - uproperty = udev_device_get_property_value(udevice, name); - if (!uproperty) - return FALSE; - - NM_SET_OUT(out_value, uproperty); - return TRUE; -} - -/** - * nm_platform_link_get_unmanaged: - * @self: platform instance - * @ifindex: interface index - * @unmanaged: management status (in case %TRUE is returned) - * - * Returns: %TRUE if platform overrides NM default-unmanaged status, - * %FALSE otherwise (with @unmanaged unmodified). - */ -gboolean -nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex, gboolean *unmanaged) -{ - const char *value; - - if (link_get_udev_property(self, ifindex, "NM_UNMANAGED", &value)) { - NM_SET_OUT(unmanaged, nm_udev_utils_property_as_boolean(value)); - return TRUE; - } - - return FALSE; -} - -/** - * nm_platform_link_is_software: - * @self: platform instance - * @ifindex: Interface index. - * - * Returns: %TRUE if ifindex belongs to a software interface, not backed by - * a physical device. - */ -gboolean -nm_platform_link_is_software(NMPlatform *self, int ifindex) -{ - return nm_link_type_is_software(nm_platform_link_get_type(self, ifindex)); -} - -/** - * nm_platform_link_supports_slaves: - * @self: platform instance - * @ifindex: Interface index. - * - * Returns: %TRUE if ifindex belongs to an interface capable of enslaving - * other interfaces. - */ -gboolean -nm_platform_link_supports_slaves(NMPlatform *self, int ifindex) -{ - return nm_link_type_supports_slaves(nm_platform_link_get_type(self, ifindex)); -} - -/** - * nm_platform_link_refresh: - * @self: platform instance - * @ifindex: Interface index - * - * Reload the cache for ifindex synchronously. - */ -gboolean -nm_platform_link_refresh(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - if (klass->link_refresh) - return klass->link_refresh(self, ifindex); - - return TRUE; -} - -int -nm_platform_link_get_ifi_flags(NMPlatform *self, int ifindex, guint requested_flags) -{ - const NMPlatformLink *pllink; - - /* include invisible links (only in netlink, not udev). */ - pllink = NMP_OBJECT_CAST_LINK(nm_platform_link_get_obj(self, ifindex, FALSE)); - if (!pllink) - return -ENODEV; - - /* Errors are signaled as negative values. That means, you cannot request - * the most significant bit (2^31) with this API. Assert against that. */ - nm_assert((int) requested_flags >= 0); - nm_assert(requested_flags < (guint) G_MAXINT); - - return (int) (pllink->n_ifi_flags & requested_flags); -} - -/** - * nm_platform_link_is_up: - * @self: platform instance - * @ifindex: Interface index - * - * Check if the interface is up. - */ -gboolean -nm_platform_link_is_up(NMPlatform *self, int ifindex) -{ - return nm_platform_link_get_ifi_flags(self, ifindex, IFF_UP) == IFF_UP; -} - -/** - * nm_platform_link_is_connected: - * @self: platform instance - * @ifindex: Interface index - * - * Check if the interface is connected. - */ -gboolean -nm_platform_link_is_connected(NMPlatform *self, int ifindex) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, ifindex); - return pllink ? pllink->connected : FALSE; -} - -/** - * nm_platform_link_uses_arp: - * @self: platform instance - * @ifindex: Interface index - * - * Check if the interface is configured to use ARP. - */ -gboolean -nm_platform_link_uses_arp(NMPlatform *self, int ifindex) -{ - int f; - - f = nm_platform_link_get_ifi_flags(self, ifindex, IFF_NOARP); - - if (f < 0) - return FALSE; - if (f == IFF_NOARP) - return FALSE; - return TRUE; -} - -/** - * nm_platform_link_set_ipv6_token: - * @self: platform instance - * @ifindex: Interface index - * @iid: Tokenized interface identifier - * - * Sets then IPv6 tokenized interface identifier. - * - * Returns: %TRUE a tokenized identifier was available - */ -gboolean -nm_platform_link_set_ipv6_token(NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - if (klass->link_set_token) - return klass->link_set_token(self, ifindex, iid); - return FALSE; -} - -const char * -nm_platform_link_get_udi(NMPlatform *self, int ifindex) -{ - struct udev_device *device; - - device = nm_platform_link_get_udev_device(self, ifindex); - return device ? udev_device_get_syspath(device) : NULL; -} - -const char * -nm_platform_link_get_path(NMPlatform *self, int ifindex) -{ - const char *value = NULL; - - link_get_udev_property(self, ifindex, "ID_PATH", &value); - - return value; -} - -struct udev_device * -nm_platform_link_get_udev_device(NMPlatform *self, int ifindex) -{ - const NMPObject *obj_cache; - - obj_cache = nm_platform_link_get_obj(self, ifindex, FALSE); - return obj_cache ? obj_cache->_link.udev.device : NULL; -} - -/** - * nm_platform_link_get_user_ip6vll_enabled: - * @self: platform instance - * @ifindex: Interface index - * - * Check whether NM handles IPv6LL address creation for the link. If the - * platform or OS doesn't support changing the IPv6LL address mode, this call - * will fail and return %FALSE. - * - * Returns: %TRUE if NM handles the IPv6LL address for @ifindex - */ -gboolean -nm_platform_link_get_user_ipv6ll_enabled(NMPlatform *self, int ifindex) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, ifindex); - if (pllink && pllink->inet6_addr_gen_mode_inv) - return _nm_platform_uint8_inv(pllink->inet6_addr_gen_mode_inv) == NM_IN6_ADDR_GEN_MODE_NONE; - return FALSE; -} - -/** - * nm_platform_link_set_user_ip6vll_enabled: - * @self: platform instance - * @ifindex: Interface index - * - * Set whether NM handles IPv6LL address creation for the link. If the - * platform or OS doesn't support changing the IPv6LL address mode, this call - * will fail and return %FALSE. - * - * Returns: the negative nm-error on failure. - */ -int -nm_platform_link_set_user_ipv6ll_enabled(NMPlatform *self, int ifindex, gboolean enabled) -{ - _CHECK_SELF(self, klass, -NME_BUG); - - g_return_val_if_fail(ifindex > 0, -NME_BUG); - - return klass->link_set_user_ipv6ll_enabled(self, ifindex, enabled); -} - -/** - * nm_platform_link_set_address: - * @self: platform instance - * @ifindex: Interface index - * @address: The new MAC address - * - * Set interface MAC address. - */ -int -nm_platform_link_set_address(NMPlatform *self, int ifindex, gconstpointer address, size_t length) -{ - gs_free char *mac = NULL; - - _CHECK_SELF(self, klass, -NME_BUG); - - g_return_val_if_fail(ifindex > 0, -NME_BUG); - g_return_val_if_fail(address, -NME_BUG); - g_return_val_if_fail(length > 0, -NME_BUG); - - _LOG3D("link: setting hardware address to %s", (mac = nm_utils_hwaddr_ntoa(address, length))); - return klass->link_set_address(self, ifindex, address, length); -} - -/** - * nm_platform_link_get_address: - * @self: platform instance - * @ifindex: Interface index - * @length: Pointer to a variable to store address length - * - * Returns: the interface hardware address as an array of bytes of - * length @length. - */ -gconstpointer -nm_platform_link_get_address(NMPlatform *self, int ifindex, size_t *length) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, ifindex); - return nmp_link_address_get(pllink ? &pllink->l_address : NULL, length); -} - -/** - * nm_platform_link_get_permanent_address: - * @self: platform instance - * @ifindex: Interface index - * @buf: buffer of at least %NM_UTILS_HWADDR_LEN_MAX bytes, on success - * the permanent hardware address - * @length: Pointer to a variable to store address length - * - * Returns: %TRUE on success, %FALSE on failure to read the permanent hardware - * address. - */ -gboolean -nm_platform_link_get_permanent_address(NMPlatform *self, int ifindex, guint8 *buf, size_t *length) -{ - _CHECK_SELF(self, klass, FALSE); - - if (length) - *length = 0; - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(buf, FALSE); - g_return_val_if_fail(length, FALSE); - - if (klass->link_get_permanent_address) - return klass->link_get_permanent_address(self, ifindex, buf, length); - return FALSE; -} - -gboolean -nm_platform_link_supports_carrier_detect(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - return klass->link_supports_carrier_detect(self, ifindex); -} - -gboolean -nm_platform_link_supports_vlans(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - return klass->link_supports_vlans(self, ifindex); -} - -gboolean -nm_platform_link_supports_sriov(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - return klass->link_supports_sriov(self, ifindex); -} - -/** - * nm_platform_link_set_sriov_params: - * @self: platform instance - * @ifindex: the index of the interface to change - * @num_vfs: the number of VFs to create - * @autoprobe: the new autoprobe-drivers value (pass - * %NM_OPTION_BOOL_DEFAULT to keep current value) - * @callback: called when the operation finishes - * @callback_data: data passed to @callback - * @cancellable: cancellable to abort the operation - * - * Sets SR-IOV parameters asynchronously without - * blocking the main thread. The callback function is - * always invoked, and asynchronously. - */ -void -nm_platform_link_set_sriov_params_async(NMPlatform * self, - int ifindex, - guint num_vfs, - NMOptionBool autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data, - GCancellable * cancellable) -{ - _CHECK_SELF_VOID(self, klass); - - g_return_if_fail(ifindex > 0); - - _LOG3D("link: setting %u total VFs and autoprobe %d", num_vfs, (int) autoprobe); - klass->link_set_sriov_params_async(self, - ifindex, - num_vfs, - autoprobe, - callback, - callback_data, - cancellable); -} - -gboolean -nm_platform_link_set_sriov_vfs(NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs) -{ - guint i; - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - _LOG3D("link: setting VFs"); - for (i = 0; vfs[i]; i++) { - const NMPlatformVF *vf = vfs[i]; - - _LOG3D("link: VF %s", nm_platform_vf_to_string(vf, NULL, 0)); - } - - return klass->link_set_sriov_vfs(self, ifindex, vfs); -} - -gboolean -nm_platform_link_set_bridge_vlans(NMPlatform * self, - int ifindex, - gboolean on_master, - const NMPlatformBridgeVlan *const *vlans) -{ - guint i; - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - _LOG3D("link: %s bridge VLANs on %s", - vlans ? "setting" : "clearing", - on_master ? "master" : "self"); - if (vlans) { - for (i = 0; vlans[i]; i++) { - const NMPlatformBridgeVlan *vlan = vlans[i]; - - _LOG3D("link: bridge VLAN %s", nm_platform_bridge_vlan_to_string(vlan, NULL, 0)); - } - } - - return klass->link_set_bridge_vlans(self, ifindex, on_master, vlans); -} - -/** - * nm_platform_link_set_up: - * @self: platform instance - * @ifindex: Interface index - * @out_no_firmware: (allow-none): if the failure reason is due to missing firmware. - * - * Bring the interface up. - */ -gboolean -nm_platform_link_set_up(NMPlatform *self, int ifindex, gboolean *out_no_firmware) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - _LOG3D("link: setting up"); - return klass->link_set_up(self, ifindex, out_no_firmware); -} - -/** - * nm_platform_link_set_down: - * @self: platform instance - * @ifindex: Interface index - * - * Take the interface down. - */ -gboolean -nm_platform_link_set_down(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - _LOG3D("link: setting down"); - return klass->link_set_down(self, ifindex); -} - -/** - * nm_platform_link_set_arp: - * @self: platform instance - * @ifindex: Interface index - * - * Enable ARP on the interface. - */ -gboolean -nm_platform_link_set_arp(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - _LOG3D("link: setting arp"); - return klass->link_set_arp(self, ifindex); -} - -/** - * nm_platform_link_set_noarp: - * @self: platform instance - * @ifindex: Interface index - * - * Disable ARP on the interface. - */ -gboolean -nm_platform_link_set_noarp(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - _LOG3D("link: setting noarp"); - return klass->link_set_noarp(self, ifindex); -} - -/** - * nm_platform_link_set_mtu: - * @self: platform instance - * @ifindex: Interface index - * @mtu: The new MTU value - * - * Set interface MTU. - */ -int -nm_platform_link_set_mtu(NMPlatform *self, int ifindex, guint32 mtu) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - g_return_val_if_fail(mtu > 0, FALSE); - - _LOG3D("link: setting mtu %" G_GUINT32_FORMAT, mtu); - return klass->link_set_mtu(self, ifindex, mtu); -} - -/** - * nm_platform_link_get_mtu: - * @self: platform instance - * @ifindex: Interface index - * - * Returns: MTU value for the interface or 0 on error. - */ -guint32 -nm_platform_link_get_mtu(NMPlatform *self, int ifindex) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, ifindex); - return pllink ? pllink->mtu : 0; -} - -/** - * nm_platform_link_set_name: - * @self: platform instance - * @ifindex: Interface index - * @name: The new interface name - * - * Set interface name. - */ -gboolean -nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *name) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - g_return_val_if_fail(name, FALSE); - - _LOG3D("link: setting name %s", name); - - if (strlen(name) + 1 > IFNAMSIZ) - return FALSE; - - return klass->link_set_name(self, ifindex, name); -} - -/** - * nm_platform_link_get_physical_port_id: - * @self: platform instance - * @ifindex: Interface index - * - * The physical port ID, if present, indicates some unique identifier of - * the parent interface (eg, the physical port of which this link is a child). - * Two links that report the same physical port ID can be assumed to be - * children of the same physical port and may share resources that limit - * their abilities. - * - * Returns: physical port ID for the interface, or %NULL on error - * or if the interface has no physical port ID. - */ -char * -nm_platform_link_get_physical_port_id(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, NULL); - - g_return_val_if_fail(ifindex >= 0, NULL); - - if (klass->link_get_physical_port_id) - return klass->link_get_physical_port_id(self, ifindex); - return NULL; -} - -/** - * nm_platform_link_get_dev_id: - * @self: platform instance - * @ifindex: Interface index - * - * In contrast to the physical device ID (which indicates which parent a - * child has) the device ID differentiates sibling devices that may share - * the same MAC address. - * - * Returns: device ID for the interface, or 0 on error or if the - * interface has no device ID. - */ -guint -nm_platform_link_get_dev_id(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, 0); - - g_return_val_if_fail(ifindex >= 0, 0); - - if (klass->link_get_dev_id) - return klass->link_get_dev_id(self, ifindex); - return 0; -} - -/** - * nm_platform_link_get_wake_onlan: - * @self: platform instance - * @ifindex: Interface index - * - * Returns: the "Wake-on-LAN" status for @ifindex. - */ -gboolean -nm_platform_link_get_wake_on_lan(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - if (klass->link_get_wake_on_lan) - return klass->link_get_wake_on_lan(self, ifindex); - return FALSE; -} - -/** - * nm_platform_link_get_driver_info: - * @self: platform instance - * @ifindex: Interface index - * @out_driver_name: (transfer full): on success, the driver name if available - * @out_driver_version: (transfer full): on success, the driver version if available - * @out_fw_version: (transfer full): on success, the firmware version if available - * - * Returns: %TRUE on success (though @out_driver_name, @out_driver_version and - * @out_fw_version can be %NULL if no information was available), %FALSE on - * failure. - */ -gboolean -nm_platform_link_get_driver_info(NMPlatform *self, - int ifindex, - char ** out_driver_name, - char ** out_driver_version, - char ** out_fw_version) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex >= 0, FALSE); - - return klass->link_get_driver_info(self, - ifindex, - out_driver_name, - out_driver_version, - out_fw_version); -} - -/** - * nm_platform_link_enslave: - * @self: platform instance - * @master: Interface index of the master - * @ifindex: Interface index of the slave - * - * Enslave @ifindex to @master. - */ -gboolean -nm_platform_link_enslave(NMPlatform *self, int master, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(master > 0, FALSE); - g_return_val_if_fail(ifindex > 0, FALSE); - - _LOG3D("link: enslaving to master '%s'", nm_platform_link_get_name(self, master)); - return klass->link_enslave(self, master, ifindex); -} - -/** - * nm_platform_link_release: - * @self: platform instance - * @master: Interface index of the master - * @ifindex: Interface index of the slave - * - * Release @slave from @master. - */ -gboolean -nm_platform_link_release(NMPlatform *self, int master, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(master > 0, FALSE); - g_return_val_if_fail(ifindex > 0, FALSE); - - if (nm_platform_link_get_master(self, ifindex) != master) - return FALSE; - - _LOG3D("link: releasing from master '%s'", nm_platform_link_get_name(self, master)); - return klass->link_release(self, master, ifindex); -} - -/** - * nm_platform_link_get_master: - * @self: platform instance - * @slave: Interface index of the slave. - * - * Returns: Interface index of the slave's master. - */ -int -nm_platform_link_get_master(NMPlatform *self, int slave) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get(self, slave); - return pllink ? pllink->master : 0; -} - -/*****************************************************************************/ - -gboolean -nm_platform_link_can_assume(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - if (klass->link_can_assume) - return klass->link_can_assume(self, ifindex); - g_return_val_if_reached(FALSE); -} - -/*****************************************************************************/ - -/** - * nm_platform_link_get_lnk: - * @self: the platform instance - * @ifindex: the link ifindex to lookup - * @link_type: filter by link-type. - * @out_link: (allow-none): returns the platform link instance - * - * If the function returns %NULL, that could mean that no such ifindex - * exists, of that the link has no lnk data. You can find that out - * by checking @out_link. @out_link will always be set if a link - * with @ifindex exists. - * - * If @link_type is %NM_LINK_TYPE_NONE, the function returns the lnk - * object if it is present. If you set link-type, you can be sure - * that only a link type of the matching type is returned (or %NULL). - * - * Returns: the internal link lnk object. The returned object - * is owned by the platform cache and must not be modified. Note - * however, that the object is guaranteed to be immutable, so - * you can safely take a reference and keep it for yourself - * (but don't modify it). - */ -const NMPObject * -nm_platform_link_get_lnk(NMPlatform * self, - int ifindex, - NMLinkType link_type, - const NMPlatformLink **out_link) -{ - const NMPObject *obj; - - obj = nm_platform_link_get_obj(self, ifindex, TRUE); - if (!obj) { - NM_SET_OUT(out_link, NULL); - return NULL; - } - - NM_SET_OUT(out_link, &obj->link); - - if (!obj->_link.netlink.lnk) - return NULL; - if (link_type != NM_LINK_TYPE_NONE - && (link_type != obj->link.type - || link_type != NMP_OBJECT_GET_CLASS(obj->_link.netlink.lnk)->lnk_link_type)) - return NULL; - - return obj->_link.netlink.lnk; -} - -static gconstpointer -_link_get_lnk(NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) -{ - const NMPObject *lnk; - - lnk = nm_platform_link_get_lnk(self, ifindex, link_type, out_link); - return lnk ? &lnk->object : NULL; -} - -const NMPlatformLnkBridge * -nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_BRIDGE, out_link); -} - -const NMPlatformLnkGre * -nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GRE, out_link); -} - -const NMPlatformLnkGre * -nm_platform_link_get_lnk_gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GRETAP, out_link); -} - -const NMPlatformLnkInfiniband * -nm_platform_link_get_lnk_infiniband(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link); -} - -const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6tnl(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IP6TNL, out_link); -} - -const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IP6GRE, out_link); -} - -const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IP6GRETAP, out_link); -} - -const NMPlatformLnkIpIp * -nm_platform_link_get_lnk_ipip(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IPIP, out_link); -} - -const NMPlatformLnkMacsec * -nm_platform_link_get_lnk_macsec(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_MACSEC, out_link); -} - -const NMPlatformLnkMacvlan * -nm_platform_link_get_lnk_macvlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_MACVLAN, out_link); -} - -const NMPlatformLnkMacvlan * -nm_platform_link_get_lnk_macvtap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_MACVTAP, out_link); -} - -const NMPlatformLnkSit * -nm_platform_link_get_lnk_sit(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_SIT, out_link); -} - -const NMPlatformLnkTun * -nm_platform_link_get_lnk_tun(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_TUN, out_link); -} - -const NMPlatformLnkVlan * -nm_platform_link_get_lnk_vlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_VLAN, out_link); -} - -const NMPlatformLnkVrf * -nm_platform_link_get_lnk_vrf(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_VRF, out_link); -} - -const NMPlatformLnkVxlan * -nm_platform_link_get_lnk_vxlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_VXLAN, out_link); -} - -const NMPlatformLnkWireGuard * -nm_platform_link_get_lnk_wireguard(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) -{ - return _link_get_lnk(self, ifindex, NM_LINK_TYPE_WIREGUARD, out_link); -} - -/*****************************************************************************/ - -static NM_UTILS_FLAGS2STR_DEFINE( - _wireguard_change_flags_to_string, - NMPlatformWireGuardChangeFlags, - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE, "none"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS, "replace-peers"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY, "has-private-key"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT, "has-listen-port"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK, "has-fwmark"), ); - -static NM_UTILS_FLAGS2STR_DEFINE( - _wireguard_change_peer_flags_to_string, - NMPlatformWireGuardChangePeerFlags, - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE, "none"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME, "remove"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY, "psk"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL, "ka"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT, "ep"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, "aips"), - NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS, "remove-aips"), ); - -int -nm_platform_link_wireguard_change(NMPlatform * self, - int ifindex, - const NMPlatformLnkWireGuard * lnk_wireguard, - const NMPWireGuardPeer * peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags) -{ - _CHECK_SELF(self, klass, -NME_BUG); - - nm_assert(klass->link_wireguard_change); - - if (_LOGD_ENABLED()) { - char buf_lnk[256]; - char buf_peers[512]; - char buf_change_flags[100]; - - buf_peers[0] = '\0'; - if (peers_len > 0) { - char *b = buf_peers; - gsize len = sizeof(buf_peers); - guint i; - - nm_utils_strbuf_append_str(&b, &len, " { "); - for (i = 0; i < peers_len; i++) { - nm_utils_strbuf_append_str(&b, &len, " { "); - nm_platform_wireguard_peer_to_string(&peers[i], b, len); - nm_utils_strbuf_seek_end(&b, &len); - if (peer_flags) { - nm_utils_strbuf_append( - &b, - &len, - " (%s)", - _wireguard_change_peer_flags_to_string(peer_flags[i], - buf_change_flags, - sizeof(buf_change_flags))); - } - nm_utils_strbuf_append_str(&b, &len, " } "); - } - nm_utils_strbuf_append_str(&b, &len, "}"); - } - - _LOG3D("link: change wireguard ifindex %d, %s, (%s), %u peers%s", - ifindex, - nm_platform_lnk_wireguard_to_string(lnk_wireguard, buf_lnk, sizeof(buf_lnk)), - _wireguard_change_flags_to_string(change_flags, - buf_change_flags, - sizeof(buf_change_flags)), - peers_len, - buf_peers); - } - - return klass->link_wireguard_change(self, - ifindex, - lnk_wireguard, - peers, - peer_flags, - peers_len, - change_flags); -} - -/*****************************************************************************/ - -/** - * nm_platform_link_tun_add: - * @self: platform instance - * @name: new interface name - * @tap: whether the interface is a TAP - * @owner: interface owner or -1 - * @group: interface group or -1 - * @pi: whether to clear the IFF_NO_PI flag - * @vnet_hdr: whether to set the IFF_VNET_HDR flag - * @multi_queue: whether to set the IFF_MULTI_QUEUE flag - * @out_link: on success, the link object - * @out_fd: (allow-none): if give, return the file descriptor for the - * created device. Note that when creating a non-persistent device, - * this argument is mandatory, otherwise it makes no sense - * to create such an interface. - * The caller is responsible for closing this file descriptor. - * - * Create a TUN or TAP interface. - */ -int -nm_platform_link_tun_add(NMPlatform * self, - const char * name, - const NMPlatformLnkTun *props, - const NMPlatformLink ** out_link, - int * out_fd) -{ - char b[255]; - int r; - - _CHECK_SELF(self, klass, -NME_BUG); - - g_return_val_if_fail(name, -NME_BUG); - g_return_val_if_fail(props, -NME_BUG); - g_return_val_if_fail(NM_IN_SET(props->type, IFF_TUN, IFF_TAP), -NME_BUG); - - /* creating a non-persistent device requires that the caller handles - * the file descriptor. */ - g_return_val_if_fail(props->persist || out_fd, -NME_BUG); - - NM_SET_OUT(out_fd, -1); - - r = _link_add_check_existing(self, name, NM_LINK_TYPE_TUN, out_link); - if (r < 0) - return r; - - _LOG2D("link: adding link %s", nm_platform_lnk_tun_to_string(props, b, sizeof(b))); - - if (!klass->link_tun_add(self, name, props, out_link, out_fd)) - return -NME_UNSPEC; - return 0; -} - -gboolean -nm_platform_link_6lowpan_get_properties(NMPlatform *self, int ifindex, int *out_parent) -{ - const NMPlatformLink *plink; - - plink = nm_platform_link_get(self, ifindex); - if (!plink) - return FALSE; - - if (plink->type != NM_LINK_TYPE_6LOWPAN) - return FALSE; - - if (plink->parent != 0) { - NM_SET_OUT(out_parent, plink->parent); - return TRUE; - } - - /* As of 4.16 kernel does not expose the peer_ifindex as IFA_LINK. - * Find the WPAN device with the same MAC address. */ - if (out_parent) { - const NMPlatformLink *parent_plink; - - parent_plink = nm_platform_link_get_by_address(self, - NM_LINK_TYPE_WPAN, - plink->l_address.data, - plink->l_address.len); - NM_SET_OUT(out_parent, parent_plink ? parent_plink->ifindex : -1); - } - - return TRUE; -} - -/*****************************************************************************/ - -static gboolean -link_set_option(NMPlatform *self, - int ifindex, - const char *category, - const char *option, - const char *value) -{ - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - const char * path; - - if (!category || !option) - return FALSE; - - dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname_verified); - if (dirfd < 0) - return FALSE; - - path = - nm_sprintf_buf_unsafe_a(strlen(category) + strlen(option) + 2, "%s/%s", category, option); - return nm_platform_sysctl_set(self, - NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname_verified, path), - value); -} - -static char * -link_get_option(NMPlatform *self, int ifindex, const char *category, const char *option) -{ - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - const char * path; - - if (!category || !option) - return NULL; - - dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname_verified); - if (dirfd < 0) - return NULL; - - path = - nm_sprintf_buf_unsafe_a(strlen(category) + strlen(option) + 2, "%s/%s", category, option); - return nm_platform_sysctl_get(self, - NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname_verified, path)); -} - -static const char * -master_category(NMPlatform *self, int master) -{ - switch (nm_platform_link_get_type(self, master)) { - case NM_LINK_TYPE_BRIDGE: - return "bridge"; - case NM_LINK_TYPE_BOND: - return "bonding"; - default: - return NULL; - } -} - -static const char * -slave_category(NMPlatform *self, int slave) -{ - int master = nm_platform_link_get_master(self, slave); - - if (master <= 0) - return NULL; - - switch (nm_platform_link_get_type(self, master)) { - case NM_LINK_TYPE_BRIDGE: - return "brport"; - default: - return NULL; - } -} - -gboolean -nm_platform_sysctl_master_set_option(NMPlatform *self, - int ifindex, - const char *option, - const char *value) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(option, FALSE); - g_return_val_if_fail(value, FALSE); - - return link_set_option(self, ifindex, master_category(self, ifindex), option, value); -} - -char * -nm_platform_sysctl_master_get_option(NMPlatform *self, int ifindex, const char *option) -{ - _CHECK_SELF(self, klass, NULL); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(option, FALSE); - - return link_get_option(self, ifindex, master_category(self, ifindex), option); -} - -gboolean -nm_platform_sysctl_slave_set_option(NMPlatform *self, - int ifindex, - const char *option, - const char *value) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(option, FALSE); - g_return_val_if_fail(value, FALSE); - - return link_set_option(self, ifindex, slave_category(self, ifindex), option, value); -} - -char * -nm_platform_sysctl_slave_get_option(NMPlatform *self, int ifindex, const char *option) -{ - _CHECK_SELF(self, klass, NULL); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(option, FALSE); - - return link_get_option(self, ifindex, slave_category(self, ifindex), option); -} - -/*****************************************************************************/ - -gboolean -nm_platform_link_vlan_change(NMPlatform * self, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map) -{ - _CHECK_SELF(self, klass, FALSE); - - nm_assert(klass->link_vlan_change); - - g_return_val_if_fail(!n_ingress_map || ingress_map, FALSE); - g_return_val_if_fail(!n_egress_map || egress_map, FALSE); - - flags_set &= flags_mask; - - if (_LOGD_ENABLED()) { - char buf[512]; - char *b = buf; - gsize len, i; - - b[0] = '\0'; - len = sizeof(buf); - - if (flags_mask) - nm_utils_strbuf_append(&b, - &len, - " flags 0x%x/0x%x", - (unsigned) flags_set, - (unsigned) flags_mask); - - if (ingress_reset_all || n_ingress_map) { - nm_utils_strbuf_append_str(&b, &len, " ingress-qos-map"); - nm_platform_vlan_qos_mapping_to_string("", ingress_map, n_ingress_map, b, len); - i = strlen(b); - b += i; - len -= i; - if (ingress_reset_all) - nm_utils_strbuf_append_str(&b, &len, " (reset-all)"); - } - - if (egress_reset_all || n_egress_map) { - nm_utils_strbuf_append_str(&b, &len, " egress-qos-map"); - nm_platform_vlan_qos_mapping_to_string("", egress_map, n_egress_map, b, len); - i = strlen(b); - b += i; - len -= i; - if (egress_reset_all) - nm_utils_strbuf_append_str(&b, &len, " (reset-all)"); - } - - _LOG3D("link: change vlan %s", buf); - } - return klass->link_vlan_change(self, - ifindex, - flags_mask, - flags_set, - ingress_reset_all, - ingress_map, - n_ingress_map, - egress_reset_all, - egress_map, - n_egress_map); -} - -gboolean -nm_platform_link_vlan_set_ingress_map(NMPlatform *self, int ifindex, int from, int to) -{ - NMVlanQosMapping map = { - .from = from, - .to = to, - }; - - return nm_platform_link_vlan_change(self, ifindex, 0, 0, FALSE, &map, 1, FALSE, NULL, 0); -} - -gboolean -nm_platform_link_vlan_set_egress_map(NMPlatform *self, int ifindex, int from, int to) -{ - NMVlanQosMapping map = { - .from = from, - .to = to, - }; - - return nm_platform_link_vlan_change(self, ifindex, 0, 0, FALSE, NULL, 0, FALSE, &map, 1); -} - -static int -_infiniband_add_add_or_delete(NMPlatform * self, - int ifindex, - int p_key, - gboolean add, - const NMPlatformLink **out_link) -{ - char name[IFNAMSIZ]; - const NMPlatformLink *parent_link; - int r; - - _CHECK_SELF(self, klass, -NME_BUG); - - g_return_val_if_fail(ifindex >= 0, -NME_BUG); - g_return_val_if_fail(p_key >= 0 && p_key <= 0xffff, -NME_BUG); - - /* the special keys 0x0000 and 0x8000 are not allowed. */ - if (NM_IN_SET(p_key, 0, 0x8000)) - return -NME_UNSPEC; - - parent_link = nm_platform_link_get(self, ifindex); - if (!parent_link) - return -NME_PL_NOT_FOUND; - - if (parent_link->type != NM_LINK_TYPE_INFINIBAND) - return -NME_PL_WRONG_TYPE; - - nm_utils_new_infiniband_name(name, parent_link->name, p_key); - - if (add) { - r = _link_add_check_existing(self, name, NM_LINK_TYPE_INFINIBAND, out_link); - if (r < 0) - return r; - - _LOG3D("link: adding infiniband partition %s, key %d", name, p_key); - if (!klass->infiniband_partition_add(self, ifindex, p_key, out_link)) - return -NME_UNSPEC; - } else { - _LOG3D("link: deleting infiniband partition %s, key %d", name, p_key); - - if (!klass->infiniband_partition_delete(self, ifindex, p_key)) - return -NME_UNSPEC; - } - - return 0; -} - -int -nm_platform_link_infiniband_add(NMPlatform * self, - int parent, - int p_key, - const NMPlatformLink **out_link) -{ - return _infiniband_add_add_or_delete(self, parent, p_key, TRUE, out_link); -} - -int -nm_platform_link_infiniband_delete(NMPlatform *self, int parent, int p_key) -{ - return _infiniband_add_add_or_delete(self, parent, p_key, FALSE, NULL); -} - -gboolean -nm_platform_link_infiniband_get_properties(NMPlatform * self, - int ifindex, - int * out_parent, - int * out_p_key, - const char **out_mode) -{ - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - const NMPlatformLnkInfiniband *plnk; - const NMPlatformLink * plink; - char * contents; - const char * mode; - int p_key = 0; - - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - plnk = nm_platform_link_get_lnk_infiniband(self, ifindex, &plink); - - if (!plink || plink->type != NM_LINK_TYPE_INFINIBAND) - return FALSE; - - if (plnk) { - NM_SET_OUT(out_parent, plink->parent); - NM_SET_OUT(out_p_key, plnk->p_key); - NM_SET_OUT(out_mode, plnk->mode); - return TRUE; - } - - /* Could not get the link information via netlink. To support older kernels, - * fallback to reading sysfs. */ - - dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname_verified); - if (dirfd < 0) - return FALSE; - - contents = - nm_platform_sysctl_get(self, NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "mode")); - if (!contents) - return FALSE; - if (strstr(contents, "datagram")) - mode = "datagram"; - else if (strstr(contents, "connected")) - mode = "connected"; - else - mode = NULL; - g_free(contents); - - p_key = - nm_platform_sysctl_get_int_checked(self, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "pkey"), - 16, - 0, - 0xFFFF, - -1); - if (p_key < 0) - return FALSE; - - NM_SET_OUT(out_parent, plink->parent); - NM_SET_OUT(out_p_key, p_key); - NM_SET_OUT(out_mode, mode); - return TRUE; -} - -gboolean -nm_platform_link_veth_get_properties(NMPlatform *self, int ifindex, int *out_peer_ifindex) -{ - const NMPlatformLink *plink; - int peer_ifindex; - - plink = nm_platform_link_get(self, ifindex); - if (!plink) - return FALSE; - - if (plink->type != NM_LINK_TYPE_VETH) - return FALSE; - - if (plink->parent != 0) { - NM_SET_OUT(out_peer_ifindex, plink->parent); - return TRUE; - } - - /* Pre-4.1 kernel did not expose the peer_ifindex as IFA_LINK. Lookup via ethtool. */ - if (out_peer_ifindex) { - nm_auto_pop_netns NMPNetns *netns = NULL; - - if (!nm_platform_netns_push(self, &netns)) - return FALSE; - peer_ifindex = nmp_utils_ethtool_get_peer_ifindex(plink->ifindex); - if (peer_ifindex <= 0) - return FALSE; - - *out_peer_ifindex = peer_ifindex; - } - return TRUE; -} - -/** - * nm_platform_link_tun_get_properties: - * @self: the #NMPlatform instance - * @ifindex: the ifindex to look up - * @out_properties: (out) (allow-none): return the read properties - * - * Only recent versions of kernel export tun properties via netlink. - * So, if that's the case, then we have the NMPlatformLnkTun instance - * in the platform cache ready to return. Otherwise, this function - * falls back reading sysctl to obtain the tun properties. That - * is racy, because querying sysctl means that the object might - * be already removed from cache (while NM didn't yet process the - * netlink message). - * - * Hence, to lookup the tun properties, you always need to use this - * function, and use it with care knowing that it might obtain its - * data by reading sysctl. Note that we don't want to add this workaround - * to the platform cache itself, because the cache should (mainly) - * contain data from netlink. To access the sysctl side channel, the - * user needs to do explicitly. - * - * Returns: #TRUE, if the properties could be read. */ -gboolean -nm_platform_link_tun_get_properties(NMPlatform *self, int ifindex, NMPlatformLnkTun *out_properties) -{ - const NMPObject *plobj; - const NMPObject *pllnk; - char ifname[IFNAMSIZ]; - gint64 owner; - gint64 group; - gint64 flags; - - /* we consider also invisible links (those that are not yet in udev). */ - plobj = nm_platform_link_get_obj(self, ifindex, FALSE); - if (!plobj) - return FALSE; - - if (NMP_OBJECT_CAST_LINK(plobj)->type != NM_LINK_TYPE_TUN) - return FALSE; - - pllnk = plobj->_link.netlink.lnk; - if (pllnk) { - nm_assert(NMP_OBJECT_GET_TYPE(pllnk) == NMP_OBJECT_TYPE_LNK_TUN); - nm_assert(NMP_OBJECT_GET_CLASS(pllnk)->lnk_link_type == NM_LINK_TYPE_TUN); - - /* recent kernels expose tun properties via netlink and thus we have them - * in the platform cache. */ - NM_SET_OUT(out_properties, pllnk->lnk_tun); - return TRUE; - } - - /* fallback to reading sysctl. */ - { - nm_auto_close int dirfd = -1; - - dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname); - if (dirfd < 0) - return FALSE; - - owner = nm_platform_sysctl_get_int_checked(self, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "owner"), - 10, - -1, - G_MAXUINT32, - -2); - if (owner == -2) - return FALSE; - - group = nm_platform_sysctl_get_int_checked(self, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "group"), - 10, - -1, - G_MAXUINT32, - -2); - if (group == -2) - return FALSE; - - flags = - nm_platform_sysctl_get_int_checked(self, - NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "tun_flags"), - 16, - 0, - G_MAXINT64, - -1); - if (flags == -1) - return FALSE; - } - - if (out_properties) { - memset(out_properties, 0, sizeof(*out_properties)); - if (owner != -1) { - out_properties->owner_valid = TRUE; - out_properties->owner = owner; - } - if (group != -1) { - out_properties->group_valid = TRUE; - out_properties->group = group; - } - out_properties->type = (flags & TUN_TYPE_MASK); - out_properties->pi = !(flags & IFF_NO_PI); - out_properties->vnet_hdr = !!(flags & IFF_VNET_HDR); - out_properties->multi_queue = !!(flags & NM_IFF_MULTI_QUEUE); - out_properties->persist = !!(flags & IFF_PERSIST); - } - return TRUE; -} - -gboolean -nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_capabilities(self, ifindex, caps); -} - -guint32 -nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, 0); - - g_return_val_if_fail(ifindex > 0, 0); - - return klass->wifi_get_frequency(self, ifindex); -} - -gboolean -nm_platform_wifi_get_station(NMPlatform * self, - int ifindex, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_station(self, ifindex, out_bssid, out_quality, out_rate); -} - -NM80211Mode -nm_platform_wifi_get_mode(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, NM_802_11_MODE_UNKNOWN); - - g_return_val_if_fail(ifindex > 0, NM_802_11_MODE_UNKNOWN); - - return klass->wifi_get_mode(self, ifindex); -} - -void -nm_platform_wifi_set_mode(NMPlatform *self, int ifindex, NM80211Mode mode) -{ - _CHECK_SELF_VOID(self, klass); - - g_return_if_fail(ifindex > 0); - - klass->wifi_set_mode(self, ifindex, mode); -} - -static void -wifi_set_powersave(NMPlatform *p, int ifindex, guint32 powersave) -{ - /* empty */ -} - -void -nm_platform_wifi_set_powersave(NMPlatform *self, int ifindex, guint32 powersave) -{ - _CHECK_SELF_VOID(self, klass); - - g_return_if_fail(ifindex > 0); - - klass->wifi_set_powersave(self, ifindex, powersave); -} - -guint32 -nm_platform_wifi_find_frequency(NMPlatform *self, int ifindex, const guint32 *freqs) -{ - _CHECK_SELF(self, klass, 0); - - g_return_val_if_fail(ifindex > 0, 0); - g_return_val_if_fail(freqs != NULL, 0); - - return klass->wifi_find_frequency(self, ifindex, freqs); -} - -void -nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex, gboolean running) -{ - _CHECK_SELF_VOID(self, klass); - - g_return_if_fail(ifindex > 0); - - klass->wifi_indicate_addressing_running(self, ifindex, running); -} - -NMSettingWirelessWakeOnWLan -nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_wake_on_wlan(self, ifindex); -} - -gboolean -nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_set_wake_on_wlan(self, ifindex, wowl); -} - -guint32 -nm_platform_mesh_get_channel(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, 0); - - g_return_val_if_fail(ifindex > 0, 0); - - return klass->mesh_get_channel(self, ifindex); -} - -gboolean -nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->mesh_set_channel(self, ifindex, channel); -} - -gboolean -nm_platform_mesh_set_ssid(NMPlatform *self, int ifindex, const guint8 *ssid, gsize len) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(ssid != NULL, FALSE); - - return klass->mesh_set_ssid(self, ifindex, ssid, len); -} - -guint16 -nm_platform_wpan_get_pan_id(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wpan_get_pan_id(self, ifindex); -} - -gboolean -nm_platform_wpan_set_pan_id(NMPlatform *self, int ifindex, guint16 pan_id) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wpan_set_pan_id(self, ifindex, pan_id); -} - -guint16 -nm_platform_wpan_get_short_addr(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wpan_get_short_addr(self, ifindex); -} - -gboolean -nm_platform_wpan_set_short_addr(NMPlatform *self, int ifindex, guint16 short_addr) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wpan_set_short_addr(self, ifindex, short_addr); -} - -gboolean -nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8 channel) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wpan_set_channel(self, ifindex, page, channel); -} - -#define TO_STRING_DEV_BUF_SIZE (5 + 15 + 1) -static const char * -_to_string_dev(NMPlatform *self, int ifindex, char *buf, size_t size) -{ - g_assert(buf && size >= TO_STRING_DEV_BUF_SIZE); - - if (ifindex) { - const char *name = ifindex > 0 && self ? nm_platform_link_get_name(self, ifindex) : NULL; - char * buf2; - - strcpy(buf, " dev "); - buf2 = buf + 5; - size -= 5; - - if (name) - g_strlcpy(buf2, name, size); - else - g_snprintf(buf2, size, "%d", ifindex); - } else - buf[0] = 0; - - return buf; -} - -#define TO_STRING_IFA_FLAGS_BUF_SIZE 256 - -static const char * -_to_string_ifa_flags(guint32 ifa_flags, char *buf, gsize size) -{ -#define S_FLAGS_PREFIX " flags " - nm_assert(buf && size >= TO_STRING_IFA_FLAGS_BUF_SIZE && size > NM_STRLEN(S_FLAGS_PREFIX)); - - if (!ifa_flags) - buf[0] = '\0'; - else { - nm_platform_addr_flags2str(ifa_flags, - &buf[NM_STRLEN(S_FLAGS_PREFIX)], - size - NM_STRLEN(S_FLAGS_PREFIX)); - if (buf[NM_STRLEN(S_FLAGS_PREFIX)] == '\0') - buf[0] = '\0'; - else - memcpy(buf, S_FLAGS_PREFIX, NM_STRLEN(S_FLAGS_PREFIX)); - } - return buf; -} - -/*****************************************************************************/ - -gboolean -nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, - int ifindex, - _NMSettingWiredWakeOnLan wol, - const char * wol_password) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return nmp_utils_ethtool_set_wake_on_lan(ifindex, wol, wol_password); -} - -gboolean -nm_platform_ethtool_set_link_settings(NMPlatform * self, - int ifindex, - gboolean autoneg, - guint32 speed, - NMPlatformLinkDuplexType duplex) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return nmp_utils_ethtool_set_link_settings(ifindex, autoneg, speed, duplex); -} - -gboolean -nm_platform_ethtool_get_link_settings(NMPlatform * self, - int ifindex, - gboolean * out_autoneg, - guint32 * out_speed, - NMPlatformLinkDuplexType *out_duplex) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return nmp_utils_ethtool_get_link_settings(ifindex, out_autoneg, out_speed, out_duplex); -} - -/*****************************************************************************/ - -NMEthtoolFeatureStates * -nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex) -{ - _CHECK_SELF_NETNS(self, klass, netns, NULL); - - g_return_val_if_fail(ifindex > 0, NULL); - - return nmp_utils_ethtool_get_features(ifindex); -} - -gboolean -nm_platform_ethtool_set_features( - NMPlatform * self, - int ifindex, - const NMEthtoolFeatureStates *features, - const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return nmp_utils_ethtool_set_features(ifindex, features, requested, do_set); -} - -gboolean -nm_platform_ethtool_get_link_coalesce(NMPlatform * self, - int ifindex, - NMEthtoolCoalesceState *coalesce) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(coalesce, FALSE); - - return nmp_utils_ethtool_get_coalesce(ifindex, coalesce); -} - -gboolean -nm_platform_ethtool_set_coalesce(NMPlatform * self, - int ifindex, - const NMEthtoolCoalesceState *coalesce) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return nmp_utils_ethtool_set_coalesce(ifindex, coalesce); -} - -gboolean -nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(ring, FALSE); - - return nmp_utils_ethtool_get_ring(ifindex, ring); -} - -gboolean -nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring) -{ - _CHECK_SELF_NETNS(self, klass, netns, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return nmp_utils_ethtool_set_ring(ifindex, ring); -} - -/*****************************************************************************/ - -const NMDedupMultiHeadEntry * -nm_platform_lookup_all(NMPlatform *self, NMPCacheIdType cache_id_type, const NMPObject *obj) -{ - return nmp_cache_lookup_all(nm_platform_get_cache(self), cache_id_type, obj); -} - -const NMDedupMultiEntry * -nm_platform_lookup_entry(NMPlatform *self, NMPCacheIdType cache_id_type, const NMPObject *obj) -{ - return nmp_cache_lookup_entry_with_idx_type(nm_platform_get_cache(self), cache_id_type, obj); -} - -const NMDedupMultiHeadEntry * -nm_platform_lookup(NMPlatform *self, const NMPLookup *lookup) -{ - return nmp_cache_lookup(nm_platform_get_cache(self), lookup); -} - -gboolean -nm_platform_lookup_predicate_routes_main(const NMPObject *obj, gpointer user_data) -{ - nm_assert( - NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - return nm_platform_route_table_is_main( - nm_platform_ip_route_get_effective_table(&obj->ip_route)); -} - -gboolean -nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel(const NMPObject *obj, - gpointer user_data) -{ - nm_assert( - NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - return nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&obj->ip_route)) - && obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL; -} - -/** - * nm_platform_lookup_clone: - * @self: - * @lookup: - * @predicate: if given, only objects for which @predicate returns %TRUE are included - * in the result. - * @user_data: user data for @predicate - * - * Returns the result of lookup in a GPtrArray. The result array contains - * references objects from the cache, its destroy function will unref them. - * - * The user must unref the GPtrArray, which will also unref the NMPObject - * elements. - * - * The elements in the array *must* not be modified. - * - * Returns: the result of the lookup. - */ -GPtrArray * -nm_platform_lookup_clone(NMPlatform * self, - const NMPLookup * lookup, - NMPObjectPredicateFunc predicate, - gpointer user_data) -{ - return nm_dedup_multi_objs_to_ptr_array_head(nm_platform_lookup(self, lookup), - (NMDedupMultiFcnSelectPredicate) predicate, - user_data); -} - -void -nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen) -{ - nm_assert(plen <= 32); - - addr->address = address; - addr->peer_address = address; - addr->plen = plen; -} - -const struct in6_addr * -nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr) -{ - if (IN6_IS_ADDR_UNSPECIFIED(&addr->peer_address) - || IN6_ARE_ADDR_EQUAL(&addr->peer_address, &addr->address)) - return &addr->address; - return &addr->peer_address; -} - -gboolean -nm_platform_ip6_address_match(const NMPlatformIP6Address *addr, NMPlatformMatchFlags match_flag) -{ - nm_assert(!NM_FLAGS_ANY( - match_flag, - ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))); - nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY)); - nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)); - - if (IN6_IS_ADDR_LINKLOCAL(&addr->address)) { - if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL)) - return FALSE; - } else { - if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL)) - return FALSE; - } - - if (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_DADFAILED)) { - if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED)) - return FALSE; - } else if (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TENTATIVE) - && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { - if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) - return FALSE; - } else { - if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) - return FALSE; - } - - return TRUE; -} - -gboolean -nm_platform_ip4_address_add(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(plen <= 32, FALSE); - g_return_val_if_fail(lifetime > 0, FALSE); - g_return_val_if_fail(preferred <= lifetime, FALSE); - g_return_val_if_fail(!label || strlen(label) < sizeof(((NMPlatformIP4Address *) NULL)->label), - FALSE); - - if (_LOGD_ENABLED()) { - NMPlatformIP4Address addr; - - addr = (NMPlatformIP4Address){ - .ifindex = ifindex, - .address = address, - .peer_address = peer_address, - .plen = plen, - .timestamp = 0, /* set it at zero, which to_string will treat as *now* */ - .lifetime = lifetime, - .preferred = preferred, - .n_ifa_flags = flags, - .broadcast_address = broadcast_address, - .use_ip4_broadcast_address = TRUE, - }; - if (label) - g_strlcpy(addr.label, label, sizeof(addr.label)); - - _LOG3D("address: adding or updating IPv4 address: %s", - nm_platform_ip4_address_to_string(&addr, NULL, 0)); - } - return klass->ip4_address_add(self, - ifindex, - address, - plen, - peer_address, - broadcast_address, - lifetime, - preferred, - flags, - label); -} - -gboolean -nm_platform_ip6_address_add(NMPlatform * self, - int ifindex, - struct in6_addr address, - guint8 plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(plen <= 128, FALSE); - g_return_val_if_fail(lifetime > 0, FALSE); - g_return_val_if_fail(preferred <= lifetime, FALSE); - - if (_LOGD_ENABLED()) { - NMPlatformIP6Address addr = {0}; - - addr.ifindex = ifindex; - addr.address = address; - addr.peer_address = peer_address; - addr.plen = plen; - addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */ - addr.lifetime = lifetime; - addr.preferred = preferred; - addr.n_ifa_flags = flags; - - _LOG3D("address: adding or updating IPv6 address: %s", - nm_platform_ip6_address_to_string(&addr, NULL, 0)); - } - return klass - ->ip6_address_add(self, ifindex, address, plen, peer_address, lifetime, preferred, flags); -} - -gboolean -nm_platform_ip4_address_delete(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address) -{ - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char b1[NM_UTILS_INET_ADDRSTRLEN]; - char b2[NM_UTILS_INET_ADDRSTRLEN]; - char str_peer[INET_ADDRSTRLEN + 50]; - - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(plen <= 32, FALSE); - - _LOG3D("address: deleting IPv4 address %s/%d, %s%s", - _nm_utils_inet4_ntop(address, b1), - plen, - peer_address != address - ? nm_sprintf_buf(str_peer, "peer %s, ", _nm_utils_inet4_ntop(peer_address, b2)) - : "", - _to_string_dev(self, ifindex, str_dev, sizeof(str_dev))); - return klass->ip4_address_delete(self, ifindex, address, plen, peer_address); -} - -gboolean -nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen) -{ - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(plen <= 128, FALSE); - - _LOG3D("address: deleting IPv6 address %s/%d, %s", - _nm_utils_inet6_ntop(&address, sbuf), - plen, - _to_string_dev(self, ifindex, str_dev, sizeof(str_dev))); - return klass->ip6_address_delete(self, ifindex, address, plen); -} - -const NMPlatformIP4Address * -nm_platform_ip4_address_get(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address) -{ - NMPObject obj_id; - const NMPObject *obj; - - _CHECK_SELF(self, klass, NULL); - - g_return_val_if_fail(plen <= 32, NULL); - - nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, address, plen, peer_address); - obj = nmp_cache_lookup_obj(nm_platform_get_cache(self), &obj_id); - nm_assert(!obj || nmp_object_is_visible(obj)); - return NMP_OBJECT_CAST_IP4_ADDRESS(obj); -} - -const NMPlatformIP6Address * -nm_platform_ip6_address_get(NMPlatform *self, int ifindex, const struct in6_addr *address) -{ - NMPObject obj_id; - const NMPObject *obj; - - _CHECK_SELF(self, klass, NULL); - - nm_assert(address); - - nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, address); - obj = nmp_cache_lookup_obj(nm_platform_get_cache(self), &obj_id); - nm_assert(!obj || nmp_object_is_visible(obj)); - return NMP_OBJECT_CAST_IP6_ADDRESS(obj); -} - -static gboolean -_addr_array_clean_expired(int addr_family, - int ifindex, - GPtrArray * array, - guint32 now, - GHashTable **idx) -{ - guint i; - gboolean any_addrs = FALSE; - - nm_assert_addr_family(addr_family); - nm_assert(ifindex > 0); - nm_assert(now > 0); - - if (!array) - return FALSE; - - /* remove all addresses that are already expired. */ - for (i = 0; i < array->len; i++) { - const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(array->pdata[i]); - -#if NM_MORE_ASSERTS > 10 - nm_assert(a); - nm_assert(a->ifindex == ifindex); - { - const NMPObject *o = NMP_OBJECT_UP_CAST(a); - guint j; - - nm_assert(NMP_OBJECT_GET_CLASS(o)->addr_family == addr_family); - for (j = i + 1; j < array->len; j++) { - const NMPObject *o2 = array->pdata[j]; - - nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_GET_TYPE(o2)); - nm_assert(!nmp_object_id_equal(o, o2)); - } - } -#endif - - if (!NM_IS_IPv4(addr_family) && NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TEMPORARY)) { - /* temporary addresses are never added explicitly by NetworkManager but - * kernel adds them via mngtempaddr flag. - * - * We drop them from this list. */ - goto clear_and_next; - } - - if (!nm_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, now, NULL)) - goto clear_and_next; - - if (idx) { - if (G_UNLIKELY(!*idx)) { - *idx = g_hash_table_new((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); - } - if (!g_hash_table_add(*idx, (gpointer) NMP_OBJECT_UP_CAST(a))) - nm_assert_not_reached(); - } - any_addrs = TRUE; - continue; - -clear_and_next: - nmp_object_unref(g_steal_pointer(&array->pdata[i])); - } - - return any_addrs; -} - -static gboolean -ip4_addr_subnets_is_plain_address(const GPtrArray *addresses, gconstpointer needle) -{ - return needle >= (gconstpointer) &addresses->pdata[0] - && needle < (gconstpointer) &addresses->pdata[addresses->len]; -} - -static const NMPObject ** -ip4_addr_subnets_addr_list_get(const GPtrArray *addr_list, guint idx) -{ - nm_assert(addr_list); - nm_assert(addr_list->len > 1); - nm_assert(idx < addr_list->len); - nm_assert(addr_list->pdata[idx]); - nm_assert(!(*((gpointer *) addr_list->pdata[idx])) - || NMP_OBJECT_CAST_IP4_ADDRESS(*((gpointer *) addr_list->pdata[idx]))); - nm_assert(idx == 0 || ip4_addr_subnets_addr_list_get(addr_list, idx - 1)); - return addr_list->pdata[idx]; -} - -static void -ip4_addr_subnets_destroy_index(GHashTable *subnets, const GPtrArray *addresses) -{ - GHashTableIter iter; - gpointer p; - - if (!subnets) - return; - - g_hash_table_iter_init(&iter, subnets); - while (g_hash_table_iter_next(&iter, NULL, &p)) { - if (!ip4_addr_subnets_is_plain_address(addresses, p)) - g_ptr_array_free((GPtrArray *) p, TRUE); - } - - g_hash_table_unref(subnets); -} - -static GHashTable * -ip4_addr_subnets_build_index(const GPtrArray *addresses, - gboolean consider_flags, - gboolean full_index) -{ - GHashTable *subnets; - guint i; - - nm_assert(addresses && addresses->len); - - subnets = g_hash_table_new(nm_direct_hash, NULL); - - /* Build a hash table of all addresses per subnet */ - for (i = 0; i < addresses->len; i++) { - const NMPlatformIP4Address *address; - gpointer p_address; - GPtrArray * addr_list; - guint32 net; - int position; - gpointer p; - - if (!addresses->pdata[i]) - continue; - - p_address = &addresses->pdata[i]; - address = NMP_OBJECT_CAST_IP4_ADDRESS(addresses->pdata[i]); - - net = address->address & _nm_utils_ip4_prefix_to_netmask(address->plen); - if (!g_hash_table_lookup_extended(subnets, GUINT_TO_POINTER(net), NULL, &p)) { - g_hash_table_insert(subnets, GUINT_TO_POINTER(net), p_address); - continue; - } - nm_assert(p); - - if (full_index) { - if (ip4_addr_subnets_is_plain_address(addresses, p)) { - addr_list = g_ptr_array_new(); - g_hash_table_insert(subnets, GUINT_TO_POINTER(net), addr_list); - g_ptr_array_add(addr_list, p); - } else - addr_list = p; - - if (!consider_flags || NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_SECONDARY)) - position = -1; /* append */ - else - position = 0; /* prepend */ - g_ptr_array_insert(addr_list, position, p_address); - } else { - /* we only care about the primary. No need to track the secondaries - * as a GPtrArray. */ - nm_assert(ip4_addr_subnets_is_plain_address(addresses, p)); - if (consider_flags && !NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_SECONDARY)) { - g_hash_table_insert(subnets, GUINT_TO_POINTER(net), p_address); - } - } - } - - return subnets; -} - -/** - * ip4_addr_subnets_is_secondary: - * @address: an address - * @subnets: the hash table mapping subnets to addresses - * @addresses: array of addresses in the hash table - * @out_addr_list: array of addresses belonging to the same subnet - * - * Checks whether @address is secondary and returns in @out_addr_list the list of addresses - * belonging to the same subnet, if it contains other elements. - * - * Returns: %TRUE if the address is secondary, %FALSE otherwise - */ -static gboolean -ip4_addr_subnets_is_secondary(const NMPObject * address, - GHashTable * subnets, - const GPtrArray * addresses, - const GPtrArray **out_addr_list) -{ - const NMPlatformIP4Address *a; - const GPtrArray * addr_list; - gconstpointer p; - guint32 net; - const NMPObject ** o; - - a = NMP_OBJECT_CAST_IP4_ADDRESS(address); - - net = a->address & _nm_utils_ip4_prefix_to_netmask(a->plen); - p = g_hash_table_lookup(subnets, GUINT_TO_POINTER(net)); - nm_assert(p); - if (!ip4_addr_subnets_is_plain_address(addresses, p)) { - addr_list = p; - nm_assert(addr_list->len > 1); - NM_SET_OUT(out_addr_list, addr_list); - o = ip4_addr_subnets_addr_list_get(addr_list, 0); - nm_assert(o && *o); - if (*o != address) - return TRUE; - } else { - NM_SET_OUT(out_addr_list, NULL); - return address != *((gconstpointer *) p); - } - return FALSE; -} - -typedef enum { - IP6_ADDR_SCOPE_LOOPBACK, - IP6_ADDR_SCOPE_LINKLOCAL, - IP6_ADDR_SCOPE_SITELOCAL, - IP6_ADDR_SCOPE_OTHER, -} IP6AddrScope; - -static IP6AddrScope -ip6_address_scope(const NMPlatformIP6Address *a) -{ - if (IN6_IS_ADDR_LOOPBACK(&a->address)) - return IP6_ADDR_SCOPE_LOOPBACK; - if (IN6_IS_ADDR_LINKLOCAL(&a->address)) - return IP6_ADDR_SCOPE_LINKLOCAL; - if (IN6_IS_ADDR_SITELOCAL(&a->address)) - return IP6_ADDR_SCOPE_SITELOCAL; - return IP6_ADDR_SCOPE_OTHER; -} - -static int -ip6_address_scope_cmp(gconstpointer p_a, gconstpointer p_b, gpointer increasing) -{ - const NMPlatformIP6Address *a; - const NMPlatformIP6Address *b; - - if (!increasing) - NM_SWAP(&p_a, &p_b); - - a = NMP_OBJECT_CAST_IP6_ADDRESS(*(const NMPObject *const *) p_a); - b = NMP_OBJECT_CAST_IP6_ADDRESS(*(const NMPObject *const *) p_b); - - NM_CMP_DIRECT(ip6_address_scope(a), ip6_address_scope(b)); - return 0; -} - -/** - * nm_platform_ip_address_sync: - * @self: platform instance - * @addr_family: the address family AF_INET or AF_INET6. - * @ifindex: Interface index - * @known_addresses: List of addresses. The list will be modified and only - * addresses that were successfully added will be kept in the list. - * That means, expired addresses and addresses that could not be added - * will be dropped. - * Hence, the input argument @known_addresses is also an output argument - * telling which addresses were successfully added. - * Addresses are removed by unrefing the instance via nmp_object_unref() - * and leaving a NULL tombstone. - * @addresses_prune: (allow-none): the list of addresses to delete. - * If platform has such an address configured, it will be deleted - * at the beginning of the sync. Note that the array will be modified - * by the function. - * Note that the addresses must be properly sorted, by their priority. - * Create this list with nm_platform_ip_address_get_prune_list() which - * gets the sorting right. - * - * A convenience function to synchronize addresses for a specific interface - * with the least possible disturbance. It simply removes addresses that are - * not listed and adds addresses that are. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_ip_address_sync(NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray * known_addresses, - GPtrArray * addresses_prune) -{ - const gint32 now = nm_utils_get_monotonic_timestamp_sec(); - const int IS_IPv4 = NM_IS_IPv4(addr_family); - gs_unref_hashtable GHashTable *known_addresses_idx = NULL; - GPtrArray * plat_addresses; - GHashTable * known_subnets = NULL; - guint32 ifa_flags; - guint i_plat; - guint i_know; - guint i; - guint j; - - _CHECK_SELF(self, klass, FALSE); - - /* The order we want to enforce is only among addresses with the same - * scope, as the kernel keeps addresses sorted by scope. Therefore, - * apply the same sorting to known addresses, so that we don't try to - * unnecessary change the order of addresses with different scopes. */ - if (!IS_IPv4) { - if (known_addresses) - g_ptr_array_sort_with_data(known_addresses, - ip6_address_scope_cmp, - GINT_TO_POINTER(TRUE)); - } - - if (!_addr_array_clean_expired(addr_family, - ifindex, - known_addresses, - now, - &known_addresses_idx)) - known_addresses = NULL; - - /* @plat_addresses must be sorted in decreasing priority order (highest priority addresses first), contrary to - * @known_addresses which is in increasing priority order (lowest priority addresses first). */ - plat_addresses = addresses_prune; - - if (nm_g_ptr_array_len(plat_addresses) > 0) { - /* Delete unknown addresses */ - if (IS_IPv4) { - GHashTable *plat_subnets; - - plat_subnets = ip4_addr_subnets_build_index(plat_addresses, TRUE, TRUE); - - for (i = 0; i < plat_addresses->len; i++) { - const NMPObject * plat_obj; - const NMPlatformIP4Address *plat_address; - const GPtrArray * addr_list; - - plat_obj = plat_addresses->pdata[i]; - if (!plat_obj) { - /* Already deleted */ - continue; - } - - plat_address = NMP_OBJECT_CAST_IP4_ADDRESS(plat_obj); - - if (known_addresses) { - const NMPObject *o; - - o = g_hash_table_lookup(known_addresses_idx, plat_obj); - if (o) { - gboolean secondary; - - if (!known_subnets) - known_subnets = - ip4_addr_subnets_build_index(known_addresses, FALSE, FALSE); - - secondary = - ip4_addr_subnets_is_secondary(o, known_subnets, known_addresses, NULL); - if (secondary == NM_FLAGS_HAS(plat_address->n_ifa_flags, IFA_F_SECONDARY)) { - /* if we have an existing known-address, with matching secondary role, - * do not delete the platform-address. */ - continue; - } - } - } - - nm_platform_ip4_address_delete(self, - ifindex, - plat_address->address, - plat_address->plen, - plat_address->peer_address); - - if (!ip4_addr_subnets_is_secondary(plat_obj, - plat_subnets, - plat_addresses, - &addr_list) - && addr_list) { - /* If we just deleted a primary addresses and there were - * secondary ones the kernel can do two things, depending on - * version and sysctl setting: delete also secondary addresses - * or promote a secondary to primary. Ensure that secondary - * addresses are deleted, so that we can start with a clean - * slate and add addresses in the right order. */ - for (j = 1; j < addr_list->len; j++) { - const NMPObject **o; - - o = ip4_addr_subnets_addr_list_get(addr_list, j); - nm_assert(o); - - if (*o) { - const NMPlatformIP4Address *a; - - a = NMP_OBJECT_CAST_IP4_ADDRESS(*o); - nm_platform_ip4_address_delete(self, - ifindex, - a->address, - a->plen, - a->peer_address); - nmp_object_unref(*o); - *o = NULL; - } - } - } - } - ip4_addr_subnets_destroy_index(plat_subnets, plat_addresses); - } else { - guint known_addresses_len; - IP6AddrScope cur_scope; - gboolean delete_remaining_addrs; - - g_ptr_array_sort_with_data(plat_addresses, - ip6_address_scope_cmp, - GINT_TO_POINTER(FALSE)); - - known_addresses_len = known_addresses ? known_addresses->len : 0; - - /* First, compare every address whether it is still a "known address", that is, whether - * to keep it or to delete it. - * - * If we don't find a matching valid address in @known_addresses, we will delete - * plat_addr. - * - * Certain addresses, like temporary addresses, are ignored by this function - * if not run with full_sync. These addresses are usually not managed by NetworkManager - * directly, or at least, they are not managed via nm_platform_ip6_address_sync(). - * Only in full_sync mode, we really want to get rid of them (usually, when we take - * the interface down). - * - * Note that we mark handled addresses by setting it to %NULL in @plat_addresses array. */ - for (i_plat = 0; i_plat < plat_addresses->len; i_plat++) { - const NMPObject * plat_obj = plat_addresses->pdata[i_plat]; - const NMPObject * know_obj; - const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj); - - if (known_addresses_idx) { - know_obj = g_hash_table_lookup(known_addresses_idx, plat_obj); - if (know_obj - && plat_addr->plen == NMP_OBJECT_CAST_IP6_ADDRESS(know_obj)->plen) { - /* technically, plen is not part of the ID for IPv6 addresses and thus - * @plat_addr is essentially the same address as @know_addr (regrading - * its identity, not its other attributes). - * However, we cannot modify an existing addresses' plen without - * removing and readding it. Thus, only keep plat_addr, if the plen - * matches. - * - * keep this one, and continue */ - continue; - } - } - - nm_platform_ip6_address_delete(self, ifindex, plat_addr->address, plat_addr->plen); - nmp_object_unref(g_steal_pointer(&plat_addresses->pdata[i_plat])); - } - - /* Next, we must preserve the priority of the routes. That is, source address - * selection will choose addresses in the order as they are reported by kernel. - * Note that the order in @plat_addresses of the remaining matches is highest - * priority first. - * We need to compare this to the order of addresses with same scope in - * @known_addresses (which has lowest priority first). - * - * If we find a first discrepancy, we need to delete all remaining addresses - * with same scope from that point on, because below we must re-add all the - * addresses in the right order to get their priority right. */ - cur_scope = IP6_ADDR_SCOPE_LOOPBACK; - delete_remaining_addrs = FALSE; - i_plat = plat_addresses->len; - i_know = 0; - while (i_plat > 0) { - const NMPlatformIP6Address *plat_addr = - NMP_OBJECT_CAST_IP6_ADDRESS(plat_addresses->pdata[--i_plat]); - IP6AddrScope plat_scope; - - if (!plat_addr) - continue; - - plat_scope = ip6_address_scope(plat_addr); - if (cur_scope != plat_scope) { - nm_assert(cur_scope < plat_scope); - delete_remaining_addrs = FALSE; - cur_scope = plat_scope; - } - - if (!delete_remaining_addrs) { - delete_remaining_addrs = TRUE; - for (; i_know < known_addresses_len; i_know++) { - const NMPlatformIP6Address *know_addr = - NMP_OBJECT_CAST_IP6_ADDRESS(known_addresses->pdata[i_know]); - IP6AddrScope know_scope; - - if (!know_addr) - continue; - - know_scope = ip6_address_scope(know_addr); - if (know_scope < plat_scope) - continue; - - if (IN6_ARE_ADDR_EQUAL(&plat_addr->address, &know_addr->address)) { - /* we have a match. Mark address as handled. */ - i_know++; - delete_remaining_addrs = FALSE; - goto next_plat; - } - - /* plat_address has no match. Now delete_remaining_addrs is TRUE and we will - * delete all the remaining addresses with cur_scope. */ - break; - } - } - - nm_platform_ip6_address_delete(self, ifindex, plat_addr->address, plat_addr->plen); -next_plat:; - } - } - } - - if (!known_addresses) - return TRUE; - - if (IS_IPv4) - ip4_addr_subnets_destroy_index(known_subnets, known_addresses); - - ifa_flags = nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) - ? IFA_F_NOPREFIXROUTE - : 0; - - /* Add missing addresses. New addresses are added by kernel with top - * priority. - */ - for (i_know = 0; i_know < known_addresses->len; i_know++) { - const NMPlatformIPXAddress *known_address; - const NMPObject * o; - guint32 lifetime; - guint32 preferred; - - o = known_addresses->pdata[i_know]; - if (!o) - continue; - - nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)); - - known_address = NMP_OBJECT_CAST_IPX_ADDRESS(o); - - lifetime = nm_utils_lifetime_get(known_address->ax.timestamp, - known_address->ax.lifetime, - known_address->ax.preferred, - now, - &preferred); - nm_assert(lifetime > 0); - - if (IS_IPv4) { - if (!nm_platform_ip4_address_add( - self, - ifindex, - known_address->a4.address, - known_address->a4.plen, - known_address->a4.peer_address, - nm_platform_ip4_broadcast_address_from_addr(&known_address->a4), - lifetime, - preferred, - ifa_flags, - known_address->a4.label)) { - /* ignore error, for unclear reasons. */ - } - } else { - if (!nm_platform_ip6_address_add(self, - ifindex, - known_address->a6.address, - known_address->a6.plen, - known_address->a6.peer_address, - lifetime, - preferred, - ifa_flags | known_address->a6.n_ifa_flags)) - return FALSE; - } - } - - return TRUE; -} - -gboolean -nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex) -{ - gboolean success = TRUE; - - _CHECK_SELF(self, klass, FALSE); - - nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) - success &= nm_platform_ip4_address_sync(self, ifindex, NULL); - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) - success &= nm_platform_ip6_address_sync(self, ifindex, NULL, TRUE); - return success; -} - -/*****************************************************************************/ - -static gboolean -_err_inval_due_to_ipv6_tentative_pref_src(NMPlatform *self, const NMPObject *obj) -{ - const NMPlatformIP6Route * r; - const NMPlatformIP6Address *a; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(NMP_OBJECT_IS_VALID(obj)); - - /* trying to add an IPv6 route with pref-src fails, if the address is - * still tentative (rh#1452684). We need to hack around that. - * - * Detect it, by guessing whether that's the case. */ - - if (NMP_OBJECT_GET_TYPE(obj) != NMP_OBJECT_TYPE_IP6_ROUTE) - return FALSE; - - r = NMP_OBJECT_CAST_IP6_ROUTE(obj); - - /* we only allow this workaround for routes added manually by the user. */ - if (r->rt_source != NM_IP_CONFIG_SOURCE_USER) - return FALSE; - - if (IN6_IS_ADDR_UNSPECIFIED(&r->pref_src)) - return FALSE; - - a = nm_platform_ip6_address_get(self, r->ifindex, &r->pref_src); - if (!a) - return FALSE; - if (!NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TENTATIVE) - || NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_DADFAILED)) - return FALSE; - - return TRUE; -} - -GPtrArray * -nm_platform_ip_address_get_prune_list(NMPlatform *self, - int addr_family, - int ifindex, - gboolean exclude_ipv6_temporary_addrs) -{ - const int IS_IPv4 = NM_IS_IPv4(addr_family); - const NMDedupMultiHeadEntry *head_entry; - NMPLookup lookup; - GPtrArray * result; - CList * iter; - - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(NM_IS_IPv4(addr_family)), ifindex); - - head_entry = nm_platform_lookup(self, &lookup); - - if (!head_entry) - return NULL; - - result = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nmp_object_unref); - - c_list_for_each (iter, &head_entry->lst_entries_head) { - const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj; - - if (!IS_IPv4) { - if (exclude_ipv6_temporary_addrs - && NM_FLAGS_HAS(NMP_OBJECT_CAST_IP_ADDRESS(obj)->n_ifa_flags, IFA_F_TEMPORARY)) - continue; - } - - g_ptr_array_add(result, (gpointer) nmp_object_ref(obj)); - } - - if (result->len == 0) { - g_ptr_array_unref(result); - return NULL; - } - return result; -} - -GPtrArray * -nm_platform_ip_route_get_prune_list(NMPlatform * self, - int addr_family, - int ifindex, - NMIPRouteTableSyncMode route_table_sync) -{ - NMPLookup lookup; - GPtrArray * routes_prune; - const NMDedupMultiHeadEntry *head_entry; - CList * iter; - NMPlatformIP4Route rt_local4; - NMPlatformIP6Route rt_local6; - const NMPlatformLink * pllink; - const NMPlatformLnkVrf * lnk_vrf; - guint32 local_table; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - nm_assert(NM_IN_SET(route_table_sync, - NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, - NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE)); - - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)), ifindex); - head_entry = nm_platform_lookup(self, &lookup); - if (!head_entry) - return NULL; - - lnk_vrf = nm_platform_link_get_lnk_vrf(self, ifindex, &pllink); - if (!lnk_vrf && pllink && pllink->master > 0) - lnk_vrf = nm_platform_link_get_lnk_vrf(self, pllink->master, NULL); - local_table = lnk_vrf ? lnk_vrf->table : RT_TABLE_LOCAL; - - rt_local4.plen = 0; - rt_local6.plen = 0; - - routes_prune = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref); - - c_list_for_each (iter, &head_entry->lst_entries_head) { - const NMPObject * obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj; - const NMPlatformIPXRoute *rt = NMP_OBJECT_CAST_IPX_ROUTE(obj); - - switch (route_table_sync) { - case NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN: - if (!nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&rt->rx))) - continue; - break; - case NM_IP_ROUTE_TABLE_SYNC_MODE_FULL: - if (nm_platform_ip_route_get_effective_table(&rt->rx) == RT_TABLE_LOCAL) - continue; - break; - case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL: - - /* FIXME: we should better handle routes that are automatically added by kernel. - * - * For now, make a good guess which are those routes and exclude them from - * pruning them. */ - - if (NM_IS_IPv4(addr_family)) { - /* for each IPv4 address kernel adds a route like - * - * local $ADDR dev $IFACE table local proto kernel scope host src $PRIMARY_ADDR - * - * Check whether route could be of that kind. */ - if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table - && rt->rx.plen == 32 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL - && rt->rx.metric == 0 - && rt->r4.scope_inv == nm_platform_route_scope_inv(RT_SCOPE_HOST) - && rt->r4.gateway == INADDR_ANY) { - if (rt_local4.plen == 0) { - rt_local4 = (NMPlatformIP4Route){ - .ifindex = ifindex, - .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), - .plen = 32, - .rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL, - .metric = 0, - .table_coerced = nm_platform_route_table_coerce(local_table), - .scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST), - .gateway = INADDR_ANY, - }; - } - - /* the possible "network" depends on the addresses we have. We don't check that - * carefully. If the other parameters match, we assume that this route is the one - * generated by kernel. */ - rt_local4.network = rt->r4.network; - rt_local4.pref_src = rt->r4.pref_src; - - /* to be more confident about comparing the value, use our nm_platform_ip4_route_cmp() - * implementation. That will also consider parameters that we leave unspecified here. */ - if (nm_platform_ip4_route_cmp(&rt->r4, - &rt_local4, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - == 0) - continue; - } - } else { - /* for each IPv6 address (that is no longer tentative) kernel adds a route like - * - * local $ADDR dev $IFACE table local proto kernel metric 0 pref medium - * - * Same as for the IPv4 case. */ - if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table - && rt->rx.plen == 128 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL - && rt->rx.metric == 0 && rt->r6.rt_pref == NM_ICMPV6_ROUTER_PREF_MEDIUM - && IN6_IS_ADDR_UNSPECIFIED(&rt->r6.gateway)) { - if (rt_local6.plen == 0) { - rt_local6 = (NMPlatformIP6Route){ - .ifindex = ifindex, - .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), - .plen = 128, - .rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL, - .metric = 0, - .table_coerced = nm_platform_route_table_coerce(local_table), - .rt_pref = NM_ICMPV6_ROUTER_PREF_MEDIUM, - .gateway = IN6ADDR_ANY_INIT, - }; - } - - rt_local6.network = rt->r6.network; - - if (nm_platform_ip6_route_cmp(&rt->r6, - &rt_local6, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - == 0) - continue; - } - } - break; - - case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE: - break; - - default: - nm_assert_not_reached(); - break; - } - - g_ptr_array_add(routes_prune, (gpointer) nmp_object_ref(obj)); - } - - if (routes_prune->len == 0) { - g_ptr_array_unref(routes_prune); - return NULL; - } - return routes_prune; -} - -/** - * nm_platform_ip_route_sync: - * @self: the #NMPlatform instance. - * @addr_family: AF_INET or AF_INET6. - * @ifindex: the @ifindex for which the routes are to be added. - * @routes: (allow-none): a list of routes to configure. Must contain - * NMPObject instances of routes, according to @addr_family. - * @routes_prune: (allow-none): the list of routes to delete. - * If platform has such a route configured, it will be deleted - * at the end of the operation. Note that if @routes contains - * the same route, then it will not be deleted. @routes overrules - * @routes_prune list. - * @out_temporary_not_available: (allow-none) (out): routes that could - * currently not be synced. The caller shall keep them and try later again. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_ip_route_sync(NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray * routes, - GPtrArray * routes_prune, - GPtrArray **out_temporary_not_available) -{ - const int IS_IPv4 = NM_IS_IPv4(addr_family); - const NMPlatformVTableRoute *vt; - gs_unref_hashtable GHashTable *routes_idx = NULL; - const NMPObject * conf_o; - const NMDedupMultiEntry * plat_entry; - guint i; - int i_type; - gboolean success = TRUE; - char sbuf1[sizeof(_nm_utils_to_string_buffer)]; - char sbuf2[sizeof(_nm_utils_to_string_buffer)]; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(ifindex > 0); - - vt = &nm_platform_vtable_route.vx[IS_IPv4]; - - for (i_type = 0; routes && i_type < 2; i_type++) { - for (i = 0; i < routes->len; i++) { - int r, r2; - gboolean gateway_route_added = FALSE; - - conf_o = routes->pdata[i]; - -#define VTABLE_IS_DEVICE_ROUTE(vt, o) \ - (vt->is_ip4 ? (NMP_OBJECT_CAST_IP4_ROUTE(o)->gateway == 0) \ - : IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(o)->gateway)) - - if ((i_type == 0 && !VTABLE_IS_DEVICE_ROUTE(vt, conf_o)) - || (i_type == 1 && VTABLE_IS_DEVICE_ROUTE(vt, conf_o))) { - /* we add routes in two runs over @i_type. - * - * First device routes, then gateway routes. */ - continue; - } - - if (!routes_idx) { - routes_idx = g_hash_table_new((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); - } - if (!g_hash_table_insert(routes_idx, (gpointer) conf_o, (gpointer) conf_o)) { - _LOG3D("route-sync: skip adding duplicate route %s", - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1))); - continue; - } - - if (!IS_IPv4 - && nm_platform_ip6_route_get_effective_metric(NMP_OBJECT_CAST_IP6_ROUTE(conf_o)) - == 0) { - /* User space cannot add routes with metric 0. However, kernel can, and we might track such - * routes in @route as they are present external. Skip them silently. */ - continue; - } - - plat_entry = nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, conf_o); - if (plat_entry) { - const NMPObject *plat_o; - - plat_o = plat_entry->obj; - - if (vt->route_cmp(NMP_OBJECT_CAST_IPX_ROUTE(conf_o), - NMP_OBJECT_CAST_IPX_ROUTE(plat_o), - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - == 0) - continue; - - /* we need to replace the existing route with a (slightly) different - * one. Delete it first. */ - if (!nm_platform_object_delete(self, plat_o)) { - /* ignore error. */ - } - } - -sync_route_add: - r = nm_platform_ip_route_add(self, - NMP_NLM_FLAG_APPEND - | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, - conf_o); - if (r < 0) { - if (r == -EEXIST) { - /* Don't fail for EEXIST. It's not clear that the existing route - * is identical to the one that we were about to add. However, - * above we should have deleted conflicting (non-identical) routes. */ - if (_LOGD_ENABLED()) { - plat_entry = - nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, conf_o); - if (!plat_entry) { - _LOG3D("route-sync: adding route %s failed with EEXIST, however we " - "cannot find such a route", - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1))); - } else if (vt->route_cmp(NMP_OBJECT_CAST_IPX_ROUTE(conf_o), - NMP_OBJECT_CAST_IPX_ROUTE(plat_entry->obj), - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - != 0) { - _LOG3D("route-sync: adding route %s failed due to existing " - "(different!) route %s", - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1)), - nmp_object_to_string(plat_entry->obj, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf2, - sizeof(sbuf2))); - } - } - } else if (NMP_OBJECT_CAST_IP_ROUTE(conf_o)->rt_source < NM_IP_CONFIG_SOURCE_USER) { - _LOG3D("route-sync: ignore failure to add IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1)), - nm_strerror(r)); - } else if (r == -EINVAL && out_temporary_not_available - && _err_inval_due_to_ipv6_tentative_pref_src(self, conf_o)) { - _LOG3D("route-sync: ignore failure to add IPv6 route with tentative IPv6 " - "pref-src: %s: %s", - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1)), - nm_strerror(r)); - if (!*out_temporary_not_available) - *out_temporary_not_available = - g_ptr_array_new_full(0, (GDestroyNotify) nmp_object_unref); - g_ptr_array_add(*out_temporary_not_available, - (gpointer) nmp_object_ref(conf_o)); - } else if (!gateway_route_added - && ((r == -ENETUNREACH && vt->is_ip4 - && !!NMP_OBJECT_CAST_IP4_ROUTE(conf_o)->gateway) - || (r == -EHOSTUNREACH && !vt->is_ip4 - && !IN6_IS_ADDR_UNSPECIFIED( - &NMP_OBJECT_CAST_IP6_ROUTE(conf_o)->gateway)))) { - NMPObject oo; - - if (vt->is_ip4) { - const NMPlatformIP4Route *rt = NMP_OBJECT_CAST_IP4_ROUTE(conf_o); - - nmp_object_stackinit( - &oo, - NMP_OBJECT_TYPE_IP4_ROUTE, - &((NMPlatformIP4Route){ - .ifindex = rt->ifindex, - .network = rt->gateway, - .plen = 32, - .metric = nm_platform_ip4_route_get_effective_metric(rt), - .rt_source = rt->rt_source, - .table_coerced = nm_platform_ip_route_get_effective_table( - NM_PLATFORM_IP_ROUTE_CAST(rt)), - })); - } else { - const NMPlatformIP6Route *rt = NMP_OBJECT_CAST_IP6_ROUTE(conf_o); - - nmp_object_stackinit( - &oo, - NMP_OBJECT_TYPE_IP6_ROUTE, - &((NMPlatformIP6Route){ - .ifindex = rt->ifindex, - .network = rt->gateway, - .plen = 128, - .metric = nm_platform_ip6_route_get_effective_metric(rt), - .rt_source = rt->rt_source, - .table_coerced = nm_platform_ip_route_get_effective_table( - NM_PLATFORM_IP_ROUTE_CAST(rt)), - })); - } - - _LOG3D("route-sync: failure to add IPv%c route: %s: %s; try adding direct " - "route to gateway %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1)), - nm_strerror(r), - nmp_object_to_string(&oo, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf2, - sizeof(sbuf2))); - - r2 = nm_platform_ip_route_add(self, - NMP_NLM_FLAG_APPEND - | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, - &oo); - - if (r2 < 0) { - _LOG3D("route-sync: failure to add gateway IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1)), - nm_strerror(r2)); - } - - gateway_route_added = TRUE; - goto sync_route_add; - } else { - _LOG3W("route-sync: failure to add IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string(conf_o, - NMP_OBJECT_TO_STRING_PUBLIC, - sbuf1, - sizeof(sbuf1)), - nm_strerror(r)); - success = FALSE; - } - } - } - } - - if (routes_prune) { - for (i = 0; i < routes_prune->len; i++) { - const NMPObject *prune_o; - - prune_o = routes_prune->pdata[i]; - - nm_assert((NM_IS_IPv4(addr_family) - && NMP_OBJECT_GET_TYPE(prune_o) == NMP_OBJECT_TYPE_IP4_ROUTE) - || (!NM_IS_IPv4(addr_family) - && NMP_OBJECT_GET_TYPE(prune_o) == NMP_OBJECT_TYPE_IP6_ROUTE)); - - if (routes_idx && g_hash_table_lookup(routes_idx, prune_o)) - continue; - - if (!nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, prune_o)) - continue; - - if (!nm_platform_object_delete(self, prune_o)) { - /* ignore error... */ - } - } - } - - return success; -} - -gboolean -nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex) -{ - gboolean success = TRUE; - - _CHECK_SELF(self, klass, FALSE); - - nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) { - gs_unref_ptrarray GPtrArray *routes_prune = NULL; - - routes_prune = nm_platform_ip_route_get_prune_list(self, - AF_INET, - ifindex, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE); - success &= nm_platform_ip_route_sync(self, AF_INET, ifindex, NULL, routes_prune, NULL); - } - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) { - gs_unref_ptrarray GPtrArray *routes_prune = NULL; - - routes_prune = nm_platform_ip_route_get_prune_list(self, - AF_INET6, - ifindex, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE); - success &= nm_platform_ip_route_sync(self, AF_INET6, ifindex, NULL, routes_prune, NULL); - } - return success; -} - -/*****************************************************************************/ - -static guint8 -_ip_route_scope_inv_get_normalized(const NMPlatformIP4Route *route) -{ - /* in kernel, you cannot set scope to RT_SCOPE_NOWHERE (255). - * That means, in NM, we treat RT_SCOPE_NOWHERE as unset, and detect - * it based on the presence of the gateway. In other words, when adding - * a route with scope RT_SCOPE_NOWHERE (in NetworkManager) to kernel, - * the resulting scope will be either "link" or "universe" (depending - * on the gateway). - * - * Note that internally, we track @scope_inv is the inverse of scope, - * so that the default equals zero (~(RT_SCOPE_NOWHERE)). - **/ - if (route->scope_inv == 0) { - if (route->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL)) - return nm_platform_route_scope_inv(RT_SCOPE_HOST); - else { - return nm_platform_route_scope_inv(!route->gateway ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); - } - } - return route->scope_inv; -} - -static guint8 -_route_pref_normalize(guint8 pref) -{ - /* for kernel (and ICMPv6) pref can only have one of 3 values. Normalize. */ - return NM_IN_SET(pref, NM_ICMPV6_ROUTER_PREF_LOW, NM_ICMPV6_ROUTER_PREF_HIGH) - ? pref - : NM_ICMPV6_ROUTER_PREF_MEDIUM; -} - -/** - * nm_platform_ip_route_normalize: - * @addr_family: AF_INET or AF_INET6 - * @route: an NMPlatformIP4Route or NMPlatformIP6Route instance, depending on @addr_family. - * - * Adding a route to kernel via nm_platform_ip_route_add() will normalize/coerce some - * properties of the route. This function modifies (normalizes) the route like it - * would be done by adding the route in kernel. - * - * Note that this function is related to NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY - * in that if two routes compare semantically equal, after normalizing they also shall - * compare equal with NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL. - */ -void -nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route) -{ - NMPlatformIP4Route *r4; - NMPlatformIP6Route *r6; - - route->table_coerced = - nm_platform_route_table_coerce(nm_platform_ip_route_get_effective_table(route)); - route->table_any = FALSE; - - route->rt_source = nmp_utils_ip_config_source_round_trip_rtprot(route->rt_source); - - switch (addr_family) { - case AF_INET: - r4 = (NMPlatformIP4Route *) route; - route->metric = nm_platform_ip4_route_get_effective_metric(r4); - route->metric_any = FALSE; - r4->network = nm_utils_ip4_address_clear_host_address(r4->network, r4->plen); - r4->scope_inv = _ip_route_scope_inv_get_normalized(r4); - break; - case AF_INET6: - r6 = (NMPlatformIP6Route *) route; - route->metric = nm_platform_ip6_route_get_effective_metric(r6); - route->metric_any = FALSE; - nm_utils_ip6_address_clear_host_address(&r6->network, &r6->network, r6->plen); - nm_utils_ip6_address_clear_host_address(&r6->src, &r6->src, r6->src_plen); - break; - default: - nm_assert_not_reached(); - break; - } -} - -static int -_ip_route_add(NMPlatform *self, NMPNlmFlags flags, int addr_family, gconstpointer route) -{ - char sbuf[sizeof(_nm_utils_to_string_buffer)]; - int ifindex; - - _CHECK_SELF(self, klass, FALSE); - - nm_assert(route); - nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - - ifindex = ((const NMPlatformIPRoute *) route)->ifindex; - _LOG3D("route: %-10s IPv%c route: %s", - _nmp_nlm_flag_to_string(flags & NMP_NLM_FLAG_FMASK), - nm_utils_addr_family_to_char(addr_family), - NM_IS_IPv4(addr_family) ? nm_platform_ip4_route_to_string(route, sbuf, sizeof(sbuf)) - : nm_platform_ip6_route_to_string(route, sbuf, sizeof(sbuf))); - - return klass->ip_route_add(self, flags, addr_family, route); -} - -int -nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *route) -{ - int addr_family; - - switch (NMP_OBJECT_GET_TYPE(route)) { - case NMP_OBJECT_TYPE_IP4_ROUTE: - addr_family = AF_INET; - break; - case NMP_OBJECT_TYPE_IP6_ROUTE: - addr_family = AF_INET6; - break; - default: - g_return_val_if_reached(FALSE); - } - - return _ip_route_add(self, flags, addr_family, NMP_OBJECT_CAST_IP_ROUTE(route)); -} - -int -nm_platform_ip4_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route) -{ - return _ip_route_add(self, flags, AF_INET, route); -} - -int -nm_platform_ip6_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route) -{ - return _ip_route_add(self, flags, AF_INET6, route); -} - -gboolean -nm_platform_object_delete(NMPlatform *self, const NMPObject *obj) -{ - int ifindex; - - _CHECK_SELF(self, klass, FALSE); - - switch (NMP_OBJECT_GET_TYPE(obj)) { - case NMP_OBJECT_TYPE_ROUTING_RULE: - _LOGD("%s: delete %s", - NMP_OBJECT_GET_CLASS(obj)->obj_type_name, - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - break; - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - case NMP_OBJECT_TYPE_QDISC: - case NMP_OBJECT_TYPE_TFILTER: - ifindex = NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj)->ifindex; - _LOG3D("%s: delete %s", - NMP_OBJECT_GET_CLASS(obj)->obj_type_name, - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - break; - default: - g_return_val_if_reached(FALSE); - } - - return klass->object_delete(self, obj); -} - -/*****************************************************************************/ - -int -nm_platform_ip_route_get(NMPlatform * self, - int addr_family, - gconstpointer address /* in_addr_t or struct in6_addr */, - int oif_ifindex, - NMPObject ** out_route) -{ - nm_auto_nmpobj NMPObject *route = NULL; - int result; - char buf[NM_UTILS_INET_ADDRSTRLEN]; - char buf_oif[64]; - - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(address, -NME_BUG); - g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), -NME_BUG); - - _LOGT("route: get IPv%c route for: %s%s", - nm_utils_addr_family_to_char(addr_family), - inet_ntop(addr_family, address, buf, sizeof(buf)), - oif_ifindex > 0 ? nm_sprintf_buf(buf_oif, " oif %d", oif_ifindex) : ""); - - if (!klass->ip_route_get) - result = -NME_PL_OPNOTSUPP; - else { - result = klass->ip_route_get(self, addr_family, address, oif_ifindex, &route); - } - - if (result < 0) { - nm_assert(!route); - _LOGW("route: get IPv%c route for: %s failed with %s", - nm_utils_addr_family_to_char(addr_family), - inet_ntop(addr_family, address, buf, sizeof(buf)), - nm_strerror(result)); - } else { - nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(route), - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - nm_assert(!NMP_OBJECT_IS_STACKINIT(route)); - nm_assert(route->parent._ref_count == 1); - _LOGD("route: get IPv%c route for: %s succeeded: %s", - nm_utils_addr_family_to_char(addr_family), - inet_ntop(addr_family, address, buf, sizeof(buf)), - nmp_object_to_string(route, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - NM_SET_OUT(out_route, g_steal_pointer(&route)); - } - return result; -} - -/*****************************************************************************/ - -#define IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS ((int) 1500) -#define IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S \ - ((int) (((IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS + 999) * 3) / 1000)) - -static gint64 -_ip4_dev_route_blacklist_timeout_ms_get(gint64 timeout_msec) -{ - return timeout_msec >> 1; -} - -static gint64 -_ip4_dev_route_blacklist_timeout_ms_marked(gint64 timeout_msec) -{ - return !!(timeout_msec & ((gint64) 1)); -} - -static gboolean -_ip4_dev_route_blacklist_check_cb(gpointer user_data) -{ - NMPlatform * self = user_data; - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - GHashTableIter iter; - const NMPObject * p_obj; - gint64 * p_timeout_ms; - gint64 now_ms; - - priv->ip4_dev_route_blacklist_check_id = 0; - -again: - if (!priv->ip4_dev_route_blacklist_hash) - goto out; - - now_ms = nm_utils_get_monotonic_timestamp_msec(); - - g_hash_table_iter_init(&iter, priv->ip4_dev_route_blacklist_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { - if (!_ip4_dev_route_blacklist_timeout_ms_marked(*p_timeout_ms)) - continue; - - /* unmark because we checked it. */ - *p_timeout_ms = *p_timeout_ms & ~((gint64) 1); - - if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get(*p_timeout_ms)) - continue; - - if (!nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, p_obj)) - continue; - - _LOGT("ip4-dev-route: delete %s", - nmp_object_to_string(p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - nm_platform_object_delete(self, p_obj); - goto again; - } - -out: - return G_SOURCE_REMOVE; -} - -static void -_ip4_dev_route_blacklist_check_schedule(NMPlatform *self) -{ - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - - if (!priv->ip4_dev_route_blacklist_check_id) { - priv->ip4_dev_route_blacklist_check_id = - g_idle_add_full(G_PRIORITY_HIGH, _ip4_dev_route_blacklist_check_cb, self, NULL); - } -} - -static void -_ip4_dev_route_blacklist_notify_route(NMPlatform *self, const NMPObject *obj) -{ - NMPlatformPrivate *priv; - const NMPObject * p_obj; - gint64 * p_timeout_ms; - gint64 now_ms; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP4_ROUTE); - - priv = NM_PLATFORM_GET_PRIVATE(self); - - nm_assert(priv->ip4_dev_route_blacklist_gc_timeout_id); - - if (!g_hash_table_lookup_extended(priv->ip4_dev_route_blacklist_hash, - obj, - (gpointer *) &p_obj, - (gpointer *) &p_timeout_ms)) - return; - - now_ms = nm_utils_get_monotonic_timestamp_msec(); - if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get(*p_timeout_ms)) { - /* already expired. Wait for gc. */ - return; - } - - if (_ip4_dev_route_blacklist_timeout_ms_marked(*p_timeout_ms)) { - nm_assert(priv->ip4_dev_route_blacklist_check_id); - return; - } - - /* We cannot delete it right away because we are in the process of receiving netlink messages. - * It may be possible to do so, but complicated and error prone. - * - * Instead, we mark the entry and schedule an idle action (with high priority). */ - *p_timeout_ms = (*p_timeout_ms) | ((gint64) 1); - _ip4_dev_route_blacklist_check_schedule(self); -} - -static gboolean -_ip4_dev_route_blacklist_gc_timeout_handle(gpointer user_data) -{ - NMPlatform * self = user_data; - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - GHashTableIter iter; - const NMPObject * p_obj; - gint64 * p_timeout_ms; - gint64 now_ms; - - nm_assert(priv->ip4_dev_route_blacklist_gc_timeout_id); - - now_ms = nm_utils_get_monotonic_timestamp_msec(); - - g_hash_table_iter_init(&iter, priv->ip4_dev_route_blacklist_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { - if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get(*p_timeout_ms)) { - _LOGT("ip4-dev-route: cleanup %s", - nmp_object_to_string(p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - g_hash_table_iter_remove(&iter); - } - } - - _ip4_dev_route_blacklist_schedule(self); - return G_SOURCE_CONTINUE; -} - -static void -_ip4_dev_route_blacklist_schedule(NMPlatform *self) -{ - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - - if (!priv->ip4_dev_route_blacklist_hash - || g_hash_table_size(priv->ip4_dev_route_blacklist_hash) == 0) { - nm_clear_pointer(&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); - nm_clear_g_source(&priv->ip4_dev_route_blacklist_gc_timeout_id); - } else { - if (!priv->ip4_dev_route_blacklist_gc_timeout_id) { - /* this timeout is only to garbage collect the expired entries from priv->ip4_dev_route_blacklist_hash. - * It can run infrequently, and it doesn't hurt if expired entries linger around a bit - * longer then necessary. */ - priv->ip4_dev_route_blacklist_gc_timeout_id = - g_timeout_add_seconds(IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S, - _ip4_dev_route_blacklist_gc_timeout_handle, - self); - } - } -} - -/** - * nm_platform_ip4_dev_route_blacklist_set: - * @self: - * @ifindex: - * @ip4_dev_route_blacklist: - * - * When adding an IP address, kernel automatically adds a device route. - * This can be suppressed via the IFA_F_NOPREFIXROUTE address flag. For proper - * IPv6 support, we require kernel support for IFA_F_NOPREFIXROUTE and always - * add the device route manually. - * - * For IPv4, this flag is rather new and we don't rely on it yet. We want to use - * it (but currently still don't). So, for IPv4, kernel possibly adds a device - * route, however it has a wrong metric of zero. We add our own device route (with - * proper metric), but need to delete the route that kernel adds. - * - * The problem is, that kernel does not immediately add the route, when adding - * the address. It only shows up some time later. So, we register here a list - * of blacklisted routes, and when they show up within a time out, we assume it's - * the kernel generated one, and we delete it. - * - * Eventually, we want to get rid of this and use IFA_F_NOPREFIXROUTE for IPv4 - * routes as well. - */ -void -nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, - int ifindex, - GPtrArray * ip4_dev_route_blacklist) -{ - NMPlatformPrivate *priv; - GHashTableIter iter; - const NMPObject * p_obj; - guint i; - gint64 timeout_msec; - gint64 timeout_msec_val; - gint64 * p_timeout_ms; - gboolean needs_check = FALSE; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(ifindex > 0); - - /* TODO: the blacklist should be maintained by NML3Cfg. */ - - priv = NM_PLATFORM_GET_PRIVATE(self); - - /* first, expire all for current ifindex... */ - if (priv->ip4_dev_route_blacklist_hash) { - g_hash_table_iter_init(&iter, priv->ip4_dev_route_blacklist_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { - if (NMP_OBJECT_CAST_IP4_ROUTE(p_obj)->ifindex == ifindex) { - /* we could g_hash_table_iter_remove(&iter) the current entry. - * Instead, just expire it and let _ip4_dev_route_blacklist_gc_timeout_handle() - * handle it. - * - * The assumption is, that ip4_dev_route_blacklist contains the very same entry - * again, with a new timeout. So, we can un-expire it below. */ - *p_timeout_ms = 0; - } - } - } - - if (ip4_dev_route_blacklist && ip4_dev_route_blacklist->len > 0) { - if (!priv->ip4_dev_route_blacklist_hash) { - priv->ip4_dev_route_blacklist_hash = - g_hash_table_new_full((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal, - (GDestroyNotify) nmp_object_unref, - nm_g_slice_free_fcn_gint64); - } - - timeout_msec = nm_utils_get_monotonic_timestamp_msec() + IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS; - timeout_msec_val = (timeout_msec << 1) | ((gint64) 1); - for (i = 0; i < ip4_dev_route_blacklist->len; i++) { - const NMPObject *o; - - needs_check = TRUE; - o = ip4_dev_route_blacklist->pdata[i]; - if (g_hash_table_lookup_extended(priv->ip4_dev_route_blacklist_hash, - o, - (gpointer *) &p_obj, - (gpointer *) &p_timeout_ms)) { - if (nmp_object_equal(p_obj, o)) { - /* un-expire and reuse the entry. */ - _LOGT("ip4-dev-route: register %s (update)", - nmp_object_to_string(p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - *p_timeout_ms = timeout_msec_val; - continue; - } - } - - _LOGT("ip4-dev-route: register %s", - nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - p_timeout_ms = g_slice_new(gint64); - *p_timeout_ms = timeout_msec_val; - g_hash_table_replace(priv->ip4_dev_route_blacklist_hash, - (gpointer) nmp_object_ref(o), - p_timeout_ms); - } - } - - _ip4_dev_route_blacklist_schedule(self); - - if (needs_check) - _ip4_dev_route_blacklist_check_schedule(self); -} - -/*****************************************************************************/ - -int -nm_platform_routing_rule_add(NMPlatform * self, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule) -{ - _CHECK_SELF(self, klass, -NME_BUG); - - g_return_val_if_fail(routing_rule, -NME_BUG); - - _LOGD("routing-rule: adding or updating: %s", - nm_platform_routing_rule_to_string(routing_rule, NULL, 0)); - return klass->routing_rule_add(self, flags, routing_rule); -} - -/*****************************************************************************/ - -int -nm_platform_qdisc_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformQdisc *qdisc) -{ - int ifindex = qdisc->ifindex; - _CHECK_SELF(self, klass, -NME_BUG); - - /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind - * is undefined. */ - - _LOG3D("adding or updating a qdisc: %s", nm_platform_qdisc_to_string(qdisc, NULL, 0)); - return klass->qdisc_add(self, flags, qdisc); -} - -/** - * nm_platform_qdisc_sync: - * @self: the #NMPlatform instance - * @ifindex: the ifindex where to configure the qdiscs. - * @known_qdiscs: the list of qdiscs (#NMPObject). - * - * The function promises not to take any reference to the qdisc - * instances from @known_qdiscs, nor to keep them around after - * the function returns. This is important, because it allows the - * caller to pass NMPlatformQdisc instances which "kind" string - * have a limited lifetime. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_qdisc_sync(NMPlatform *self, int ifindex, GPtrArray *known_qdiscs) -{ - gs_unref_ptrarray GPtrArray *plat_qdiscs = NULL; - NMPLookup lookup; - guint i; - gboolean success = TRUE; - gs_unref_hashtable GHashTable *known_qdiscs_idx = NULL; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(ifindex > 0); - - known_qdiscs_idx = - g_hash_table_new((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal); - if (known_qdiscs) { - for (i = 0; i < known_qdiscs->len; i++) { - const NMPObject *q = g_ptr_array_index(known_qdiscs, i); - - if (!g_hash_table_insert(known_qdiscs_idx, (gpointer) q, (gpointer) q)) { - _LOGW("duplicate qdisc %s", nm_platform_qdisc_to_string(&q->qdisc, NULL, 0)); - return FALSE; - } - } - } - - plat_qdiscs = - nm_platform_lookup_clone(self, - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_QDISC, ifindex), - NULL, - NULL); - if (plat_qdiscs) { - for (i = 0; i < plat_qdiscs->len; i++) { - const NMPObject *p = g_ptr_array_index(plat_qdiscs, i); - const NMPObject *k; - - /* look up known qdisc with same parent */ - k = g_hash_table_lookup(known_qdiscs_idx, p); - - if (k) { - const NMPlatformQdisc *qdisc_k = NMP_OBJECT_CAST_QDISC(k); - const NMPlatformQdisc *qdisc_p = NMP_OBJECT_CAST_QDISC(p); - - /* check other fields */ - if (nm_platform_qdisc_cmp_full(qdisc_k, qdisc_p, FALSE) != 0 - || (qdisc_k->handle != qdisc_p->handle && qdisc_k != 0)) { - k = NULL; - } - } - - if (k) { - g_hash_table_remove(known_qdiscs_idx, k); - } else { - /* can't delete qdisc with zero handle */ - if (TC_H_MAJ(p->qdisc.handle) != 0) { - success &= nm_platform_object_delete(self, p); - } - } - } - } - - if (known_qdiscs) { - for (i = 0; i < known_qdiscs->len; i++) { - const NMPObject *q = g_ptr_array_index(known_qdiscs, i); - - if (g_hash_table_contains(known_qdiscs_idx, q)) { - success &= - (nm_platform_qdisc_add(self, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_QDISC(q)) >= 0); - } - } - } - - return success; -} - -/*****************************************************************************/ - -int -nm_platform_tfilter_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformTfilter *tfilter) -{ - int ifindex = tfilter->ifindex; - _CHECK_SELF(self, klass, -NME_BUG); - - /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind - * and tfilter.action.kind is undefined. */ - - _LOG3D("adding or updating a tfilter: %s", nm_platform_tfilter_to_string(tfilter, NULL, 0)); - return klass->tfilter_add(self, flags, tfilter); -} - -/** - * nm_platform_qdisc_sync: - * @self: the #NMPlatform instance - * @ifindex: the ifindex where to configure the qdiscs. - * @known_tfilters: the list of tfilters (#NMPObject). - * - * The function promises not to take any reference to the tfilter - * instances from @known_tfilters, nor to keep them around after - * the function returns. This is important, because it allows the - * caller to pass NMPlatformTfilter instances which "kind" string - * have a limited lifetime. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_tfilter_sync(NMPlatform *self, int ifindex, GPtrArray *known_tfilters) -{ - gs_unref_ptrarray GPtrArray *plat_tfilters = NULL; - NMPLookup lookup; - guint i; - gboolean success = TRUE; - gs_unref_hashtable GHashTable *known_tfilters_idx = NULL; - - nm_assert(NM_IS_PLATFORM(self)); - nm_assert(ifindex > 0); - - known_tfilters_idx = - g_hash_table_new((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal); - - if (known_tfilters) { - for (i = 0; i < known_tfilters->len; i++) { - const NMPObject *q = g_ptr_array_index(known_tfilters, i); - - g_hash_table_insert(known_tfilters_idx, (gpointer) q, (gpointer) q); - } - } - - plat_tfilters = - nm_platform_lookup_clone(self, - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_TFILTER, ifindex), - NULL, - NULL); - - if (plat_tfilters) { - for (i = 0; i < plat_tfilters->len; i++) { - const NMPObject *q = g_ptr_array_index(plat_tfilters, i); - - if (!g_hash_table_lookup(known_tfilters_idx, q)) - success &= nm_platform_object_delete(self, q); - } - } - - if (known_tfilters) { - for (i = 0; i < known_tfilters->len; i++) { - const NMPObject *q = g_ptr_array_index(known_tfilters, i); - - success &= - (nm_platform_tfilter_add(self, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_TFILTER(q)) >= 0); - } - } - - return success; -} - -/*****************************************************************************/ - -const char * -nm_platform_vlan_qos_mapping_to_string(const char * name, - const NMVlanQosMapping *map, - gsize n_map, - char * buf, - gsize len) -{ - gsize i; - char *b; - - nm_utils_to_string_buffer_init(&buf, &len); - - if (!n_map) { - nm_utils_strbuf_append_str(&buf, &len, ""); - return buf; - } - - if (!map) - g_return_val_if_reached(""); - - b = buf; - - if (name) { - nm_utils_strbuf_append_str(&b, &len, name); - nm_utils_strbuf_append_str(&b, &len, " {"); - } else - nm_utils_strbuf_append_c(&b, &len, '{'); - - for (i = 0; i < n_map; i++) - nm_utils_strbuf_append(&b, &len, " %u:%u", map[i].from, map[i].to); - nm_utils_strbuf_append_str(&b, &len, " }"); - return buf; -} - -static const char * -_lifetime_to_string(guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size) -{ - if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT) - return "forever"; - - g_snprintf(buf, - buf_size, - "%usec", - nm_utils_lifetime_rebase_relative_time_on_now(timestamp, lifetime, now)); - return buf; -} - -static const char * -_lifetime_summary_to_string(gint32 now, - guint32 timestamp, - guint32 preferred, - guint32 lifetime, - char * buf, - size_t buf_size) -{ - g_snprintf(buf, - buf_size, - " lifetime %d-%u[%u,%u]", - (signed) now, - (unsigned) timestamp, - (unsigned) preferred, - (unsigned) lifetime); - return buf; -} - -/** - * nm_platform_link_to_string: - * @route: pointer to NMPlatformLink address structure - * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. - * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. - * - * A method for converting an link struct into a string representation. - * - * Returns: a string representation of the link. - */ -const char * -nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len) -{ - char master[20]; - char parent[20]; - char str_flags[1 + NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 1]; - char str_highlighted_flags[50]; - char * s; - gsize l; - char str_addrmode[30]; - char str_address[NM_UTILS_HWADDR_LEN_MAX * 3]; - char str_broadcast[NM_UTILS_HWADDR_LEN_MAX * 3]; - char str_inet6_token[NM_UTILS_INET_ADDRSTRLEN]; - const char *str_link_type; - - if (!nm_utils_to_string_buffer_init_null(link, &buf, &len)) - return buf; - - s = str_highlighted_flags; - l = sizeof(str_highlighted_flags); - if (NM_FLAGS_HAS(link->n_ifi_flags, IFF_NOARP)) - nm_utils_strbuf_append_str(&s, &l, "NOARP,"); - if (NM_FLAGS_HAS(link->n_ifi_flags, IFF_UP)) - nm_utils_strbuf_append_str(&s, &l, "UP"); - else - nm_utils_strbuf_append_str(&s, &l, "DOWN"); - if (link->connected) - nm_utils_strbuf_append_str(&s, &l, ",LOWER_UP"); - nm_assert(s > str_highlighted_flags && l > 0); - - if (link->n_ifi_flags) { - str_flags[0] = ';'; - nm_platform_link_flags2str(link->n_ifi_flags, &str_flags[1], sizeof(str_flags) - 1); - } else - str_flags[0] = '\0'; - - if (link->master) - g_snprintf(master, sizeof(master), " master %d", link->master); - else - master[0] = 0; - - if (link->parent > 0) - g_snprintf(parent, sizeof(parent), "@%d", link->parent); - else if (link->parent == NM_PLATFORM_LINK_OTHER_NETNS) - g_strlcpy(parent, "@other-netns", sizeof(parent)); - else - parent[0] = 0; - - _nmp_link_address_to_string(&link->l_address, str_address); - _nmp_link_address_to_string(&link->l_broadcast, str_broadcast); - - str_link_type = nm_link_type_to_string(link->type); - - g_snprintf( - buf, - len, - "%d: " /* ifindex */ - "%s" /* name */ - "%s" /* parent */ - " <%s%s>" /* flags */ - " mtu %d" - "%s" /* master */ - " arp %u" /* arptype */ - " %s" /* link->type */ - "%s%s" /* kind */ - "%s" /* is-in-udev */ - "%s%s" /* addr-gen-mode */ - "%s%s" /* l_address */ - "%s%s" /* l_broadcast */ - "%s%s" /* inet6_token */ - "%s%s" /* driver */ - " rx:%" G_GUINT64_FORMAT ",%" G_GUINT64_FORMAT " tx:%" G_GUINT64_FORMAT - ",%" G_GUINT64_FORMAT, - link->ifindex, - link->name, - parent, - str_highlighted_flags, - str_flags, - link->mtu, - master, - link->arptype, - str_link_type ?: "???", - link->kind ? (g_strcmp0(str_link_type, link->kind) ? "/" : "*") : "?", - link->kind && g_strcmp0(str_link_type, link->kind) ? link->kind : "", - link->initialized ? " init" : " not-init", - link->inet6_addr_gen_mode_inv ? " addrgenmode " : "", - link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str( - _nm_platform_uint8_inv(link->inet6_addr_gen_mode_inv), - str_addrmode, - sizeof(str_addrmode)) - : "", - str_address[0] ? " addr " : "", - str_address[0] ? str_address : "", - str_broadcast[0] ? " brd " : "", - str_broadcast[0] ? str_broadcast : "", - link->inet6_token.id ? " inet6token " : "", - link->inet6_token.id - ? nm_utils_inet6_interface_identifier_to_token(link->inet6_token, str_inet6_token) - : "", - link->driver ? " driver " : "", - link->driver ?: "", - link->rx_packets, - link->rx_bytes, - link->tx_packets, - link->tx_bytes); - return buf; -} - -const NMPlatformLnkBridge nm_platform_lnk_bridge_default = { - .forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF_SYS, - .hello_time = NM_BRIDGE_HELLO_TIME_DEF_SYS, - .max_age = NM_BRIDGE_MAX_AGE_DEF_SYS, - .ageing_time = NM_BRIDGE_AGEING_TIME_DEF_SYS, - .stp_state = FALSE, - .priority = NM_BRIDGE_PRIORITY_DEF, - .vlan_protocol = 0x8100, - .vlan_stats_enabled = NM_BRIDGE_VLAN_STATS_ENABLED_DEF, - .group_fwd_mask = 0, - .group_addr = NM_ETHER_ADDR_INIT(NM_BRIDGE_GROUP_ADDRESS_DEF_BIN), - .mcast_snooping = NM_BRIDGE_MULTICAST_SNOOPING_DEF, - .mcast_router = 1, - .mcast_query_use_ifaddr = NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF, - .mcast_querier = NM_BRIDGE_MULTICAST_QUERIER_DEF, - .mcast_hash_max = NM_BRIDGE_MULTICAST_HASH_MAX_DEF, - .mcast_last_member_count = NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF, - .mcast_startup_query_count = NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF, - .mcast_last_member_interval = NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF, - .mcast_membership_interval = NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF, - .mcast_querier_interval = NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF, - .mcast_query_interval = NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF, - .mcast_query_response_interval = NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF, - .mcast_startup_query_interval = NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF, -}; - -const char * -nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len) -{ - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf(buf, - len, - "forward_delay %u" - " hello_time %u" - " max_age %u" - " ageing_time %u" - " stp_state %d" - " priority %u" - " vlan_protocol %u" - " vlan_stats_enabled %d" - " group_fwd_mask %#x" - " group_address " NM_ETHER_ADDR_FORMAT_STR " mcast_snooping %d" - " mcast_router %u" - " mcast_query_use_ifaddr %d" - " mcast_querier %d" - " mcast_hash_max %u" - " mcast_last_member_count %u" - " mcast_startup_query_count %u" - " mcast_last_member_interval %" G_GUINT64_FORMAT - " mcast_membership_interval %" G_GUINT64_FORMAT - " mcast_querier_interval %" G_GUINT64_FORMAT - " mcast_query_interval %" G_GUINT64_FORMAT - " mcast_query_response_interval %" G_GUINT64_FORMAT - " mcast_startup_query_interval %" G_GUINT64_FORMAT "", - lnk->forward_delay, - lnk->hello_time, - lnk->max_age, - lnk->ageing_time, - (int) lnk->stp_state, - lnk->priority, - lnk->vlan_protocol, - (int) lnk->vlan_stats_enabled, - lnk->group_fwd_mask, - NM_ETHER_ADDR_FORMAT_VAL(&lnk->group_addr), - (int) lnk->mcast_snooping, - lnk->mcast_router, - (int) lnk->mcast_query_use_ifaddr, - (int) lnk->mcast_querier, - lnk->mcast_hash_max, - lnk->mcast_last_member_count, - lnk->mcast_startup_query_count, - lnk->mcast_last_member_interval, - lnk->mcast_membership_interval, - lnk->mcast_querier_interval, - lnk->mcast_query_interval, - lnk->mcast_query_response_interval, - lnk->mcast_startup_query_interval); - return buf; -} - -const char * -nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tos[30]; - char str_parent_ifindex[30]; - char str_input_flags[30]; - char str_output_flags[30]; - char str_input_key[30]; - char str_input_key1[NM_UTILS_INET_ADDRSTRLEN]; - char str_output_key[30]; - char str_output_key1[NM_UTILS_INET_ADDRSTRLEN]; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf( - buf, - len, - "gre%s" /* is_tap */ - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tos */ - "%s" /* path_mtu_discovery */ - "%s" /* iflags */ - "%s" /* oflags */ - "%s" /* ikey */ - "%s" /* okey */ - "", - lnk->is_tap ? "tap" : "", - lnk->remote ? nm_sprintf_buf(str_remote, - " remote %s", - _nm_utils_inet4_ntop(lnk->remote, str_remote1)) - : "", - lnk->local - ? nm_sprintf_buf(str_local, " local %s", _nm_utils_inet4_ntop(lnk->local, str_local1)) - : "", - lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) - : "", - lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos)) - : "", - lnk->path_mtu_discovery ? "" : " nopmtudisc", - lnk->input_flags ? nm_sprintf_buf(str_input_flags, " iflags 0x%x", lnk->input_flags) : "", - lnk->output_flags ? nm_sprintf_buf(str_output_flags, " oflags 0x%x", lnk->output_flags) - : "", - NM_FLAGS_HAS(lnk->input_flags, GRE_KEY) || lnk->input_key - ? nm_sprintf_buf(str_input_key, - " ikey %s", - _nm_utils_inet4_ntop(lnk->input_key, str_input_key1)) - : "", - NM_FLAGS_HAS(lnk->output_flags, GRE_KEY) || lnk->output_key - ? nm_sprintf_buf(str_output_key, - " okey %s", - _nm_utils_inet4_ntop(lnk->output_key, str_output_key1)) - : ""); - return buf; -} - -const char * -nm_platform_lnk_infiniband_to_string(const NMPlatformLnkInfiniband *lnk, char *buf, gsize len) -{ - char str_p_key[64]; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf(buf, - len, - "infiniband" - "%s" /* p_key */ - "%s%s" /* mode */ - "", - lnk->p_key ? nm_sprintf_buf(str_p_key, " pkey %d", lnk->p_key) : "", - lnk->mode ? " mode " : "", - lnk->mode ?: ""); - return buf; -} - -const char * -nm_platform_lnk_ip6tnl_to_string(const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tclass[30]; - char str_flow[30]; - char str_encap[30]; - char str_proto[30]; - char str_parent_ifindex[30]; - char *str_type; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - if (lnk->is_gre) - str_type = lnk->is_tap ? "ip6gretap" : "ip6gre"; - else - str_type = "ip6tnl"; - - g_snprintf( - buf, - len, - "%s" /* type */ - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tclass */ - "%s" /* encap limit */ - "%s" /* flow label */ - "%s" /* proto */ - " flags 0x%x" - "", - str_type, - nm_sprintf_buf(str_remote, " remote %s", _nm_utils_inet6_ntop(&lnk->remote, str_remote1)), - nm_sprintf_buf(str_local, " local %s", _nm_utils_inet6_ntop(&lnk->local, str_local1)), - lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) - : "", - lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tclass == 1 ? " tclass inherit" - : nm_sprintf_buf(str_tclass, " tclass 0x%x", lnk->tclass), - nm_sprintf_buf(str_encap, " encap-limit %u", lnk->encap_limit), - nm_sprintf_buf(str_flow, " flow-label 0x05%x", lnk->flow_label), - nm_sprintf_buf(str_proto, " proto %u", lnk->proto), - (guint) lnk->flags); - return buf; -} - -const char * -nm_platform_lnk_ipip_to_string(const NMPlatformLnkIpIp *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tos[30]; - char str_parent_ifindex[30]; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf( - buf, - len, - "ipip" - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tos */ - "%s" /* path_mtu_discovery */ - "", - lnk->remote ? nm_sprintf_buf(str_remote, - " remote %s", - _nm_utils_inet4_ntop(lnk->remote, str_remote1)) - : "", - lnk->local - ? nm_sprintf_buf(str_local, " local %s", _nm_utils_inet4_ntop(lnk->local, str_local1)) - : "", - lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) - : "", - lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos)) - : "", - lnk->path_mtu_discovery ? "" : " nopmtudisc"); - return buf; -} - -const char * -nm_platform_lnk_macsec_to_string(const NMPlatformLnkMacsec *lnk, char *buf, gsize len) -{ - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf(buf, - len, - "macsec " - "sci %016llx " - "protect %s " - "cipher %016llx " - "icvlen %u " - "encodingsa %u " - "validate %u " - "encrypt %s " - "send_sci %s " - "end_station %s " - "scb %s " - "replay %s", - (unsigned long long) lnk->sci, - lnk->protect ? "on" : "off", - (unsigned long long) lnk->cipher_suite, - lnk->icv_length, - lnk->encoding_sa, - lnk->validation, - lnk->encrypt ? "on" : "off", - lnk->include_sci ? "on" : "off", - lnk->es ? "on" : "off", - lnk->scb ? "on" : "off", - lnk->replay_protect ? "on" : "off"); - return buf; -} - -const char * -nm_platform_lnk_macvlan_to_string(const NMPlatformLnkMacvlan *lnk, char *buf, gsize len) -{ - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf(buf, - len, - "%s mode %u %s", - lnk->tap ? "macvtap" : "macvlan", - lnk->mode, - lnk->no_promisc ? "not-promisc" : "promisc"); - return buf; -} - -const char * -nm_platform_lnk_sit_to_string(const NMPlatformLnkSit *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tos[30]; - char str_flags[30]; - char str_proto[30]; - char str_parent_ifindex[30]; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - g_snprintf( - buf, - len, - "sit" - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tos */ - "%s" /* path_mtu_discovery */ - "%s" /* flags */ - "%s" /* proto */ - "", - lnk->remote ? nm_sprintf_buf(str_remote, - " remote %s", - _nm_utils_inet4_ntop(lnk->remote, str_remote1)) - : "", - lnk->local - ? nm_sprintf_buf(str_local, " local %s", _nm_utils_inet4_ntop(lnk->local, str_local1)) - : "", - lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) - : "", - lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos)) - : "", - lnk->path_mtu_discovery ? "" : " nopmtudisc", - lnk->flags ? nm_sprintf_buf(str_flags, " flags 0x%x", lnk->flags) : "", - lnk->proto ? nm_sprintf_buf(str_proto, " proto 0x%x", lnk->proto) : ""); - return buf; -} - -const char * -nm_platform_lnk_tun_to_string(const NMPlatformLnkTun *lnk, char *buf, gsize len) -{ - char str_owner[50]; - char str_group[50]; - char str_type[50]; - const char *type; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - if (lnk->type == IFF_TUN) - type = "tun"; - else if (lnk->type == IFF_TAP) - type = "tap"; - else - type = nm_sprintf_buf(str_type, "tun type %u", (guint) lnk->type); - - g_snprintf(buf, - len, - "%s" /* type */ - "%s" /* pi */ - "%s" /* vnet_hdr */ - "%s" /* multi_queue */ - "%s" /* persist */ - "%s" /* owner */ - "%s" /* group */ - "", - type, - lnk->pi ? " pi" : "", - lnk->vnet_hdr ? " vnet_hdr" : "", - lnk->multi_queue ? " multi_queue" : "", - lnk->persist ? " persist" : "", - lnk->owner_valid ? nm_sprintf_buf(str_owner, " owner %u", (guint) lnk->owner) : "", - lnk->group_valid ? nm_sprintf_buf(str_group, " group %u", (guint) lnk->group) : ""); - return buf; -} - -const char * -nm_platform_lnk_vlan_to_string(const NMPlatformLnkVlan *lnk, char *buf, gsize len) -{ - char *b; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - b = buf; - - nm_utils_strbuf_append(&b, &len, "vlan %u", lnk->id); - if (lnk->flags) - nm_utils_strbuf_append(&b, &len, " flags 0x%x", lnk->flags); - return buf; -} - -const char * -nm_platform_lnk_vrf_to_string(const NMPlatformLnkVrf *lnk, char *buf, gsize len) -{ - char *b; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - b = buf; - - nm_utils_strbuf_append(&b, &len, "table %u", lnk->table); - return buf; -} - -const char * -nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize len) -{ - char str_group[100]; - char str_group6[100]; - char str_local[100]; - char str_local6[100]; - char str_dev[25]; - char str_limit[25]; - char str_src_port[35]; - char str_dst_port[25]; - char str_tos[25]; - char str_ttl[25]; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - if (lnk->group == 0) - str_group[0] = '\0'; - else { - g_snprintf(str_group, - sizeof(str_group), - " %s %s", - IN_MULTICAST(ntohl(lnk->group)) ? "group" : "remote", - _nm_utils_inet4_ntop(lnk->group, sbuf)); - } - if (IN6_IS_ADDR_UNSPECIFIED(&lnk->group6)) - str_group6[0] = '\0'; - else { - g_snprintf(str_group6, - sizeof(str_group6), - " %s%s %s", - IN6_IS_ADDR_MULTICAST(&lnk->group6) ? "group" : "remote", - str_group[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ - _nm_utils_inet6_ntop(&lnk->group6, sbuf)); - } - - if (lnk->local == 0) - str_local[0] = '\0'; - else { - g_snprintf(str_local, - sizeof(str_local), - " local %s", - _nm_utils_inet4_ntop(lnk->local, sbuf)); - } - if (IN6_IS_ADDR_UNSPECIFIED(&lnk->local6)) - str_local6[0] = '\0'; - else { - g_snprintf(str_local6, - sizeof(str_local6), - " local%s %s", - str_local[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ - _nm_utils_inet6_ntop(&lnk->local6, sbuf)); - } - - g_snprintf( - buf, - len, - "vxlan" - " id %u" /* id */ - "%s%s" /* group/group6 */ - "%s%s" /* local/local6 */ - "%s" /* dev */ - "%s" /* src_port_min/src_port_max */ - "%s" /* dst_port */ - "%s" /* learning */ - "%s" /* proxy */ - "%s" /* rsc */ - "%s" /* l2miss */ - "%s" /* l3miss */ - "%s" /* tos */ - "%s" /* ttl */ - " ageing %u" /* ageing */ - "%s" /* limit */ - "", - (guint) lnk->id, - str_group, - str_group6, - str_local, - str_local6, - lnk->parent_ifindex ? nm_sprintf_buf(str_dev, " dev %d", lnk->parent_ifindex) : "", - lnk->src_port_min || lnk->src_port_max - ? nm_sprintf_buf(str_src_port, " srcport %u %u", lnk->src_port_min, lnk->src_port_max) - : "", - lnk->dst_port ? nm_sprintf_buf(str_dst_port, " dstport %u", lnk->dst_port) : "", - !lnk->learning ? " nolearning" : "", - lnk->proxy ? " proxy" : "", - lnk->rsc ? " rsc" : "", - lnk->l2miss ? " l2miss" : "", - lnk->l3miss ? " l3miss" : "", - lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos %#x", lnk->tos), - lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : "", - lnk->ageing, - lnk->limit ? nm_sprintf_buf(str_limit, " maxaddr %u", lnk->limit) : ""); - return buf; -} - -const char * -nm_platform_wireguard_peer_to_string(const NMPWireGuardPeer *peer, char *buf, gsize len) -{ - char * buf0 = buf; - gs_free char *public_key_b64 = NULL; - char s_sockaddr[NM_UTILS_INET_ADDRSTRLEN + 100]; - char s_endpoint[20 + sizeof(s_sockaddr)]; - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - char s_keepalive[100]; - guint i; - - nm_utils_to_string_buffer_init(&buf, &len); - - public_key_b64 = g_base64_encode(peer->public_key, sizeof(peer->public_key)); - - if (peer->endpoint.sa.sa_family != AF_UNSPEC) { - nm_sprintf_buf( - s_endpoint, - " endpoint %s", - nm_sock_addr_union_to_string(&peer->endpoint, s_sockaddr, sizeof(s_sockaddr))); - } else - s_endpoint[0] = '\0'; - - nm_utils_strbuf_append( - &buf, - &len, - "public-key %s" - "%s" /* preshared-key */ - "%s" /* endpoint */ - " rx %" G_GUINT64_FORMAT " tx %" G_GUINT64_FORMAT "%s" /* persistent-keepalive */ - "%s", /* allowed-ips */ - public_key_b64, - nm_utils_memeqzero_secret(peer->preshared_key, sizeof(peer->preshared_key)) - ? "" - : " preshared-key (hidden)", - s_endpoint, - peer->rx_bytes, - peer->tx_bytes, - peer->persistent_keepalive_interval > 0 - ? nm_sprintf_buf(s_keepalive, - " keepalive %u", - (guint) peer->persistent_keepalive_interval) - : "", - peer->allowed_ips_len > 0 ? " allowed-ips" : ""); - - for (i = 0; i < peer->allowed_ips_len; i++) { - const NMPWireGuardAllowedIP *allowed_ip = &peer->allowed_ips[i]; - - nm_utils_strbuf_append(&buf, - &len, - " %s/%u", - nm_utils_inet_ntop(allowed_ip->family, &allowed_ip->addr, s_addr), - allowed_ip->mask); - } - - return buf0; -} - -const char * -nm_platform_lnk_wireguard_to_string(const NMPlatformLnkWireGuard *lnk, char *buf, gsize len) -{ - gs_free char *public_b64 = NULL; - - if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) - return buf; - - if (!nm_utils_memeqzero(lnk->public_key, sizeof(lnk->public_key))) - public_b64 = g_base64_encode(lnk->public_key, sizeof(lnk->public_key)); - - g_snprintf(buf, - len, - "wireguard" - "%s%s" /* public-key */ - "%s" /* private-key */ - " listen-port %u" - " fwmark 0x%x", - public_b64 ? " public-key " : "", - public_b64 ?: "", - nm_utils_memeqzero_secret(lnk->private_key, sizeof(lnk->private_key)) - ? "" - : " private-key (hidden)", - lnk->listen_port, - lnk->fwmark); - - return buf; -} - -/** - * nm_platform_ip4_address_to_string: - * @route: pointer to NMPlatformIP4Address address structure - * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. - * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. - * - * A method for converting an address struct into a string representation. - * - * Example output: "" - * - * Returns: a string representation of the address. - */ -const char * -nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len) -{ - char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; - char s_address[INET_ADDRSTRLEN]; - char s_peer[INET_ADDRSTRLEN]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char str_label[32]; - char str_lft[30], str_pref[30], str_time[50], s_source[50]; - char * str_peer = NULL; - const char *str_lft_p, *str_pref_p, *str_time_p; - gint32 now = nm_utils_get_monotonic_timestamp_sec(); - in_addr_t broadcast_address; - char str_broadcast[INET_ADDRSTRLEN]; - - if (!nm_utils_to_string_buffer_init_null(address, &buf, &len)) - return buf; - - inet_ntop(AF_INET, &address->address, s_address, sizeof(s_address)); - - if (address->peer_address != address->address) { - inet_ntop(AF_INET, &address->peer_address, s_peer, sizeof(s_peer)); - str_peer = g_strconcat(" ptp ", s_peer, NULL); - } - - _to_string_dev(NULL, address->ifindex, str_dev, sizeof(str_dev)); - - if (*address->label) - g_snprintf(str_label, sizeof(str_label), " label %s", address->label); - else - str_label[0] = 0; - - str_lft_p = _lifetime_to_string(address->timestamp, - address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT, - now, - str_lft, - sizeof(str_lft)), - str_pref_p = - (address->lifetime == address->preferred) - ? str_lft_p - : (_lifetime_to_string(address->timestamp, - address->lifetime ? MIN(address->preferred, address->lifetime) - : NM_PLATFORM_LIFETIME_PERMANENT, - now, - str_pref, - sizeof(str_pref))); - str_time_p = _lifetime_summary_to_string(now, - address->timestamp, - address->preferred, - address->lifetime, - str_time, - sizeof(str_time)); - - broadcast_address = nm_platform_ip4_broadcast_address_from_addr(address); - - g_snprintf( - buf, - len, - "%s/%d" - "%s%s" /* broadcast */ - " lft %s" - " pref %s" - "%s" /* time */ - "%s" /* peer */ - "%s" /* dev */ - "%s" /* flags */ - "%s" /* label */ - " src %s" - "%s" /* external */ - "%s" /* ip4acd_not_ready */ - "", - s_address, - address->plen, - broadcast_address != 0u || address->use_ip4_broadcast_address - ? (address->use_ip4_broadcast_address ? " brd " : " brd* ") - : "", - broadcast_address != 0u || address->use_ip4_broadcast_address - ? _nm_utils_inet4_ntop(broadcast_address, str_broadcast) - : "", - str_lft_p, - str_pref_p, - str_time_p, - str_peer ?: "", - str_dev, - _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)), - str_label, - nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)), - address->external ? " ext" : "", - address->ip4acd_not_ready ? " ip4acd-not-ready" : ""); - g_free(str_peer); - return buf; -} - -NM_UTILS_FLAGS2STR_DEFINE(nm_platform_link_flags2str, - unsigned, - NM_UTILS_FLAGS2STR(IFF_LOOPBACK, "loopback"), - NM_UTILS_FLAGS2STR(IFF_BROADCAST, "broadcast"), - NM_UTILS_FLAGS2STR(IFF_POINTOPOINT, "pointopoint"), - NM_UTILS_FLAGS2STR(IFF_MULTICAST, "multicast"), - NM_UTILS_FLAGS2STR(IFF_NOARP, "noarp"), - NM_UTILS_FLAGS2STR(IFF_ALLMULTI, "allmulti"), - NM_UTILS_FLAGS2STR(IFF_PROMISC, "promisc"), - NM_UTILS_FLAGS2STR(IFF_MASTER, "master"), - NM_UTILS_FLAGS2STR(IFF_SLAVE, "slave"), - NM_UTILS_FLAGS2STR(IFF_DEBUG, "debug"), - NM_UTILS_FLAGS2STR(IFF_DYNAMIC, "dynamic"), - NM_UTILS_FLAGS2STR(IFF_AUTOMEDIA, "automedia"), - NM_UTILS_FLAGS2STR(IFF_PORTSEL, "portsel"), - NM_UTILS_FLAGS2STR(IFF_NOTRAILERS, "notrailers"), - NM_UTILS_FLAGS2STR(IFF_UP, "up"), - NM_UTILS_FLAGS2STR(IFF_RUNNING, "running"), - NM_UTILS_FLAGS2STR(IFF_LOWER_UP, "lowerup"), - NM_UTILS_FLAGS2STR(IFF_DORMANT, "dormant"), - NM_UTILS_FLAGS2STR(IFF_ECHO, "echo"), ); - -NM_UTILS_ENUM2STR_DEFINE(nm_platform_link_inet6_addrgenmode2str, - guint8, - NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_NONE, "none"), - NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"), - NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"), - NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_RANDOM, "random"), ); - -NM_UTILS_FLAGS2STR_DEFINE(nm_platform_addr_flags2str, - unsigned, - NM_UTILS_FLAGS2STR(IFA_F_SECONDARY, "secondary"), - NM_UTILS_FLAGS2STR(IFA_F_NODAD, "nodad"), - NM_UTILS_FLAGS2STR(IFA_F_OPTIMISTIC, "optimistic"), - NM_UTILS_FLAGS2STR(IFA_F_HOMEADDRESS, "homeaddress"), - NM_UTILS_FLAGS2STR(IFA_F_DEPRECATED, "deprecated"), - NM_UTILS_FLAGS2STR(IFA_F_PERMANENT, "permanent"), - NM_UTILS_FLAGS2STR(IFA_F_MANAGETEMPADDR, "mngtmpaddr"), - NM_UTILS_FLAGS2STR(IFA_F_NOPREFIXROUTE, "noprefixroute"), - NM_UTILS_FLAGS2STR(IFA_F_TENTATIVE, "tentative"), ); - -NM_UTILS_ENUM2STR_DEFINE(nm_platform_route_scope2str, - int, - NM_UTILS_ENUM2STR(RT_SCOPE_NOWHERE, "nowhere"), - NM_UTILS_ENUM2STR(RT_SCOPE_HOST, "host"), - NM_UTILS_ENUM2STR(RT_SCOPE_LINK, "link"), - NM_UTILS_ENUM2STR(RT_SCOPE_SITE, "site"), - NM_UTILS_ENUM2STR(RT_SCOPE_UNIVERSE, "global"), ); - -/** - * nm_platform_ip6_address_to_string: - * @route: pointer to NMPlatformIP6Address address structure - * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. - * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. - * - * A method for converting an address struct into a string representation. - * - * Example output: "2001:db8:0:f101::1/64 lft 4294967295 pref 4294967295 time 16922666 on dev em1" - * - * Returns: a string representation of the address. - */ -const char * -nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len) -{ - char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; - char s_address[INET6_ADDRSTRLEN]; - char s_peer[INET6_ADDRSTRLEN]; - char str_lft[30], str_pref[30], str_time[50], s_source[50]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char * str_peer = NULL; - const char *str_lft_p, *str_pref_p, *str_time_p; - gint32 now = nm_utils_get_monotonic_timestamp_sec(); - - if (!nm_utils_to_string_buffer_init_null(address, &buf, &len)) - return buf; - - inet_ntop(AF_INET6, &address->address, s_address, sizeof(s_address)); - - if (!IN6_IS_ADDR_UNSPECIFIED(&address->peer_address)) { - inet_ntop(AF_INET6, &address->peer_address, s_peer, sizeof(s_peer)); - str_peer = g_strconcat(" ptp ", s_peer, NULL); - } - - _to_string_dev(NULL, address->ifindex, str_dev, sizeof(str_dev)); - - str_lft_p = _lifetime_to_string(address->timestamp, - address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT, - now, - str_lft, - sizeof(str_lft)), - str_pref_p = - (address->lifetime == address->preferred) - ? str_lft_p - : (_lifetime_to_string(address->timestamp, - address->lifetime ? MIN(address->preferred, address->lifetime) - : NM_PLATFORM_LIFETIME_PERMANENT, - now, - str_pref, - sizeof(str_pref))); - str_time_p = _lifetime_summary_to_string(now, - address->timestamp, - address->preferred, - address->lifetime, - str_time, - sizeof(str_time)); - - g_snprintf( - buf, - len, - "%s/%d lft %s pref %s%s%s%s%s src %s%s", - s_address, - address->plen, - str_lft_p, - str_pref_p, - str_time_p, - str_peer ?: "", - str_dev, - _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)), - nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)), - address->external ? " ext" : ""); - g_free(str_peer); - return buf; -} - -static NM_UTILS_FLAGS2STR_DEFINE(_rtm_flags_to_string, - unsigned, - NM_UTILS_FLAGS2STR(RTNH_F_DEAD, "dead"), - NM_UTILS_FLAGS2STR(RTNH_F_PERVASIVE, "pervasive"), - NM_UTILS_FLAGS2STR(RTNH_F_ONLINK, "onlink"), - NM_UTILS_FLAGS2STR(8 /*RTNH_F_OFFLOAD*/, "offload"), - NM_UTILS_FLAGS2STR(16 /*RTNH_F_LINKDOWN*/, "linkdown"), - NM_UTILS_FLAGS2STR(32 /*RTNH_F_UNRESOLVED*/, "unresolved"), - - NM_UTILS_FLAGS2STR(RTM_F_NOTIFY, "notify"), - NM_UTILS_FLAGS2STR(RTM_F_CLONED, "cloned"), - NM_UTILS_FLAGS2STR(RTM_F_EQUALIZE, "equalize"), - NM_UTILS_FLAGS2STR(RTM_F_PREFIX, "prefix"), - NM_UTILS_FLAGS2STR(0x1000 /*RTM_F_LOOKUP_TABLE*/, "lookup-table"), - NM_UTILS_FLAGS2STR(0x2000 /*RTM_F_FIB_MATCH*/, "fib-match"), ); - -#define _RTM_FLAGS_TO_STRING_MAXLEN 200 - -static const char * -_rtm_flags_to_string_full(char *buf, gsize buf_size, unsigned rtm_flags) -{ - const char *buf0 = buf; - - nm_assert(buf_size >= _RTM_FLAGS_TO_STRING_MAXLEN); - - if (!rtm_flags) - return ""; - - nm_utils_strbuf_append_str(&buf, &buf_size, " rtm_flags "); - _rtm_flags_to_string(rtm_flags, buf, buf_size); - nm_assert(strlen(buf) < buf_size); - return buf0; -} - -/** - * nm_platform_ip4_route_to_string: - * @route: pointer to NMPlatformIP4Route route structure - * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. - * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. - * - * A method for converting a route struct into a string representation. - * - * Example output: "192.168.1.0/24 via 0.0.0.0 dev em1 metric 0 mss 0" - * - * Returns: a string representation of the route. - */ -const char * -nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsize len) -{ - char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN]; - char s_pref_src[INET_ADDRSTRLEN]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char str_table[30]; - char str_scope[30], s_source[50]; - char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32]; - char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; - char str_type[30]; - char str_metric[30]; - - if (!nm_utils_to_string_buffer_init_null(route, &buf, &len)) - return buf; - - inet_ntop(AF_INET, &route->network, s_network, sizeof(s_network)); - inet_ntop(AF_INET, &route->gateway, s_gateway, sizeof(s_gateway)); - - _to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev)); - - g_snprintf( - buf, - len, - "type %s " /* type */ - "%s" /* table */ - "%s/%d" - " via %s" - "%s" - " metric %s" - " mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */ - "%s" /* rtm_flags */ - "%s%s" /* scope */ - "%s%s" /* pref-src */ - "%s" /* tos */ - "%s" /* window */ - "%s" /* cwnd */ - "%s" /* initcwnd */ - "%s" /* initrwnd */ - "%s" /* mtu */ - "", - nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced), - str_type, - sizeof(str_type)), - route->table_any - ? "table ?? " - : (route->table_coerced - ? nm_sprintf_buf(str_table, - "table %u ", - nm_platform_route_table_uncoerce(route->table_coerced, FALSE)) - : ""), - s_network, - route->plen, - s_gateway, - str_dev, - route->metric_any - ? (route->metric ? nm_sprintf_buf(str_metric, "??+%u", route->metric) : "??") - : nm_sprintf_buf(str_metric, "%u", route->metric), - route->mss, - nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)), - _rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags), - route->scope_inv ? " scope " : "", - route->scope_inv - ? (nm_platform_route_scope2str(nm_platform_route_scope_inv(route->scope_inv), - str_scope, - sizeof(str_scope))) - : "", - route->pref_src ? " pref-src " : "", - route->pref_src ? inet_ntop(AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "", - route->tos ? nm_sprintf_buf(str_tos, " tos 0x%x", (unsigned) route->tos) : "", - route->window || route->lock_window ? nm_sprintf_buf(str_window, - " window %s%" G_GUINT32_FORMAT, - route->lock_window ? "lock " : "", - route->window) - : "", - route->cwnd || route->lock_cwnd ? nm_sprintf_buf(str_cwnd, - " cwnd %s%" G_GUINT32_FORMAT, - route->lock_cwnd ? "lock " : "", - route->cwnd) - : "", - route->initcwnd || route->lock_initcwnd - ? nm_sprintf_buf(str_initcwnd, - " initcwnd %s%" G_GUINT32_FORMAT, - route->lock_initcwnd ? "lock " : "", - route->initcwnd) - : "", - route->initrwnd || route->lock_initrwnd - ? nm_sprintf_buf(str_initrwnd, - " initrwnd %s%" G_GUINT32_FORMAT, - route->lock_initrwnd ? "lock " : "", - route->initrwnd) - : "", - route->mtu || route->lock_mtu ? nm_sprintf_buf(str_mtu, - " mtu %s%" G_GUINT32_FORMAT, - route->lock_mtu ? "lock " : "", - route->mtu) - : ""); - return buf; -} - -/** - * nm_platform_ip6_route_to_string: - * @route: pointer to NMPlatformIP6Route route structure - * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. - * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. - * - * A method for converting a route struct into a string representation. - * - * Example output: "ff02::fb/128 via :: dev em1 metric 0" - * - * Returns: a string representation of the route. - */ -const char * -nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsize len) -{ - char s_network[INET6_ADDRSTRLEN]; - char s_gateway[INET6_ADDRSTRLEN]; - char s_pref_src[INET6_ADDRSTRLEN]; - char s_src_all[INET6_ADDRSTRLEN + 40]; - char s_src[INET6_ADDRSTRLEN]; - char str_type[30]; - char str_table[30]; - char str_pref[40]; - char str_pref2[30]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char s_source[50]; - char str_window[32]; - char str_cwnd[32]; - char str_initcwnd[32]; - char str_initrwnd[32]; - char str_mtu[32]; - char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; - char str_metric[30]; - - if (!nm_utils_to_string_buffer_init_null(route, &buf, &len)) - return buf; - - inet_ntop(AF_INET6, &route->network, s_network, sizeof(s_network)); - inet_ntop(AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway)); - - if (IN6_IS_ADDR_UNSPECIFIED(&route->pref_src)) - s_pref_src[0] = 0; - else - inet_ntop(AF_INET6, &route->pref_src, s_pref_src, sizeof(s_pref_src)); - - _to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev)); - - g_snprintf( - buf, - len, - "type %s " /* type */ - "%s" /* table */ - "%s/%d" - " via %s" - "%s" - " metric %s" - " mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */ - "%s" /* source */ - "%s" /* rtm_flags */ - "%s%s" /* pref-src */ - "%s" /* window */ - "%s" /* cwnd */ - "%s" /* initcwnd */ - "%s" /* initrwnd */ - "%s" /* mtu */ - "%s" /* pref */ - "", - nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced), - str_type, - sizeof(str_type)), - route->table_any - ? "table ?? " - : (route->table_coerced - ? nm_sprintf_buf(str_table, - "table %u ", - nm_platform_route_table_uncoerce(route->table_coerced, FALSE)) - : ""), - s_network, - route->plen, - s_gateway, - str_dev, - route->metric_any - ? (route->metric ? nm_sprintf_buf(str_metric, "??+%u", route->metric) : "??") - : nm_sprintf_buf(str_metric, "%u", route->metric), - route->mss, - nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)), - route->src_plen || !IN6_IS_ADDR_UNSPECIFIED(&route->src) - ? nm_sprintf_buf(s_src_all, - " src %s/%u", - _nm_utils_inet6_ntop(&route->src, s_src), - (unsigned) route->src_plen) - : "", - _rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags), - s_pref_src[0] ? " pref-src " : "", - s_pref_src[0] ? s_pref_src : "", - route->window || route->lock_window ? nm_sprintf_buf(str_window, - " window %s%" G_GUINT32_FORMAT, - route->lock_window ? "lock " : "", - route->window) - : "", - route->cwnd || route->lock_cwnd ? nm_sprintf_buf(str_cwnd, - " cwnd %s%" G_GUINT32_FORMAT, - route->lock_cwnd ? "lock " : "", - route->cwnd) - : "", - route->initcwnd || route->lock_initcwnd - ? nm_sprintf_buf(str_initcwnd, - " initcwnd %s%" G_GUINT32_FORMAT, - route->lock_initcwnd ? "lock " : "", - route->initcwnd) - : "", - route->initrwnd || route->lock_initrwnd - ? nm_sprintf_buf(str_initrwnd, - " initrwnd %s%" G_GUINT32_FORMAT, - route->lock_initrwnd ? "lock " : "", - route->initrwnd) - : "", - route->mtu || route->lock_mtu ? nm_sprintf_buf(str_mtu, - " mtu %s%" G_GUINT32_FORMAT, - route->lock_mtu ? "lock " : "", - route->mtu) - : "", - route->rt_pref ? nm_sprintf_buf( - str_pref, - " pref %s", - nm_icmpv6_router_pref_to_string(route->rt_pref, str_pref2, sizeof(str_pref2))) - : ""); - - return buf; -} - -static void -_routing_rule_addr_to_string(char ** buf, - gsize * len, - int addr_family, - const NMIPAddr *addr, - guint8 plen, - gboolean is_src) -{ - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - gboolean is_zero; - gsize addr_size; - - nm_assert_addr_family(addr_family); - nm_assert(addr); - - addr_size = nm_utils_addr_family_to_size(addr_family); - - is_zero = nm_utils_memeqzero(addr, addr_size); - - if (plen == 0 && is_zero) { - if (is_src) - nm_utils_strbuf_append_str(buf, len, " from all"); - else - nm_utils_strbuf_append_str(buf, len, ""); - return; - } - - nm_utils_strbuf_append_str(buf, len, is_src ? " from " : " to "); - - nm_utils_strbuf_append_str(buf, len, nm_utils_inet_ntop(addr_family, addr, s_addr)); - - if (plen != (addr_size * 8)) - nm_utils_strbuf_append(buf, len, "/%u", plen); -} - -static void -_routing_rule_port_range_to_string(char ** buf, - gsize * len, - const NMFibRulePortRange *port_range, - const char * name) -{ - if (port_range->start == 0 && port_range->end == 0) - nm_utils_strbuf_append_str(buf, len, ""); - else { - nm_utils_strbuf_append(buf, len, " %s %u", name, port_range->start); - if (port_range->start != port_range->end) - nm_utils_strbuf_append(buf, len, "-%u", port_range->end); - } -} - -const char * -nm_platform_routing_rule_to_string(const NMPlatformRoutingRule *routing_rule, char *buf, gsize len) -{ - const char *buf0; - guint32 rr_flags; - - if (!nm_utils_to_string_buffer_init_null(routing_rule, &buf, &len)) - return buf; - - if (!NM_IN_SET(routing_rule->addr_family, AF_INET, AF_INET6)) { - /* invalid addr-family. The other fields are undefined. */ - if (routing_rule->addr_family == AF_UNSPEC) - g_snprintf(buf, len, "[routing-rule]"); - else - g_snprintf(buf, len, "[routing-rule family:%u]", routing_rule->addr_family); - return buf; - } - - buf0 = buf; - - rr_flags = routing_rule->flags; - - rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_INVERT); - nm_utils_strbuf_append(&buf, - &len, - "[%c] " /* addr-family */ - "%u:" /* priority */ - "%s", /* not/FIB_RULE_INVERT */ - nm_utils_addr_family_to_char(routing_rule->addr_family), - routing_rule->priority, - (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_INVERT) ? " not" : "")); - - _routing_rule_addr_to_string(&buf, - &len, - routing_rule->addr_family, - &routing_rule->src, - routing_rule->src_len, - TRUE); - - _routing_rule_addr_to_string(&buf, - &len, - routing_rule->addr_family, - &routing_rule->dst, - routing_rule->dst_len, - FALSE); - - if (routing_rule->tos) - nm_utils_strbuf_append(&buf, &len, " tos 0x%02x", routing_rule->tos); - - if (routing_rule->fwmark != 0 || routing_rule->fwmask != 0) { - nm_utils_strbuf_append(&buf, &len, " fwmark %#x", (unsigned) routing_rule->fwmark); - if (routing_rule->fwmark != 0xFFFFFFFFu) - nm_utils_strbuf_append(&buf, &len, "/%#x", (unsigned) routing_rule->fwmask); - } - - if (routing_rule->iifname[0]) { - nm_utils_strbuf_append(&buf, &len, " iif %s", routing_rule->iifname); - rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_IIF_DETACHED); - if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_IIF_DETACHED)) - nm_utils_strbuf_append_str(&buf, &len, " [detached]"); - } - - if (routing_rule->oifname[0]) { - nm_utils_strbuf_append(&buf, &len, " oif %s", routing_rule->oifname); - rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_OIF_DETACHED); - if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_OIF_DETACHED)) - nm_utils_strbuf_append_str(&buf, &len, " [detached]"); - } - - if (routing_rule->l3mdev != 0) { - if (routing_rule->l3mdev == 1) - nm_utils_strbuf_append_str(&buf, &len, " lookup [l3mdev-table]"); - else { - nm_utils_strbuf_append(&buf, - &len, - " lookup [l3mdev-table/%u]", - (unsigned) routing_rule->l3mdev); - } - } - - if (routing_rule->uid_range_has || routing_rule->uid_range.start - || routing_rule->uid_range.end) { - nm_utils_strbuf_append(&buf, - &len, - " uidrange %u-%u%s", - routing_rule->uid_range.start, - routing_rule->uid_range.end, - routing_rule->uid_range_has ? "" : "(?)"); - } - - if (routing_rule->ip_proto != 0) { - /* we don't call getprotobynumber(), just print the numeric value. - * This differs from what ip-rule prints. */ - nm_utils_strbuf_append(&buf, &len, " ipproto %u", routing_rule->ip_proto); - } - - _routing_rule_port_range_to_string(&buf, &len, &routing_rule->sport_range, "sport"); - - _routing_rule_port_range_to_string(&buf, &len, &routing_rule->dport_range, "dport"); - - if (routing_rule->tun_id != 0) { - nm_utils_strbuf_append(&buf, &len, " tun_id %" G_GUINT64_FORMAT, routing_rule->tun_id); - } - - if (routing_rule->table != 0) { - nm_utils_strbuf_append(&buf, &len, " lookup %u", routing_rule->table); - } - - if (routing_rule->suppress_prefixlen_inverse != 0) { - nm_utils_strbuf_append(&buf, - &len, - " suppress_prefixlen %d", - (int) (~routing_rule->suppress_prefixlen_inverse)); - } - - if (routing_rule->suppress_ifgroup_inverse != 0) { - nm_utils_strbuf_append(&buf, - &len, - " suppress_ifgroup %d", - (int) (~routing_rule->suppress_ifgroup_inverse)); - } - - if (routing_rule->flow) { - /* FRA_FLOW is only for IPv4, but we want to print the value for all address-families, - * to see when it is set. In practice, this should not be set except for IPv4. - * - * We don't follow the style how ip-rule prints flow/realms. It's confusing. Just - * print the value hex. */ - nm_utils_strbuf_append(&buf, &len, " realms 0x%08x", routing_rule->flow); - } - - if (routing_rule->action == RTN_NAT) { - G_STATIC_ASSERT_EXPR(RTN_NAT == 10); - - /* NAT is deprecated for many years. We don't support RTA_GATEWAY/FRA_UNUSED2 - * for the gateway, and so do recent kernels ignore that parameter. */ - nm_utils_strbuf_append_str(&buf, &len, " masquerade"); - } else if (routing_rule->action == FR_ACT_GOTO) { - if (routing_rule->goto_target != 0) - nm_utils_strbuf_append(&buf, &len, " goto %u", routing_rule->goto_target); - else - nm_utils_strbuf_append_str(&buf, &len, " goto none"); - rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_UNRESOLVED); - if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_UNRESOLVED)) - nm_utils_strbuf_append_str(&buf, &len, " unresolved"); - } else if (routing_rule->action != FR_ACT_TO_TBL) { - const char *ss; - char ss_buf[60]; - -#define _V(v1, v2) ((sizeof(char[(((int) (v1)) == ((int) (v2))) ? 1 : -1]) * 0) + (v1)) - switch (routing_rule->action) { - case _V(FR_ACT_UNSPEC, RTN_UNSPEC): - ss = "none"; - break; - case _V(FR_ACT_TO_TBL, RTN_UNICAST): - ss = "unicast"; - break; - case _V(FR_ACT_GOTO, RTN_LOCAL): - ss = "local"; - break; - case _V(FR_ACT_NOP, RTN_BROADCAST): - ss = "nop"; - break; - case _V(FR_ACT_RES3, RTN_ANYCAST): - ss = "anycast"; - break; - case _V(FR_ACT_RES4, RTN_MULTICAST): - ss = "multicast"; - break; - case _V(FR_ACT_BLACKHOLE, RTN_BLACKHOLE): - ss = "blackhole"; - break; - case _V(FR_ACT_UNREACHABLE, RTN_UNREACHABLE): - ss = "unreachable"; - break; - case _V(FR_ACT_PROHIBIT, RTN_PROHIBIT): - ss = "prohibit"; - break; - case RTN_THROW: - ss = "throw"; - break; - case RTN_NAT: - ss = "nat"; - break; - case RTN_XRESOLVE: - ss = "xresolve"; - break; - default: - ss = nm_sprintf_buf(ss_buf, "action-%u", routing_rule->action); - break; - } -#undef _V - nm_utils_strbuf_append(&buf, &len, " %s", ss); - } - - if (routing_rule->protocol != RTPROT_UNSPEC) - nm_utils_strbuf_append(&buf, &len, " protocol %u", routing_rule->protocol); - - if (routing_rule->goto_target != 0 && routing_rule->action != FR_ACT_GOTO) { - /* a trailing target is set for an unexpected action. Print it. */ - nm_utils_strbuf_append(&buf, &len, " goto-target %u", routing_rule->goto_target); - } - - if (rr_flags != 0) { - /* we have some flags we didn't print about yet. */ - nm_utils_strbuf_append(&buf, &len, " remaining-flags %x", rr_flags); - } - - return buf0; -} - -const char * -nm_platform_qdisc_to_string(const NMPlatformQdisc *qdisc, char *buf, gsize len) -{ - char str_dev[TO_STRING_DEV_BUF_SIZE]; - const char *buf0; - - if (!nm_utils_to_string_buffer_init_null(qdisc, &buf, &len)) - return buf; - - buf0 = buf; - - nm_utils_strbuf_append(&buf, - &len, - "%s%s family %u handle %x parent %x info %x", - qdisc->kind, - _to_string_dev(NULL, qdisc->ifindex, str_dev, sizeof(str_dev)), - qdisc->addr_family, - qdisc->handle, - qdisc->parent, - qdisc->info); - - if (nm_streq0(qdisc->kind, "fq_codel")) { - if (qdisc->fq_codel.limit) - nm_utils_strbuf_append(&buf, &len, " limit %u", qdisc->fq_codel.limit); - if (qdisc->fq_codel.flows) - nm_utils_strbuf_append(&buf, &len, " flows %u", qdisc->fq_codel.flows); - if (qdisc->fq_codel.target) - nm_utils_strbuf_append(&buf, &len, " target %u", qdisc->fq_codel.target); - if (qdisc->fq_codel.interval) - nm_utils_strbuf_append(&buf, &len, " interval %u", qdisc->fq_codel.interval); - if (qdisc->fq_codel.quantum) - nm_utils_strbuf_append(&buf, &len, " quantum %u", qdisc->fq_codel.quantum); - if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) - nm_utils_strbuf_append(&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); - if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) - nm_utils_strbuf_append(&buf, &len, " memory_limit %u", qdisc->fq_codel.memory_limit); - if (qdisc->fq_codel.ecn) - nm_utils_strbuf_append(&buf, &len, " ecn"); - } else if (nm_streq0(qdisc->kind, "sfq")) { - if (qdisc->sfq.quantum) - nm_utils_strbuf_append(&buf, &len, " quantum %u", qdisc->sfq.quantum); - if (qdisc->sfq.perturb_period) - nm_utils_strbuf_append(&buf, &len, " perturb %d", qdisc->sfq.perturb_period); - if (qdisc->sfq.limit) - nm_utils_strbuf_append(&buf, &len, " limit %u", (guint) qdisc->sfq.limit); - if (qdisc->sfq.divisor) - nm_utils_strbuf_append(&buf, &len, " divisor %u", qdisc->sfq.divisor); - if (qdisc->sfq.flows) - nm_utils_strbuf_append(&buf, &len, " flows %u", qdisc->sfq.flows); - if (qdisc->sfq.depth) - nm_utils_strbuf_append(&buf, &len, " depth %u", qdisc->sfq.depth); - } else if (nm_streq0(qdisc->kind, "tbf")) { - nm_utils_strbuf_append(&buf, &len, " rate %" G_GUINT64_FORMAT, qdisc->tbf.rate); - nm_utils_strbuf_append(&buf, &len, " burst %u", qdisc->tbf.burst); - if (qdisc->tbf.limit) - nm_utils_strbuf_append(&buf, &len, " limit %u", qdisc->tbf.limit); - if (qdisc->tbf.latency) - nm_utils_strbuf_append(&buf, &len, " latency %uns", qdisc->tbf.latency); - } - - return buf0; -} - -void -nm_platform_qdisc_hash_update(const NMPlatformQdisc *obj, NMHashState *h) -{ - nm_hash_update_str0(h, obj->kind); - nm_hash_update_vals(h, obj->ifindex, obj->addr_family, obj->handle, obj->parent, obj->info); - if (nm_streq0(obj->kind, "fq_codel")) { - nm_hash_update_vals(h, - obj->fq_codel.limit, - obj->fq_codel.flows, - obj->fq_codel.target, - obj->fq_codel.interval, - obj->fq_codel.quantum, - obj->fq_codel.ce_threshold, - obj->fq_codel.memory_limit, - NM_HASH_COMBINE_BOOLS(guint8, obj->fq_codel.ecn)); - } else if (nm_streq0(obj->kind, "sfq")) { - nm_hash_update_vals(h, - obj->sfq.quantum, - obj->sfq.perturb_period, - obj->sfq.limit, - obj->sfq.divisor, - obj->sfq.flows, - obj->sfq.depth); - } else if (nm_streq0(obj->kind, "tbf")) { - nm_hash_update_vals(h, obj->tbf.rate, obj->tbf.burst, obj->tbf.limit, obj->tbf.latency); - } -} - -int -nm_platform_qdisc_cmp_full(const NMPlatformQdisc *a, - const NMPlatformQdisc *b, - gboolean compare_handle) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD(a, b, parent); - NM_CMP_FIELD_STR_INTERNED(a, b, kind); - NM_CMP_FIELD(a, b, addr_family); - if (compare_handle) - NM_CMP_FIELD(a, b, handle); - NM_CMP_FIELD(a, b, info); - - if (nm_streq0(a->kind, "fq_codel")) { - NM_CMP_FIELD(a, b, fq_codel.limit); - NM_CMP_FIELD(a, b, fq_codel.flows); - NM_CMP_FIELD(a, b, fq_codel.target); - NM_CMP_FIELD(a, b, fq_codel.interval); - NM_CMP_FIELD(a, b, fq_codel.quantum); - NM_CMP_FIELD(a, b, fq_codel.ce_threshold); - NM_CMP_FIELD(a, b, fq_codel.memory_limit); - NM_CMP_FIELD_UNSAFE(a, b, fq_codel.ecn); - } else if (nm_streq0(a->kind, "sfq")) { - NM_CMP_FIELD(a, b, sfq.quantum); - NM_CMP_FIELD(a, b, sfq.perturb_period); - NM_CMP_FIELD(a, b, sfq.limit); - NM_CMP_FIELD(a, b, sfq.flows); - NM_CMP_FIELD(a, b, sfq.divisor); - NM_CMP_FIELD(a, b, sfq.depth); - } else if (nm_streq0(a->kind, "tbf")) { - NM_CMP_FIELD(a, b, tbf.rate); - NM_CMP_FIELD(a, b, tbf.burst); - NM_CMP_FIELD(a, b, tbf.limit); - NM_CMP_FIELD(a, b, tbf.latency); - } - - return 0; -} - -int -nm_platform_qdisc_cmp(const NMPlatformQdisc *a, const NMPlatformQdisc *b) -{ - return nm_platform_qdisc_cmp_full(a, b, TRUE); -} - -const char * -nm_platform_tfilter_to_string(const NMPlatformTfilter *tfilter, char *buf, gsize len) -{ - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char act_buf[300]; - char *p; - gsize l; - - if (!nm_utils_to_string_buffer_init_null(tfilter, &buf, &len)) - return buf; - - if (tfilter->action.kind) { - p = act_buf; - l = sizeof(act_buf); - - nm_utils_strbuf_append(&p, &l, " \"%s\"", tfilter->action.kind); - if (nm_streq(tfilter->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - gs_free char *t = NULL; - - nm_utils_strbuf_append( - &p, - &l, - " (\"%s\")", - nm_utils_str_utf8safe_escape(tfilter->action.kind, - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL - | NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII, - &t)); - } else if (nm_streq(tfilter->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - nm_utils_strbuf_append(&p, - &l, - "%s%s%s%s dev %d", - tfilter->action.mirred.ingress ? " ingress" : "", - tfilter->action.mirred.egress ? " egress" : "", - tfilter->action.mirred.mirror ? " mirror" : "", - tfilter->action.mirred.redirect ? " redirect" : "", - tfilter->action.mirred.ifindex); - } - } else - act_buf[0] = '\0'; - - g_snprintf(buf, - len, - "%s%s family %u handle %x parent %x info %x%s", - tfilter->kind, - _to_string_dev(NULL, tfilter->ifindex, str_dev, sizeof(str_dev)), - tfilter->addr_family, - tfilter->handle, - tfilter->parent, - tfilter->info, - act_buf); - - return buf; -} - -void -nm_platform_tfilter_hash_update(const NMPlatformTfilter *obj, NMHashState *h) -{ - nm_hash_update_str0(h, obj->kind); - nm_hash_update_vals(h, obj->ifindex, obj->addr_family, obj->handle, obj->parent, obj->info); - if (obj->action.kind) { - nm_hash_update_str(h, obj->action.kind); - if (nm_streq(obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - nm_hash_update_strarr(h, obj->action.simple.sdata); - } else if (nm_streq(obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - nm_hash_update_vals(h, - obj->action.mirred.ifindex, - NM_HASH_COMBINE_BOOLS(guint8, - obj->action.mirred.ingress, - obj->action.mirred.egress, - obj->action.mirred.mirror, - obj->action.mirred.redirect)); - } - } -} - -int -nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD(a, b, parent); - NM_CMP_FIELD_STR_INTERNED(a, b, kind); - NM_CMP_FIELD(a, b, addr_family); - NM_CMP_FIELD(a, b, handle); - NM_CMP_FIELD(a, b, info); - - NM_CMP_FIELD_STR_INTERNED(a, b, action.kind); - if (a->action.kind) { - if (nm_streq(a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - NM_CMP_FIELD_STR(a, b, action.simple.sdata); - } else if (nm_streq(a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - NM_CMP_FIELD(a, b, action.mirred.ifindex); - NM_CMP_FIELD_UNSAFE(a, b, action.mirred.ingress); - NM_CMP_FIELD_UNSAFE(a, b, action.mirred.egress); - NM_CMP_FIELD_UNSAFE(a, b, action.mirred.mirror); - NM_CMP_FIELD_UNSAFE(a, b, action.mirred.redirect); - } - } - - return 0; -} - -const char * -nm_platform_vf_to_string(const NMPlatformVF *vf, char *buf, gsize len) -{ - char str_mac[128], mac[128]; - char str_spoof_check[64]; - char str_trust[64]; - char str_min_tx_rate[64]; - char str_max_tx_rate[64]; - nm_auto_free_gstring GString *gstr_vlans = NULL; - guint i; - - if (!nm_utils_to_string_buffer_init_null(vf, &buf, &len)) - return buf; - - if (vf->mac.len) { - _nm_utils_hwaddr_ntoa(vf->mac.data, vf->mac.len, TRUE, mac, sizeof(mac)); - nm_sprintf_buf(str_mac, " mac %s", mac); - } else - str_mac[0] = '\0'; - - if (vf->num_vlans) { - gstr_vlans = g_string_new(""); - for (i = 0; i < vf->num_vlans; i++) { - g_string_append_printf(gstr_vlans, " vlan %u", (unsigned) vf->vlans[i].id); - if (vf->vlans[i].qos) - g_string_append_printf(gstr_vlans, " qos %u", (unsigned) vf->vlans[i].qos); - if (vf->vlans[i].proto_ad) - g_string_append(gstr_vlans, " proto 802.1ad"); - } - } - - g_snprintf(buf, - len, - "%u" /* index */ - "%s" /* MAC */ - "%s" /* spoof check */ - "%s" /* trust */ - "%s" /* min tx rate */ - "%s" /* max tx rate */ - "%s", /* VLANs */ - vf->index, - str_mac, - vf->spoofchk >= 0 ? nm_sprintf_buf(str_spoof_check, " spoofchk %d", vf->spoofchk) - : "", - vf->trust >= 0 ? nm_sprintf_buf(str_trust, " trust %d", vf->trust) : "", - vf->min_tx_rate - ? nm_sprintf_buf(str_min_tx_rate, " min_tx_rate %u", (unsigned) vf->min_tx_rate) - : "", - vf->max_tx_rate - ? nm_sprintf_buf(str_max_tx_rate, " max_tx_rate %u", (unsigned) vf->max_tx_rate) - : "", - gstr_vlans ? gstr_vlans->str : ""); - - return buf; -} - -const char * -nm_platform_bridge_vlan_to_string(const NMPlatformBridgeVlan *vlan, char *buf, gsize len) -{ - char str_vid_end[64]; - - if (!nm_utils_to_string_buffer_init_null(vlan, &buf, &len)) - return buf; - - g_snprintf(buf, - len, - "%u" - "%s" - "%s" - "%s", - vlan->vid_start, - vlan->vid_start != vlan->vid_end ? nm_sprintf_buf(str_vid_end, "-%u", vlan->vid_end) - : "", - vlan->pvid ? " PVID" : "", - vlan->untagged ? " untagged" : ""); - - return buf; -} - -void -nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->ifindex, - obj->master, - obj->parent, - obj->n_ifi_flags, - obj->mtu, - obj->type, - obj->arptype, - obj->inet6_addr_gen_mode_inv, - obj->inet6_token, - obj->rx_packets, - obj->rx_bytes, - obj->tx_packets, - obj->tx_bytes, - NM_HASH_COMBINE_BOOLS(guint8, obj->connected, obj->initialized)); - nm_hash_update_strarr(h, obj->name); - nm_hash_update_str0(h, obj->kind); - nm_hash_update_str0(h, obj->driver); - /* nm_hash_update_mem() also hashes the length obj->addr.len */ - nm_hash_update_mem(h, - obj->l_address.data, - NM_MIN(obj->l_address.len, sizeof(obj->l_address.data))); - nm_hash_update_mem(h, - obj->l_broadcast.data, - NM_MIN(obj->l_broadcast.len, sizeof(obj->l_broadcast.data))); -} - -int -nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD(a, b, type); - NM_CMP_FIELD_STR(a, b, name); - NM_CMP_FIELD(a, b, master); - NM_CMP_FIELD(a, b, parent); - NM_CMP_FIELD(a, b, n_ifi_flags); - NM_CMP_FIELD_UNSAFE(a, b, connected); - NM_CMP_FIELD(a, b, mtu); - NM_CMP_FIELD_BOOL(a, b, initialized); - NM_CMP_FIELD(a, b, arptype); - NM_CMP_FIELD(a, b, l_address.len); - NM_CMP_FIELD(a, b, l_broadcast.len); - NM_CMP_FIELD(a, b, inet6_addr_gen_mode_inv); - NM_CMP_FIELD_STR_INTERNED(a, b, kind); - NM_CMP_FIELD_STR_INTERNED(a, b, driver); - if (a->l_address.len) - NM_CMP_FIELD_MEMCMP_LEN(a, b, l_address.data, a->l_address.len); - if (a->l_broadcast.len) - NM_CMP_FIELD_MEMCMP_LEN(a, b, l_broadcast.data, a->l_broadcast.len); - NM_CMP_FIELD_MEMCMP(a, b, inet6_token); - NM_CMP_FIELD(a, b, rx_packets); - NM_CMP_FIELD(a, b, rx_bytes); - NM_CMP_FIELD(a, b, tx_packets); - NM_CMP_FIELD(a, b, tx_bytes); - return 0; -} - -void -nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->forward_delay, - obj->hello_time, - obj->max_age, - obj->ageing_time, - obj->priority, - obj->vlan_protocol, - obj->group_fwd_mask, - obj->group_addr, - obj->mcast_hash_max, - obj->mcast_last_member_count, - obj->mcast_startup_query_count, - obj->mcast_last_member_interval, - obj->mcast_membership_interval, - obj->mcast_querier_interval, - obj->mcast_query_interval, - obj->mcast_router, - obj->mcast_query_response_interval, - obj->mcast_startup_query_interval, - NM_HASH_COMBINE_BOOLS(guint8, - obj->stp_state, - obj->mcast_querier, - obj->mcast_query_use_ifaddr, - obj->mcast_snooping, - obj->vlan_stats_enabled)); -} - -int -nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, forward_delay); - NM_CMP_FIELD(a, b, hello_time); - NM_CMP_FIELD(a, b, max_age); - NM_CMP_FIELD(a, b, ageing_time); - NM_CMP_FIELD_BOOL(a, b, stp_state); - NM_CMP_FIELD(a, b, priority); - NM_CMP_FIELD(a, b, vlan_protocol); - NM_CMP_FIELD_BOOL(a, b, vlan_stats_enabled); - NM_CMP_FIELD(a, b, group_fwd_mask); - NM_CMP_FIELD_MEMCMP(a, b, group_addr); - NM_CMP_FIELD_BOOL(a, b, mcast_snooping); - NM_CMP_FIELD(a, b, mcast_router); - NM_CMP_FIELD_BOOL(a, b, mcast_query_use_ifaddr); - NM_CMP_FIELD_BOOL(a, b, mcast_querier); - NM_CMP_FIELD(a, b, mcast_hash_max); - NM_CMP_FIELD(a, b, mcast_last_member_count); - NM_CMP_FIELD(a, b, mcast_startup_query_count); - NM_CMP_FIELD(a, b, mcast_last_member_interval); - NM_CMP_FIELD(a, b, mcast_membership_interval); - NM_CMP_FIELD(a, b, mcast_querier_interval); - NM_CMP_FIELD(a, b, mcast_query_interval); - NM_CMP_FIELD(a, b, mcast_query_response_interval); - NM_CMP_FIELD(a, b, mcast_startup_query_interval); - - return 0; -} - -void -nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->input_flags, - obj->output_flags, - obj->input_key, - obj->output_key, - obj->ttl, - obj->tos, - (bool) obj->path_mtu_discovery, - (bool) obj->is_tap); -} - -int -nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, parent_ifindex); - NM_CMP_FIELD(a, b, input_flags); - NM_CMP_FIELD(a, b, output_flags); - NM_CMP_FIELD(a, b, input_key); - NM_CMP_FIELD(a, b, output_key); - NM_CMP_FIELD(a, b, local); - NM_CMP_FIELD(a, b, remote); - NM_CMP_FIELD(a, b, ttl); - NM_CMP_FIELD(a, b, tos); - NM_CMP_FIELD_BOOL(a, b, path_mtu_discovery); - NM_CMP_FIELD_BOOL(a, b, is_tap); - return 0; -} - -void -nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h) -{ - nm_hash_update_val(h, obj->p_key); - nm_hash_update_str0(h, obj->mode); -} - -int -nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, p_key); - NM_CMP_FIELD_STR_INTERNED(a, b, mode); - return 0; -} - -void -nm_platform_lnk_ip6tnl_hash_update(const NMPlatformLnkIp6Tnl *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->ttl, - obj->tclass, - obj->encap_limit, - obj->proto, - obj->flow_label, - obj->flags, - obj->input_flags, - obj->output_flags, - obj->input_key, - obj->output_key, - (bool) obj->is_gre, - (bool) obj->is_tap); -} - -int -nm_platform_lnk_ip6tnl_cmp(const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, parent_ifindex); - NM_CMP_FIELD_MEMCMP(a, b, local); - NM_CMP_FIELD_MEMCMP(a, b, remote); - NM_CMP_FIELD(a, b, ttl); - NM_CMP_FIELD(a, b, tclass); - NM_CMP_FIELD(a, b, encap_limit); - NM_CMP_FIELD(a, b, flow_label); - NM_CMP_FIELD(a, b, proto); - NM_CMP_FIELD(a, b, flags); - NM_CMP_FIELD(a, b, input_flags); - NM_CMP_FIELD(a, b, output_flags); - NM_CMP_FIELD(a, b, input_key); - NM_CMP_FIELD(a, b, output_key); - NM_CMP_FIELD_BOOL(a, b, is_gre); - NM_CMP_FIELD_BOOL(a, b, is_tap); - return 0; -} - -void -nm_platform_lnk_ipip_hash_update(const NMPlatformLnkIpIp *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->ttl, - obj->tos, - (bool) obj->path_mtu_discovery); -} - -int -nm_platform_lnk_ipip_cmp(const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, parent_ifindex); - NM_CMP_FIELD(a, b, local); - NM_CMP_FIELD(a, b, remote); - NM_CMP_FIELD(a, b, ttl); - NM_CMP_FIELD(a, b, tos); - NM_CMP_FIELD_BOOL(a, b, path_mtu_discovery); - return 0; -} - -void -nm_platform_lnk_macsec_hash_update(const NMPlatformLnkMacsec *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->parent_ifindex, - obj->sci, - obj->cipher_suite, - obj->window, - obj->icv_length, - obj->encoding_sa, - obj->validation, - NM_HASH_COMBINE_BOOLS(guint8, - obj->encrypt, - obj->protect, - obj->include_sci, - obj->es, - obj->scb, - obj->replay_protect)); -} - -int -nm_platform_lnk_macsec_cmp(const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, parent_ifindex); - NM_CMP_FIELD(a, b, sci); - NM_CMP_FIELD(a, b, icv_length); - NM_CMP_FIELD(a, b, cipher_suite); - NM_CMP_FIELD(a, b, window); - NM_CMP_FIELD(a, b, encoding_sa); - NM_CMP_FIELD(a, b, validation); - NM_CMP_FIELD_UNSAFE(a, b, encrypt); - NM_CMP_FIELD_UNSAFE(a, b, protect); - NM_CMP_FIELD_UNSAFE(a, b, include_sci); - NM_CMP_FIELD_UNSAFE(a, b, es); - NM_CMP_FIELD_UNSAFE(a, b, scb); - NM_CMP_FIELD_UNSAFE(a, b, replay_protect); - return 0; -} - -void -nm_platform_lnk_macvlan_hash_update(const NMPlatformLnkMacvlan *obj, NMHashState *h) -{ - nm_hash_update_vals(h, obj->mode, NM_HASH_COMBINE_BOOLS(guint8, obj->no_promisc, obj->tap)); -} - -int -nm_platform_lnk_macvlan_cmp(const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, mode); - NM_CMP_FIELD_UNSAFE(a, b, no_promisc); - NM_CMP_FIELD_UNSAFE(a, b, tap); - return 0; -} - -void -nm_platform_lnk_sit_hash_update(const NMPlatformLnkSit *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->flags, - obj->ttl, - obj->tos, - obj->proto, - (bool) obj->path_mtu_discovery); -} - -int -nm_platform_lnk_sit_cmp(const NMPlatformLnkSit *a, const NMPlatformLnkSit *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, parent_ifindex); - NM_CMP_FIELD(a, b, local); - NM_CMP_FIELD(a, b, remote); - NM_CMP_FIELD(a, b, ttl); - NM_CMP_FIELD(a, b, tos); - NM_CMP_FIELD_BOOL(a, b, path_mtu_discovery); - NM_CMP_FIELD(a, b, flags); - NM_CMP_FIELD(a, b, proto); - return 0; -} - -void -nm_platform_lnk_tun_hash_update(const NMPlatformLnkTun *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->type, - obj->owner, - obj->group, - NM_HASH_COMBINE_BOOLS(guint8, - obj->owner_valid, - obj->group_valid, - obj->pi, - obj->vnet_hdr, - obj->multi_queue, - obj->persist)); -} - -int -nm_platform_lnk_tun_cmp(const NMPlatformLnkTun *a, const NMPlatformLnkTun *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, type); - NM_CMP_FIELD(a, b, owner); - NM_CMP_FIELD(a, b, group); - NM_CMP_FIELD_BOOL(a, b, owner_valid); - NM_CMP_FIELD_BOOL(a, b, group_valid); - NM_CMP_FIELD_BOOL(a, b, pi); - NM_CMP_FIELD_BOOL(a, b, vnet_hdr); - NM_CMP_FIELD_BOOL(a, b, multi_queue); - NM_CMP_FIELD_BOOL(a, b, persist); - return 0; -} - -void -nm_platform_lnk_vlan_hash_update(const NMPlatformLnkVlan *obj, NMHashState *h) -{ - nm_hash_update_vals(h, obj->id, obj->flags); -} - -int -nm_platform_lnk_vlan_cmp(const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, id); - NM_CMP_FIELD(a, b, flags); - return 0; -} - -void -nm_platform_lnk_vrf_hash_update(const NMPlatformLnkVrf *obj, NMHashState *h) -{ - nm_hash_update_vals(h, obj->table); -} - -int -nm_platform_lnk_vrf_cmp(const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, table); - return 0; -} - -void -nm_platform_lnk_vxlan_hash_update(const NMPlatformLnkVxlan *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->group6, - obj->local6, - obj->group, - obj->local, - obj->parent_ifindex, - obj->id, - obj->ageing, - obj->limit, - obj->dst_port, - obj->src_port_min, - obj->src_port_max, - obj->tos, - obj->ttl, - NM_HASH_COMBINE_BOOLS(guint8, - obj->learning, - obj->proxy, - obj->rsc, - obj->l2miss, - obj->l3miss)); -} - -int -nm_platform_lnk_vxlan_cmp(const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, parent_ifindex); - NM_CMP_FIELD(a, b, id); - NM_CMP_FIELD(a, b, group); - NM_CMP_FIELD(a, b, local); - NM_CMP_FIELD_MEMCMP(a, b, group6); - NM_CMP_FIELD_MEMCMP(a, b, local6); - NM_CMP_FIELD(a, b, tos); - NM_CMP_FIELD(a, b, ttl); - NM_CMP_FIELD_BOOL(a, b, learning); - NM_CMP_FIELD(a, b, ageing); - NM_CMP_FIELD(a, b, limit); - NM_CMP_FIELD(a, b, dst_port); - NM_CMP_FIELD(a, b, src_port_min); - NM_CMP_FIELD(a, b, src_port_max); - NM_CMP_FIELD_BOOL(a, b, proxy); - NM_CMP_FIELD_BOOL(a, b, rsc); - NM_CMP_FIELD_BOOL(a, b, l2miss); - NM_CMP_FIELD_BOOL(a, b, l3miss); - return 0; -} - -void -nm_platform_lnk_wireguard_hash_update(const NMPlatformLnkWireGuard *obj, NMHashState *h) -{ - nm_hash_update_vals(h, obj->listen_port, obj->fwmark); - nm_hash_update(h, obj->private_key, sizeof(obj->private_key)); - nm_hash_update(h, obj->public_key, sizeof(obj->public_key)); -} - -int -nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, listen_port); - NM_CMP_FIELD(a, b, fwmark); - NM_CMP_FIELD_MEMCMP(a, b, private_key); - NM_CMP_FIELD_MEMCMP(a, b, public_key); - return 0; -} - -static int -_address_pretty_sort_get_prio_4(in_addr_t addr) -{ - if (nm_utils_ip4_address_is_link_local(addr)) - return 0; - return 1; -} - -int -nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1, - const NMPlatformIP4Address *a2) -{ - in_addr_t n1; - in_addr_t n2; - - nm_assert(a1); - nm_assert(a2); - - /* Sort by address type. For example link local will - * be sorted *after* a global address. */ - NM_CMP_DIRECT(_address_pretty_sort_get_prio_4(a2->address), - _address_pretty_sort_get_prio_4(a1->address)); - - /* Sort the addresses based on their source. */ - NM_CMP_DIRECT(a2->addr_source, a1->addr_source); - - NM_CMP_DIRECT((a2->label[0] == '\0'), (a1->label[0] == '\0')); - - /* Finally, sort addresses lexically. We compare only the - * network part so that the order of addresses in the same - * subnet (and thus also the primary/secondary role) is - * preserved. - */ - n1 = a1->address & _nm_utils_ip4_prefix_to_netmask(a1->plen); - n2 = a2->address & _nm_utils_ip4_prefix_to_netmask(a2->plen); - NM_CMP_DIRECT_MEMCMP(&n1, &n2, sizeof(guint32)); - return 0; -} - -static int -_address_pretty_sort_get_prio_6(const struct in6_addr *addr) -{ - if (IN6_IS_ADDR_V4MAPPED(addr)) - return 0; - if (IN6_IS_ADDR_V4COMPAT(addr)) - return 1; - if (IN6_IS_ADDR_UNSPECIFIED(addr)) - return 2; - if (IN6_IS_ADDR_LOOPBACK(addr)) - return 3; - if (IN6_IS_ADDR_LINKLOCAL(addr)) - return 4; - if (IN6_IS_ADDR_SITELOCAL(addr)) - return 5; - return 6; -} - -int -nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1, - const NMPlatformIP6Address *a2, - gboolean prefer_temp) -{ - gboolean ipv6_privacy1; - gboolean ipv6_privacy2; - - nm_assert(a1); - nm_assert(a2); - - /* tentative addresses are always sorted back... */ - /* sort tentative addresses after non-tentative. */ - NM_CMP_DIRECT(NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_TENTATIVE), - NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_TENTATIVE)); - - /* Sort by address type. For example link local will - * be sorted *after* site local or global. */ - NM_CMP_DIRECT(_address_pretty_sort_get_prio_6(&a2->address), - _address_pretty_sort_get_prio_6(&a1->address)); - - ipv6_privacy1 = NM_FLAGS_ANY(a1->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY); - ipv6_privacy2 = NM_FLAGS_ANY(a2->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY); - if (ipv6_privacy1 || ipv6_privacy2) { - gboolean public1 = TRUE; - gboolean public2 = TRUE; - - if (ipv6_privacy1) { - if (a1->n_ifa_flags & IFA_F_TEMPORARY) - public1 = prefer_temp; - else - public1 = !prefer_temp; - } - if (ipv6_privacy2) { - if (a2->n_ifa_flags & IFA_F_TEMPORARY) - public2 = prefer_temp; - else - public2 = !prefer_temp; - } - - NM_CMP_DIRECT(public2, public1); - } - - /* Sort the addresses based on their source. */ - NM_CMP_DIRECT(a2->addr_source, a1->addr_source); - - /* sort permanent addresses before non-permanent. */ - NM_CMP_DIRECT(NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_PERMANENT), - NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_PERMANENT)); - - /* finally sort addresses lexically */ - NM_CMP_DIRECT_IN6ADDR(&a1->address, &a2->address); - NM_CMP_DIRECT_MEMCMP(a1, a2, sizeof(*a1)); - return 0; -} - -void -nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->ifindex, - obj->addr_source, - obj->use_ip4_broadcast_address ? obj->broadcast_address : ((in_addr_t) 0u), - obj->timestamp, - obj->lifetime, - obj->preferred, - obj->n_ifa_flags, - obj->plen, - obj->address, - obj->peer_address, - NM_HASH_COMBINE_BOOLS(guint8, - obj->external, - obj->use_ip4_broadcast_address, - obj->ip4acd_not_ready)); - nm_hash_update_strarr(h, obj->label); -} - -int -nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) -{ - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD(a, b, address); - NM_CMP_FIELD(a, b, plen); - NM_CMP_FIELD(a, b, peer_address); - NM_CMP_FIELD_UNSAFE(a, b, use_ip4_broadcast_address); - if (a->use_ip4_broadcast_address) - NM_CMP_FIELD(a, b, broadcast_address); - NM_CMP_FIELD(a, b, addr_source); - NM_CMP_FIELD(a, b, timestamp); - NM_CMP_FIELD(a, b, lifetime); - NM_CMP_FIELD(a, b, preferred); - NM_CMP_FIELD(a, b, n_ifa_flags); - NM_CMP_FIELD_STR(a, b, label); - NM_CMP_FIELD_UNSAFE(a, b, external); - NM_CMP_FIELD_UNSAFE(a, b, ip4acd_not_ready); - return 0; -} - -void -nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h) -{ - nm_hash_update_vals(h, - obj->ifindex, - obj->addr_source, - obj->timestamp, - obj->lifetime, - obj->preferred, - obj->n_ifa_flags, - obj->plen, - obj->address, - obj->peer_address, - NM_HASH_COMBINE_BOOLS(guint8, obj->external)); -} - -int -nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b) -{ - const struct in6_addr *p_a, *p_b; - - NM_CMP_SELF(a, b); - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD_MEMCMP(a, b, address); - NM_CMP_FIELD(a, b, plen); - p_a = nm_platform_ip6_address_get_peer(a); - p_b = nm_platform_ip6_address_get_peer(b); - NM_CMP_DIRECT_MEMCMP(p_a, p_b, sizeof(*p_a)); - NM_CMP_FIELD(a, b, addr_source); - NM_CMP_FIELD(a, b, timestamp); - NM_CMP_FIELD(a, b, lifetime); - NM_CMP_FIELD(a, b, preferred); - NM_CMP_FIELD(a, b, n_ifa_flags); - NM_CMP_FIELD_UNSAFE(a, b, external); - return 0; -} - -void -nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, - NMPlatformIPRouteCmpType cmp_type, - NMHashState * h) -{ - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - nm_hash_update_vals( - h, - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), - nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), - obj->plen, - obj->metric, - obj->tos, - NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - nm_hash_update_vals( - h, - obj->type_coerced, - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), - nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), - obj->plen, - obj->metric, - obj->tos, - /* on top of WEAK_ID: */ - obj->ifindex, - nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), - _ip_route_scope_inv_get_normalized(obj), - obj->gateway, - obj->mss, - obj->pref_src, - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->r_rtm_flags & RTNH_F_ONLINK, - NM_HASH_COMBINE_BOOLS(guint8, - obj->metric_any, - obj->table_any, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - nm_hash_update_vals( - h, - obj->type_coerced, - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), - obj->ifindex, - nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), - obj->plen, - obj->metric, - obj->gateway, - nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), - _ip_route_scope_inv_get_normalized(obj), - obj->tos, - obj->mss, - obj->pref_src, - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), - NM_HASH_COMBINE_BOOLS(guint8, - obj->metric_any, - obj->table_any, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - nm_hash_update_vals(h, - obj->type_coerced, - obj->table_coerced, - obj->ifindex, - obj->network, - obj->plen, - obj->metric, - obj->gateway, - obj->rt_source, - obj->scope_inv, - obj->tos, - obj->mss, - obj->pref_src, - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->r_rtm_flags, - NM_HASH_COMBINE_BOOLS(guint8, - obj->metric_any, - obj->table_any, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu)); - break; - } -} - -int -nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, - const NMPlatformIP4Route *b, - NMPlatformIPRouteCmpType cmp_type) -{ - NM_CMP_SELF(a, b); - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - NM_CMP_FIELD_UNSAFE(a, b, table_any); - NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); - NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); - NM_CMP_FIELD(a, b, plen); - NM_CMP_FIELD_UNSAFE(a, b, metric_any); - NM_CMP_FIELD(a, b, metric); - NM_CMP_FIELD(a, b, tos); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD(a, b, type_coerced); - NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), - nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); - NM_CMP_DIRECT(_ip_route_scope_inv_get_normalized(a), - _ip_route_scope_inv_get_normalized(b)); - NM_CMP_FIELD(a, b, gateway); - NM_CMP_FIELD(a, b, mss); - NM_CMP_FIELD(a, b, pref_src); - NM_CMP_FIELD(a, b, window); - NM_CMP_FIELD(a, b, cwnd); - NM_CMP_FIELD(a, b, initcwnd); - NM_CMP_FIELD(a, b, initrwnd); - NM_CMP_FIELD(a, b, mtu); - NM_CMP_DIRECT(a->r_rtm_flags & RTNH_F_ONLINK, b->r_rtm_flags & RTNH_F_ONLINK); - NM_CMP_FIELD_UNSAFE(a, b, lock_window); - NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_initcwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_initrwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_mtu); - } - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - NM_CMP_FIELD(a, b, type_coerced); - NM_CMP_FIELD_UNSAFE(a, b, table_any); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); - } else - NM_CMP_FIELD(a, b, table_coerced); - NM_CMP_FIELD(a, b, ifindex); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); - else - NM_CMP_FIELD(a, b, network); - NM_CMP_FIELD(a, b, plen); - NM_CMP_FIELD_UNSAFE(a, b, metric_any); - NM_CMP_FIELD(a, b, metric); - NM_CMP_FIELD(a, b, gateway); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), - nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); - NM_CMP_DIRECT(_ip_route_scope_inv_get_normalized(a), - _ip_route_scope_inv_get_normalized(b)); - } else { - NM_CMP_FIELD(a, b, rt_source); - NM_CMP_FIELD(a, b, scope_inv); - } - NM_CMP_FIELD(a, b, mss); - NM_CMP_FIELD(a, b, pref_src); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT(a->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), - b->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK)); - } else - NM_CMP_FIELD(a, b, r_rtm_flags); - NM_CMP_FIELD(a, b, tos); - NM_CMP_FIELD_UNSAFE(a, b, lock_window); - NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_initcwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_initrwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_mtu); - NM_CMP_FIELD(a, b, window); - NM_CMP_FIELD(a, b, cwnd); - NM_CMP_FIELD(a, b, initcwnd); - NM_CMP_FIELD(a, b, initrwnd); - NM_CMP_FIELD(a, b, mtu); - break; - } - return 0; -} - -void -nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, - NMPlatformIPRouteCmpType cmp_type, - NMHashState * h) -{ - struct in6_addr a1, a2; - - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - nm_hash_update_vals( - h, - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), - *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), - obj->plen, - obj->metric, - *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), - obj->src_plen, - NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - nm_hash_update_vals( - h, - obj->type_coerced, - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), - *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), - obj->plen, - obj->metric, - *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), - obj->src_plen, - NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any), - /* on top of WEAK_ID: */ - obj->ifindex, - obj->gateway); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - nm_hash_update_vals( - h, - obj->type_coerced, - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), - obj->ifindex, - *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), - obj->plen, - obj->metric, - obj->gateway, - obj->pref_src, - *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), - obj->src_plen, - nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), - obj->mss, - obj->r_rtm_flags & RTM_F_CLONED, - NM_HASH_COMBINE_BOOLS(guint8, - obj->metric_any, - obj->table_any, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu), - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - _route_pref_normalize(obj->rt_pref)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - nm_hash_update_vals(h, - obj->type_coerced, - obj->table_coerced, - obj->ifindex, - obj->network, - obj->metric, - obj->gateway, - obj->pref_src, - obj->src, - obj->src_plen, - obj->rt_source, - obj->mss, - obj->r_rtm_flags, - NM_HASH_COMBINE_BOOLS(guint8, - obj->metric_any, - obj->table_any, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu), - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->rt_pref); - break; - } -} - -int -nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, - const NMPlatformIP6Route *b, - NMPlatformIPRouteCmpType cmp_type) -{ - NM_CMP_SELF(a, b); - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - NM_CMP_FIELD_UNSAFE(a, b, table_any); - NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); - NM_CMP_FIELD(a, b, plen); - NM_CMP_FIELD_UNSAFE(a, b, metric_any); - NM_CMP_FIELD(a, b, metric); - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); - NM_CMP_FIELD(a, b, src_plen); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { - NM_CMP_FIELD(a, b, ifindex); - NM_CMP_FIELD(a, b, type_coerced); - NM_CMP_FIELD_IN6ADDR(a, b, gateway); - } - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - NM_CMP_FIELD(a, b, type_coerced); - NM_CMP_FIELD_UNSAFE(a, b, table_any); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), - nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); - } else - NM_CMP_FIELD(a, b, table_coerced); - NM_CMP_FIELD(a, b, ifindex); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); - else - NM_CMP_FIELD_IN6ADDR(a, b, network); - NM_CMP_FIELD(a, b, plen); - NM_CMP_FIELD_UNSAFE(a, b, metric_any); - NM_CMP_FIELD(a, b, metric); - NM_CMP_FIELD_IN6ADDR(a, b, gateway); - NM_CMP_FIELD_IN6ADDR(a, b, pref_src); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); - NM_CMP_FIELD(a, b, src_plen); - NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), - nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); - } else { - NM_CMP_FIELD_IN6ADDR(a, b, src); - NM_CMP_FIELD(a, b, src_plen); - NM_CMP_FIELD(a, b, rt_source); - } - NM_CMP_FIELD(a, b, mss); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT(a->r_rtm_flags & RTM_F_CLONED, b->r_rtm_flags & RTM_F_CLONED); - } else - NM_CMP_FIELD(a, b, r_rtm_flags); - NM_CMP_FIELD_UNSAFE(a, b, lock_window); - NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_initcwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_initrwnd); - NM_CMP_FIELD_UNSAFE(a, b, lock_mtu); - NM_CMP_FIELD(a, b, window); - NM_CMP_FIELD(a, b, cwnd); - NM_CMP_FIELD(a, b, initcwnd); - NM_CMP_FIELD(a, b, initrwnd); - NM_CMP_FIELD(a, b, mtu); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT(_route_pref_normalize(a->rt_pref), _route_pref_normalize(b->rt_pref)); - else - NM_CMP_FIELD(a, b, rt_pref); - break; - } - return 0; -} - -#define _ROUTING_RULE_FLAGS_IGNORE \ - (FIB_RULE_UNRESOLVED | FIB_RULE_IIF_DETACHED | FIB_RULE_OIF_DETACHED) - -#define _routing_rule_compare(cmp_type, kernel_support_type) \ - ((cmp_type) == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL \ - || nm_platform_kernel_support_get(kernel_support_type)) - -void -nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj, - NMPlatformRoutingRuleCmpType cmp_type, - NMHashState * h) -{ - gboolean cmp_full = TRUE; - gsize addr_size; - guint32 flags_mask = G_MAXUINT32; - - if (G_UNLIKELY(!NM_IN_SET(obj->addr_family, AF_INET, AF_INET6))) { - /* the address family is not one of the supported ones. That means, the - * instance will only compare equal to itself (pointer-equality). */ - nm_hash_update_val(h, (gconstpointer) obj); - return; - } - - switch (cmp_type) { - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID: - - flags_mask &= ~_ROUTING_RULE_FLAGS_IGNORE; - - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY: - - cmp_full = FALSE; - - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: - - nm_hash_update_vals( - h, - obj->addr_family, - obj->tun_id, - obj->table, - obj->flags & flags_mask, - obj->priority, - obj->fwmark, - obj->fwmask, - ((cmp_full - || (cmp_type == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY - && obj->action == FR_ACT_GOTO)) - ? obj->goto_target - : (guint32) 0u), - ((cmp_full || obj->addr_family == AF_INET) ? obj->flow : (guint32) 0u), - NM_HASH_COMBINE_BOOLS( - guint8, - (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE) - ? obj->uid_range_has - : FALSE)), - obj->suppress_prefixlen_inverse, - obj->suppress_ifgroup_inverse, - (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV) - ? (cmp_full ? (guint16) obj->l3mdev : (guint16) !!obj->l3mdev) - : G_MAXUINT16), - obj->action, - obj->tos, - obj->src_len, - obj->dst_len, - (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL) - ? (guint16) obj->protocol - : G_MAXUINT16)); - addr_size = nm_utils_addr_family_to_size(obj->addr_family); - if (cmp_full || obj->src_len > 0) - nm_hash_update(h, &obj->src, addr_size); - if (cmp_full || obj->dst_len > 0) - nm_hash_update(h, &obj->dst, addr_size); - if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { - if (cmp_full || obj->uid_range_has) - nm_hash_update_valp(h, &obj->uid_range); - } - if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { - nm_hash_update_val(h, obj->ip_proto); - nm_hash_update_valp(h, &obj->sport_range); - nm_hash_update_valp(h, &obj->dport_range); - } - nm_hash_update_str(h, obj->iifname); - nm_hash_update_str(h, obj->oifname); - return; - } - - nm_assert_not_reached(); -} - -int -nm_platform_routing_rule_cmp(const NMPlatformRoutingRule *a, - const NMPlatformRoutingRule *b, - NMPlatformRoutingRuleCmpType cmp_type) -{ - gboolean cmp_full = TRUE; - gsize addr_size; - bool valid; - guint32 flags_mask = G_MAXUINT32; - - NM_CMP_SELF(a, b); - - valid = NM_IN_SET(a->addr_family, AF_INET, AF_INET6); - NM_CMP_DIRECT(valid, (bool) NM_IN_SET(b->addr_family, AF_INET, AF_INET6)); - - if (G_UNLIKELY(!valid)) { - /* the address family is not one of the supported ones. That means, the - * instance will only compare equal to itself. */ - NM_CMP_DIRECT((uintptr_t) a, (uintptr_t) b); - nm_assert_not_reached(); - return 0; - } - - switch (cmp_type) { - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID: - - flags_mask &= ~_ROUTING_RULE_FLAGS_IGNORE; - - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY: - - cmp_full = FALSE; - - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: - NM_CMP_FIELD(a, b, addr_family); - NM_CMP_FIELD(a, b, action); - NM_CMP_FIELD(a, b, priority); - NM_CMP_FIELD(a, b, tun_id); - - if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV)) { - if (cmp_full) - NM_CMP_FIELD(a, b, l3mdev); - else - NM_CMP_FIELD_BOOL(a, b, l3mdev); - } - - NM_CMP_FIELD(a, b, table); - - NM_CMP_DIRECT(a->flags & flags_mask, b->flags & flags_mask); - - NM_CMP_FIELD(a, b, fwmark); - NM_CMP_FIELD(a, b, fwmask); - - if (cmp_full - || (cmp_type == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY - && a->action == FR_ACT_GOTO)) - NM_CMP_FIELD(a, b, goto_target); - - NM_CMP_FIELD(a, b, suppress_prefixlen_inverse); - NM_CMP_FIELD(a, b, suppress_ifgroup_inverse); - NM_CMP_FIELD(a, b, tos); - - if (cmp_full || a->addr_family == AF_INET) - NM_CMP_FIELD(a, b, flow); - - if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) - NM_CMP_FIELD(a, b, protocol); - - if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { - NM_CMP_FIELD(a, b, ip_proto); - NM_CMP_FIELD(a, b, sport_range.start); - NM_CMP_FIELD(a, b, sport_range.end); - NM_CMP_FIELD(a, b, dport_range.start); - NM_CMP_FIELD(a, b, dport_range.end); - } - - addr_size = nm_utils_addr_family_to_size(a->addr_family); - - NM_CMP_FIELD(a, b, src_len); - if (cmp_full || a->src_len > 0) - NM_CMP_FIELD_MEMCMP_LEN(a, b, src, addr_size); - - NM_CMP_FIELD(a, b, dst_len); - if (cmp_full || a->dst_len > 0) - NM_CMP_FIELD_MEMCMP_LEN(a, b, dst, addr_size); - - if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { - NM_CMP_FIELD_UNSAFE(a, b, uid_range_has); - if (cmp_full || a->uid_range_has) { - NM_CMP_FIELD(a, b, uid_range.start); - NM_CMP_FIELD(a, b, uid_range.end); - } - } - - NM_CMP_FIELD_STR(a, b, iifname); - NM_CMP_FIELD_STR(a, b, oifname); - return 0; - } - - nm_assert_not_reached(); - return 0; -} - -/** - * nm_platform_ip_address_cmp_expiry: - * @a: a NMPlatformIPAddress to compare - * @b: the other NMPlatformIPAddress to compare - * - * Compares two addresses and returns which one has a longer remaining lifetime. - * If both addresses have the same lifetime, look at the remaining preferred time. - * - * For comparison, only the timestamp, lifetime and preferred fields are considered. - * If they compare equal (== 0), their other fields were not considered. - * - * Returns: -1, 0, or 1 according to the comparison - **/ -int -nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b) -{ - gint64 ta = 0, tb = 0; - - NM_CMP_SELF(a, b); - - if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0) - ta = G_MAXINT64; - else if (a->timestamp) - ta = ((gint64) a->timestamp) + a->lifetime; - - if (b->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0) - tb = G_MAXINT64; - else if (b->timestamp) - tb = ((gint64) b->timestamp) + b->lifetime; - - if (ta == tb) { - /* if the lifetime is equal, compare the preferred time. */ - ta = tb = 0; - - if (a->preferred == NM_PLATFORM_LIFETIME_PERMANENT - || a->lifetime == 0 /* lifetime==0 means permanent! */) - ta = G_MAXINT64; - else if (a->timestamp) - ta = ((gint64) a->timestamp) + a->preferred; - - if (b->preferred == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0) - tb = G_MAXINT64; - else if (b->timestamp) - tb = ((gint64) b->timestamp) + b->preferred; - - if (ta == tb) - return 0; - } - - return ta < tb ? -1 : 1; -} - -/*****************************************************************************/ - -GHashTable * -nm_platform_ip4_address_addr_to_hash(NMPlatform *self, int ifindex) -{ - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - const NMPObject * obj; - NMPLookup lookup; - GHashTable * hash; - - g_return_val_if_fail(NM_IS_PLATFORM(self), NULL); - g_return_val_if_fail(ifindex > 0, NULL); - - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex); - - head_entry = nmp_cache_lookup(NM_PLATFORM_GET_PRIVATE(self)->cache, &lookup); - - if (!head_entry) - return NULL; - - hash = g_hash_table_new(nm_direct_hash, NULL); - - nmp_cache_iter_for_each (&iter, head_entry, &obj) { - const NMPlatformIP4Address *a = NMP_OBJECT_CAST_IP4_ADDRESS(obj); - - g_hash_table_add(hash, GUINT_TO_POINTER(a->address)); - } - - return hash; -} - -/*****************************************************************************/ - -const char * -nm_platform_signal_change_type_to_string(NMPlatformSignalChangeType change_type) -{ - switch (change_type) { - case NM_PLATFORM_SIGNAL_ADDED: - return "added"; - case NM_PLATFORM_SIGNAL_CHANGED: - return "changed"; - case NM_PLATFORM_SIGNAL_REMOVED: - return "removed"; - default: - g_return_val_if_reached("UNKNOWN"); - } -} - -static void -log_link(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformLink * device, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: link %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_link_to_string(device, NULL, 0)); -} - -static void -log_ip4_address(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformIP4Address * address, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: address 4 %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_ip4_address_to_string(address, NULL, 0)); -} - -static void -log_ip6_address(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformIP6Address * address, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: address 6 %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_ip6_address_to_string(address, NULL, 0)); -} - -static void -log_ip4_route(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformIP4Route * route, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: route 4 %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_ip4_route_to_string(route, NULL, 0)); -} - -static void -log_ip6_route(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformIP6Route * route, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: route 6 %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_ip6_route_to_string(route, NULL, 0)); -} - -static void -log_routing_rule(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformRoutingRule * routing_rule, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - /* routing rules don't have an ifindex. We probably should refactor the signals that are emitted for platform changes. */ - _LOG3D("signal: rt-rule %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_routing_rule_to_string(routing_rule, NULL, 0)); -} - -static void -log_qdisc(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformQdisc * qdisc, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: qdisc %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_qdisc_to_string(qdisc, NULL, 0)); -} - -static void -log_tfilter(NMPlatform * self, - NMPObjectType obj_type, - int ifindex, - NMPlatformTfilter * tfilter, - NMPlatformSignalChangeType change_type, - gpointer user_data) -{ - _LOG3D("signal: tfilter %7s: %s", - nm_platform_signal_change_type_to_string(change_type), - nm_platform_tfilter_to_string(tfilter, NULL, 0)); -} - -/*****************************************************************************/ - -void -nm_platform_cache_update_emit_signal(NMPlatform * self, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new) -{ - gboolean visible_new; - gboolean visible_old; - const NMPObject *o; - const NMPClass * klass; - int ifindex; - - nm_assert(NM_IN_SET((NMPlatformSignalChangeType) cache_op, - NM_PLATFORM_SIGNAL_NONE, - NM_PLATFORM_SIGNAL_ADDED, - NM_PLATFORM_SIGNAL_CHANGED, - NM_PLATFORM_SIGNAL_REMOVED)); - - ASSERT_nmp_cache_ops(nm_platform_get_cache(self), cache_op, obj_old, obj_new); - - NMTST_ASSERT_PLATFORM_NETNS_CURRENT(self); - - switch (cache_op) { - case NMP_CACHE_OPS_ADDED: - if (!nmp_object_is_visible(obj_new)) - return; - o = obj_new; - break; - case NMP_CACHE_OPS_UPDATED: - visible_old = nmp_object_is_visible(obj_old); - visible_new = nmp_object_is_visible(obj_new); - if (!visible_old && visible_new) { - o = obj_new; - cache_op = NMP_CACHE_OPS_ADDED; - } else if (visible_old && !visible_new) { - o = obj_old; - cache_op = NMP_CACHE_OPS_REMOVED; - } else if (!visible_new) { - /* it was invisible and stayed invisible. Nothing to do. */ - return; - } else - o = obj_new; - break; - case NMP_CACHE_OPS_REMOVED: - if (!nmp_object_is_visible(obj_old)) - return; - o = obj_old; - break; - default: - nm_assert(cache_op == NMP_CACHE_OPS_UNCHANGED); - return; - } - - klass = NMP_OBJECT_GET_CLASS(o); - - if (klass->obj_type == NMP_OBJECT_TYPE_ROUTING_RULE) - ifindex = 0; - else - ifindex = NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(o)->ifindex; - - if (klass->obj_type == NMP_OBJECT_TYPE_IP4_ROUTE - && NM_PLATFORM_GET_PRIVATE(self)->ip4_dev_route_blacklist_gc_timeout_id - && NM_IN_SET(cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED)) - _ip4_dev_route_blacklist_notify_route(self, o); - - _LOG3t("emit signal %s %s: %s", - klass->signal_type, - nm_platform_signal_change_type_to_string((NMPlatformSignalChangeType) cache_op), - nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - - nmp_object_ref(o); - g_signal_emit(self, - _nm_platform_signal_id_get(klass->signal_type_id), - 0, - (int) klass->obj_type, - ifindex, - &o->object, - (int) cache_op); - nmp_object_unref(o); -} - -/*****************************************************************************/ - -NMPCache * -nm_platform_get_cache(NMPlatform *self) -{ - return NM_PLATFORM_GET_PRIVATE(self)->cache; -} - -NMPNetns * -nm_platform_netns_get(NMPlatform *self) -{ - _CHECK_SELF(self, klass, NULL); - - return self->_netns; -} - -gboolean -nm_platform_netns_push(NMPlatform *self, NMPNetns **netns) -{ - g_return_val_if_fail(NM_IS_PLATFORM(self), FALSE); - - if (self->_netns && !nmp_netns_push(self->_netns)) { - NM_SET_OUT(netns, NULL); - return FALSE; - } - - NM_SET_OUT(netns, self->_netns); - return TRUE; -} - -/*****************************************************************************/ - -const _NMPlatformVTableRouteUnion nm_platform_vtable_route = { - .v4 = - { - .is_ip4 = TRUE, - .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, - .addr_family = AF_INET, - .sizeof_route = sizeof(NMPlatformIP4Route), - .route_cmp = (int (*)(const NMPlatformIPXRoute *a, - const NMPlatformIPXRoute *b, - NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip4_route_cmp, - .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, - char * buf, - gsize len)) nm_platform_ip4_route_to_string, - }, - .v6 = - { - .is_ip4 = FALSE, - .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, - .addr_family = AF_INET6, - .sizeof_route = sizeof(NMPlatformIP6Route), - .route_cmp = (int (*)(const NMPlatformIPXRoute *a, - const NMPlatformIPXRoute *b, - NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip6_route_cmp, - .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, - char * buf, - gsize len)) nm_platform_ip6_route_to_string, - }, -}; - -/*****************************************************************************/ - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMPlatform * self = NM_PLATFORM(object); - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - - switch (prop_id) { - case PROP_NETNS_SUPPORT: - /* construct-only */ - if (g_value_get_boolean(value)) { - NMPNetns *netns; - - netns = nmp_netns_get_current(); - if (netns) - self->_netns = g_object_ref(netns); - } - break; - case PROP_USE_UDEV: - /* construct-only */ - priv->use_udev = g_value_get_boolean(value); - break; - case PROP_LOG_WITH_PTR: - /* construct-only */ - priv->log_with_ptr = g_value_get_boolean(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -nm_platform_init(NMPlatform *self) -{ - self->_priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_PLATFORM, NMPlatformPrivate); -} - -static GObject * -constructor(GType type, guint n_construct_params, GObjectConstructParam *construct_params) -{ - GObject * object; - NMPlatform * self; - NMPlatformPrivate *priv; - - object = G_OBJECT_CLASS(nm_platform_parent_class) - ->constructor(type, n_construct_params, construct_params); - self = NM_PLATFORM(object); - priv = NM_PLATFORM_GET_PRIVATE(self); - - priv->multi_idx = nm_dedup_multi_index_new(); - - priv->cache = nmp_cache_new(priv->multi_idx, priv->use_udev); - - return object; -} - -static void -finalize(GObject *object) -{ - NMPlatform * self = NM_PLATFORM(object); - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - - nm_clear_g_source(&priv->ip4_dev_route_blacklist_check_id); - nm_clear_g_source(&priv->ip4_dev_route_blacklist_gc_timeout_id); - nm_clear_pointer(&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); - g_clear_object(&self->_netns); - nm_dedup_multi_index_unref(priv->multi_idx); - nmp_cache_free(priv->cache); -} - -static void -nm_platform_class_init(NMPlatformClass *platform_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(platform_class); - - g_type_class_add_private(object_class, sizeof(NMPlatformPrivate)); - - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->finalize = finalize; - - platform_class->wifi_set_powersave = wifi_set_powersave; - - g_object_class_install_property( - object_class, - PROP_NETNS_SUPPORT, - g_param_spec_boolean(NM_PLATFORM_NETNS_SUPPORT, - "", - "", - NM_PLATFORM_NETNS_SUPPORT_DEFAULT, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property( - object_class, - PROP_USE_UDEV, - g_param_spec_boolean(NM_PLATFORM_USE_UDEV, - "", - "", - FALSE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property( - object_class, - PROP_LOG_WITH_PTR, - g_param_spec_boolean(NM_PLATFORM_LOG_WITH_PTR, - "", - "", - TRUE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - -#define SIGNAL(signal, signal_id, method) \ - G_STMT_START \ - { \ - signals[signal] = \ - g_signal_new_class_handler("" signal_id "", \ - G_OBJECT_CLASS_TYPE(object_class), \ - G_SIGNAL_RUN_FIRST, \ - G_CALLBACK(method), \ - NULL, \ - NULL, \ - NULL, \ - G_TYPE_NONE, \ - 4, \ - G_TYPE_INT, /* (int) NMPObjectType */ \ - G_TYPE_INT, /* ifindex */ \ - G_TYPE_POINTER /* const NMPObject * */, \ - G_TYPE_INT /* (int) NMPlatformSignalChangeType */ \ - ); \ - } \ - G_STMT_END - - /* Signals */ - SIGNAL(NM_PLATFORM_SIGNAL_ID_LINK, NM_PLATFORM_SIGNAL_LINK_CHANGED, log_link); - SIGNAL(NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, - NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, - log_ip4_address); - SIGNAL(NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, - NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, - log_ip6_address); - SIGNAL(NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route); - SIGNAL(NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route); - SIGNAL(NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, - NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, - log_routing_rule); - SIGNAL(NM_PLATFORM_SIGNAL_ID_QDISC, NM_PLATFORM_SIGNAL_QDISC_CHANGED, log_qdisc); - SIGNAL(NM_PLATFORM_SIGNAL_ID_TFILTER, NM_PLATFORM_SIGNAL_TFILTER_CHANGED, log_tfilter); -} diff --git a/src/core/platform/nm-platform.h b/src/core/platform/nm-platform.h deleted file mode 100644 index d400c568..00000000 --- a/src/core/platform/nm-platform.h +++ /dev/null @@ -1,2372 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2009 - 2018 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_PLATFORM_H__ -#define __NETWORKMANAGER_PLATFORM_H__ - -#include "nm-dbus-interface.h" -#include "nm-core-types-internal.h" - -#include "nm-platform/nmp-base.h" -#include "nm-base/nm-base.h" - -#include "nm-core-utils.h" -#include "nm-setting-vlan.h" -#include "nm-setting-wired.h" -#include "nm-setting-wireless.h" -#include "nm-setting-ip-tunnel.h" - -#define NM_TYPE_PLATFORM (nm_platform_get_type()) -#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PLATFORM, NMPlatform)) -#define NM_PLATFORM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_PLATFORM, NMPlatformClass)) -#define NM_IS_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_PLATFORM)) -#define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_PLATFORM)) -#define NM_PLATFORM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_PLATFORM, NMPlatformClass)) - -#define NM_PLATFORM_NETNS_SUPPORT_DEFAULT FALSE - -/*****************************************************************************/ - -#define NM_PLATFORM_NETNS_SUPPORT "netns-support" -#define NM_PLATFORM_USE_UDEV "use-udev" -#define NM_PLATFORM_LOG_WITH_PTR "log-with-ptr" - -/*****************************************************************************/ - -/* IFNAMSIZ is both defined in and . In the past, these - * headers conflicted, so we cannot simply include either of them in a header-file.*/ -#define NMP_IFNAMSIZ 16 - -/*****************************************************************************/ - -struct _NMPWireGuardPeer; - -struct udev_device; - -typedef gboolean (*NMPObjectPredicateFunc)(const NMPObject *obj, gpointer user_data); - -/* workaround for older libnl version, that does not define these flags. */ -#ifndef IFA_F_MANAGETEMPADDR - #define IFA_F_MANAGETEMPADDR 0x100 -#endif -#ifndef IFA_F_NOPREFIXROUTE - #define IFA_F_NOPREFIXROUTE 0x200 -#endif - -#define NM_RT_SCOPE_LINK 253 /* RT_SCOPE_LINK */ - -/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers - * that don't define it. */ -#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */ -#define NM_IN6_ADDR_GEN_MODE_EUI64 0 /* IN6_ADDR_GEN_MODE_EUI64 */ -#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */ -#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */ -#define NM_IN6_ADDR_GEN_MODE_RANDOM 3 /* IN6_ADDR_GEN_MODE_RANDOM */ - -#define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */ - -/* Redefine this in host's endianness */ -#define NM_GRE_KEY 0x2000 - -typedef enum { - NMP_NLM_FLAG_F_ECHO = 0x08, /* NLM_F_ECHO, Echo this request */ - - /* use our own platform enum for the nlmsg-flags. Otherwise, we'd have - * to include */ - NMP_NLM_FLAG_F_REPLACE = 0x100, /* NLM_F_REPLACE, Override existing */ - NMP_NLM_FLAG_F_EXCL = 0x200, /* NLM_F_EXCL, Do not touch, if it exists */ - NMP_NLM_FLAG_F_CREATE = 0x400, /* NLM_F_CREATE, Create, if it does not exist */ - NMP_NLM_FLAG_F_APPEND = 0x800, /* NLM_F_APPEND, Add to end of list */ - - NMP_NLM_FLAG_FMASK = 0xFFFF, /* a mask for all NMP_NLM_FLAG_F_* flags */ - - /* instructs NM to suppress logging an error message for any failures - * received from kernel. - * - * It will still log with debug-level, and it will still log - * other failures aside the kernel response. */ - NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE = 0x10000, - - /* the following aliases correspond to iproute2's `ip route CMD` for - * RTM_NEWROUTE, with CMD being one of add, change, replace, prepend, - * append and test. */ - NMP_NLM_FLAG_ADD = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_EXCL, - NMP_NLM_FLAG_CHANGE = NMP_NLM_FLAG_F_REPLACE, - NMP_NLM_FLAG_REPLACE = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_REPLACE, - NMP_NLM_FLAG_PREPEND = NMP_NLM_FLAG_F_CREATE, - NMP_NLM_FLAG_APPEND = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_APPEND, - NMP_NLM_FLAG_TEST = NMP_NLM_FLAG_F_EXCL, -} NMPNlmFlags; - -typedef enum { - /* compare fields which kernel considers as similar routes. - * It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID - * and means that `ip route add` would fail to add two routes - * that have the same NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID. - * On the other hand, `ip route append` would allow that, as - * long as NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID differs. */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, - - /* compare two routes as kernel would allow to add them with - * `ip route append`. In other words, kernel does not allow you to - * add two routes (at the same time) which compare equal according - * to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID. - * - * For the ID we can only recognize route fields that we actually implement. - * However, kernel supports more routing options, some of them also part of - * the ID. NetworkManager is oblivious to these options and will wrongly think - * that two routes are identical, while they are not. That can lead to an - * inconsistent platform cache. Not much what we can do about that, except - * implementing all options that kernel supports *sigh*. See rh#1337860. - */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, - - /* compare all fields as they make sense for kernel. For example, - * a route destination 192.168.1.5/24 is not accepted by kernel and - * we treat it identical to 192.168.1.0/24. Semantically these - * routes are identical, but NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL will - * report them as different. - * - * The result shall be identical to call first nm_platform_ip_route_normalize() - * on both routes and then doing a full comparison. */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY, - - /* compare all fields. This should have the same effect as memcmp(), - * except allowing for undefined data in holes between field alignment. - */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, - -} NMPlatformIPRouteCmpType; - -typedef enum { - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, - - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY, - - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL, -} NMPlatformRoutingRuleCmpType; - -typedef struct { - union { - guint8 data[20 /* NM_UTILS_HWADDR_LEN_MAX */]; - NMEtherAddr ether_addr; - }; - guint8 len; -} NMPLinkAddress; - -/* assert that NMEtherAddr does not affect the alignment of NMPLinkAddress struct. */ -G_STATIC_ASSERT(_nm_alignof(NMEtherAddr) == 1); -G_STATIC_ASSERT(_nm_alignof(NMPLinkAddress) == 1); - -gconstpointer nmp_link_address_get(const NMPLinkAddress *addr, size_t *length); -GBytes * nmp_link_address_get_as_bytes(const NMPLinkAddress *addr); - -typedef enum { - - /* match-flags are strictly inclusive. That means, - * by default nothing is matched, but if you enable a particular - * flag, a candidate that matches passes the check. - * - * In other words: adding more flags can only extend the result - * set of matching objects. - * - * Also, the flags form partitions. Like, an address can be either of - * ADDRTYPE_NORMAL or ADDRTYPE_LINKLOCAL, but never both. Same for - * the ADDRSTATE match types. - */ - NM_PLATFORM_MATCH_WITH_NONE = 0, - - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL = (1LL << 0), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL = (1LL << 1), - NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY = - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL | NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL, - - NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL = (1LL << 2), - NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE = (1LL << 3), - NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED = (1LL << 4), - NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY = NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED, -} NMPlatformMatchFlags; - -#define NM_PLATFORM_LINK_OTHER_NETNS (-1) - -struct _NMPlatformObject { - /* the object type has no fields of its own, it is only used to having - * a special pointer type that can be used to indicate "any" type. */ - char _dummy_don_t_use_me; -}; - -#define __NMPlatformObjWithIfindex_COMMON \ - int ifindex; \ - ; - -struct _NMPlatformObjWithIfindex { - __NMPlatformObjWithIfindex_COMMON; -}; - -struct _NMPlatformLink { - __NMPlatformObjWithIfindex_COMMON; - char name[NMP_IFNAMSIZ]; - NMLinkType type; - - /* rtnl_link_get_type(), IFLA_INFO_KIND. */ - /* NMPlatform initializes this field with a static string. */ - const char *kind; - - /* NMPlatform initializes this field with a static string. */ - const char *driver; - - int master; - - /* rtnl_link_get_link(), IFLA_LINK. - * If IFLA_LINK_NETNSID indicates that the parent is in another namespace, - * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */ - int parent; - - /* IFF_* flags. Note that the flags in 'struct ifinfomsg' are declared as 'unsigned'. */ - guint n_ifi_flags; - - guint mtu; - - /* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */ - guint32 arptype; - - /* IFLA_ADDRESS */ - NMPLinkAddress l_address; - - /* IFLA_BROADCAST */ - NMPLinkAddress l_broadcast; - - /* rtnl_link_inet6_get_token(), IFLA_INET6_TOKEN */ - NMUtilsIPv6IfaceId inet6_token; - - /* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse - * to have a default of 0 -- meaning: unspecified. That way, a struct - * initialized with memset(0) has and unset value.*/ - guint8 inet6_addr_gen_mode_inv; - - /* Statistics */ - guint64 rx_packets; - guint64 rx_bytes; - guint64 tx_packets; - guint64 tx_bytes; - - /* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters, - * where we coerce the link as disconnect if it has no slaves. */ - bool connected : 1; - - bool initialized : 1; -}; - -typedef enum { /*< skip >*/ - NM_PLATFORM_SIGNAL_ID_NONE, - NM_PLATFORM_SIGNAL_ID_LINK, - NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, - NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, - NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, - NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, - NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, - NM_PLATFORM_SIGNAL_ID_QDISC, - NM_PLATFORM_SIGNAL_ID_TFILTER, - _NM_PLATFORM_SIGNAL_ID_LAST, -} NMPlatformSignalIdType; - -guint _nm_platform_signal_id_get(NMPlatformSignalIdType signal_type); - -typedef enum { - NM_PLATFORM_SIGNAL_NONE, - NM_PLATFORM_SIGNAL_ADDED, - NM_PLATFORM_SIGNAL_CHANGED, - NM_PLATFORM_SIGNAL_REMOVED, -} NMPlatformSignalChangeType; - -#define NM_PLATFORM_IP_ADDRESS_CAST(address) \ - NM_CONSTCAST(NMPlatformIPAddress, \ - (address), \ - NMPlatformIPXAddress, \ - NMPlatformIP4Address, \ - NMPlatformIP6Address) - -#define __NMPlatformIPAddress_COMMON \ - __NMPlatformObjWithIfindex_COMMON; \ - NMIPConfigSource addr_source; \ - \ - /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*(). - * - * The rules are: - * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses - * are permanent. This rule is so that unset addresses (calloc) are permanent by default. - * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly - * set to 0). Such addresses are permanent. - * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp - * and never returned by nm_utils_get_monotonic_timestamp_sec(). In this case @valid/@preferred - * is anchored at @timestamp. - * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time - * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add(). - * - * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the - * lease was received. Addresses from kernel might have the @timestamp based on the last modification - * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring - * @lifetime and @preferred. - */ \ - guint32 timestamp; \ - guint32 lifetime; /* seconds since timestamp */ \ - guint32 preferred; /* seconds since timestamp */ \ - \ - /* ifa_flags in 'struct ifaddrmsg' from , extended to 32 bit by - * IFA_FLAGS attribute. */ \ - guint32 n_ifa_flags; \ - \ - guint8 plen; \ - \ - /* FIXME(l3cfg): the external marker won't be necessary anymore, because we only - * merge addresses we care about, and ignore (don't remove) external addresses. */ \ - bool external : 1; \ - \ - bool use_ip4_broadcast_address : 1; \ - \ - /* Whether the address is ready to be configured. By default, an address is, but this - * flag may indicate that the address is just for tracking purpose only, but the ACD - * state is not yet ready for the address to be configured. */ \ - bool ip4acd_not_ready : 1; \ - ; - -/** - * NMPlatformIPAddress: - * - * Common parts of NMPlatformIP4Address and NMPlatformIP6Address. - **/ -typedef struct { - __NMPlatformIPAddress_COMMON; - union { - guint8 address_ptr[1]; - guint32 __dummy_for_32bit_alignment; - }; -} NMPlatformIPAddress; - -/** - * NMPlatformIP4Address: - * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec() - **/ -struct _NMPlatformIP4Address { - __NMPlatformIPAddress_COMMON; - - /* The local address IFA_LOCAL. */ - in_addr_t address; - - /* The IFA_ADDRESS PTP peer address. This field is rather important, because - * it constitutes the identifier for the IPv4 address (e.g. you can add two - * addresses that only differ by their peer's network-part. - * - * Beware that for most cases, NetworkManager doesn't want to set an explicit - * peer-address. However, that corresponds to setting the peer address to @address - * itself. Leaving peer-address unset/zero, means explicitly setting the peer - * address to 0.0.0.0, which you probably don't want. - * */ - in_addr_t peer_address; /* PTP peer address */ - - /* IFA_BROADCAST. - * - * This parameter is ignored unless use_ip4_broadcast_address is TRUE. - * See nm_platform_ip4_broadcast_address_from_addr(). */ - in_addr_t broadcast_address; - - char label[NMP_IFNAMSIZ]; -}; - -/** - * NMPlatformIP6Address: - * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec() - **/ -struct _NMPlatformIP6Address { - __NMPlatformIPAddress_COMMON; - struct in6_addr address; - struct in6_addr peer_address; -}; - -typedef union { - NMPlatformIPAddress ax; - NMPlatformIP4Address a4; - NMPlatformIP6Address a6; -} NMPlatformIPXAddress; - -#undef __NMPlatformIPAddress_COMMON - -#define NM_PLATFORM_IP4_ADDRESS_INIT(...) (&((const NMPlatformIP4Address){__VA_ARGS__})) - -#define NM_PLATFORM_IP6_ADDRESS_INIT(...) (&((const NMPlatformIP6Address){__VA_ARGS__})) - -/* Default value for adding an IPv4 route. This is also what iproute2 does. - * Note that contrary to IPv6, you can add routes with metric 0 and it is even - * the default. - */ -#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 ((guint32) 0u) - -/* Default value for adding an IPv6 route. This is also what iproute2 does. - * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024). - * - * Note that kernel doesn't allow adding IPv6 routes with metric zero via netlink. - * It however can itself add routes with metric zero. */ -#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 ((guint32) 1024u) - -/* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user - * configures addresses. */ -#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE ((guint32) 0u) - -#define __NMPlatformIPRoute_COMMON \ - __NMPlatformObjWithIfindex_COMMON; \ - \ - /* The NMIPConfigSource. For routes that we receive from cache this corresponds - * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values). - * When adding a route, the source will be coerced to the protocol using - * nmp_utils_ip_config_source_coerce_to_rtprot(). - * - * rtm_protocol is part of the primary key of an IPv4 route (meaning, you can add - * two IPv4 routes that only differ in their rtm_protocol. For IPv6, that is not - * the case. - * - * When deleting an IPv4/IPv6 route, the rtm_protocol field must match (even - * if it is not part of the primary key for IPv6) -- unless rtm_protocol is set - * to zero, in which case the first matching route (with proto ignored) is deleted. */ \ - NMIPConfigSource rt_source; \ - \ - guint8 plen; \ - \ - /* RTA_METRICS: - * - * For IPv4 routes, these properties are part of their - * ID (meaning: you can add otherwise identical IPv4 routes that - * only differ by the metric property). - * On the other hand, for IPv6 you cannot add two IPv6 routes that only differ - * by an RTA_METRICS property. - * - * When deleting a route, kernel seems to ignore the RTA_METRICS properties. - * That is a problem/bug for IPv4 because you cannot explicitly select which - * route to delete. Kernel just picks the first. See rh#1475642. */ \ - \ - /* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \ - bool lock_window : 1; \ - bool lock_cwnd : 1; \ - bool lock_initcwnd : 1; \ - bool lock_initrwnd : 1; \ - bool lock_mtu : 1; \ - \ - /* if TRUE, the "metric" field is interpreted as an offset that is added to a default - * metric. For example, form a DHCP lease we don't know the actually used metric, because - * that is determined by upper layers (the configuration). However, we have a default - * metric that should be used. So we set "metric_any" to %TRUE, which means to use - * the default metric. However, we still treat the "metric" field as an offset that - * will be added to the default metric. In most case, you want that "metric" is zero - * when setting "metric_any". */ \ - bool metric_any : 1; \ - \ - /* like "metric_any", the table is determined by other layers of the code. - * This field overrides "table_coerced" field. If "table_any" is true, then - * the "table_coerced" field is ignored (unlike for the metric). */ \ - bool table_any : 1; \ - \ - /* rtnh_flags - * - * Routes with rtm_flags RTM_F_CLONED are hidden by platform and - * do not exist from the point-of-view of platform users. - * Such a route is not alive, according to nmp_object_is_alive(). - * - * NOTE: currently we ignore all flags except RTM_F_CLONED - * and RTNH_F_ONLINK. - * We also may not properly consider the flags as part of the ID - * in route-cmp. */ \ - unsigned r_rtm_flags; \ - \ - /* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \ - guint32 mss; \ - \ - /* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \ - guint32 window; \ - \ - /* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \ - guint32 cwnd; \ - \ - /* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \ - guint32 initcwnd; \ - \ - /* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \ - guint32 initrwnd; \ - \ - /* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \ - guint32 mtu; \ - \ - /* RTA_PRIORITY (iproute2: metric) - * If "metric_any" is %TRUE, then this is interpreted as an offset that will be - * added to a default base metric. In such cases, the offset is usually zero. */ \ - guint32 metric; \ - \ - /* rtm_table, RTA_TABLE. - * - * This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and - * zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main - * table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \ - guint32 table_coerced; \ - \ - /* rtm_type. - * - * This is not the original type, if type_coerced is 0 then - * it means RTN_UNSPEC otherwise the type value is preserved. - * */ \ - guint8 type_coerced; \ - \ - /*end*/ - -typedef struct { - __NMPlatformIPRoute_COMMON; - union { - guint8 network_ptr[1]; - guint32 __dummy_for_32bit_alignment; - }; -} NMPlatformIPRoute; - -#define NM_PLATFORM_IP_ROUTE_CAST(route) \ - NM_CONSTCAST(NMPlatformIPRoute, \ - (route), \ - NMPlatformIPXRoute, \ - NMPlatformIP4Route, \ - NMPlatformIP6Route) - -#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) (NM_PLATFORM_IP_ROUTE_CAST(route)->plen <= 0) - -struct _NMPlatformIP4Route { - __NMPlatformIPRoute_COMMON; - in_addr_t network; - - /* RTA_GATEWAY. The gateway is part of the primary key for a route */ - in_addr_t gateway; - - /* RTA_PREFSRC (called "src" by iproute2). - * - * pref_src is part of the ID of an IPv4 route. When deleting a route, - * pref_src must match, unless set to 0.0.0.0 to match any. */ - in_addr_t pref_src; - - /* rtm_tos (iproute2: tos) - * - * For IPv4, tos is part of the weak-id (like metric). - * - * For IPv6, tos is ignored by kernel. */ - guint8 tos; - - /* The bitwise inverse of the route scope rtm_scope. It is inverted so that the - * default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv() - * to convert back and forth between the inverse representation and the - * real value. - * - * rtm_scope is part of the primary key for IPv4 routes. When deleting a route, - * the scope must match, unless it is left at RT_SCOPE_NOWHERE, in which case the first - * matching route is deleted. - * - * For IPv6 routes, the scope is ignored and kernel always assumes global scope. - * Hence, this field is only in NMPlatformIP4Route. */ - guint8 scope_inv; -}; - -struct _NMPlatformIP6Route { - __NMPlatformIPRoute_COMMON; - struct in6_addr network; - - /* RTA_GATEWAY. The gateway is part of the primary key for a route */ - struct in6_addr gateway; - - /* RTA_PREFSRC (called "src" by iproute2). - * - * pref_src is not part of the ID for an IPv6 route. You cannot add two - * routes that only differ by pref_src. - * - * When deleting a route, pref_src is ignored by kernel. */ - struct in6_addr pref_src; - - /* RTA_SRC and rtm_src_len (called "from" by iproute2). - * - * Kernel clears the host part of src/src_plen. - * - * src/src_plen is part of the ID of a route just like network/plen. That is, - * Not only `ip route append`, but also `ip route add` allows to add routes that only - * differ in their src/src_plen. - */ - struct in6_addr src; - guint8 src_plen; - - /* RTA_PREF router preference. - * - * The type is guint8 to keep the struct size small. But the values are compatible with - * the NMIcmpv6RouterPref enum. */ - guint8 rt_pref; -}; - -typedef union { - NMPlatformIPRoute rx; - NMPlatformIP4Route r4; - NMPlatformIP6Route r6; -} NMPlatformIPXRoute; - -#undef __NMPlatformIPRoute_COMMON - -typedef struct { - /* struct fib_rule_uid_range */ - guint32 start; - guint32 end; -} NMFibRuleUidRange; - -typedef struct { - /* struct fib_rule_port_range */ - guint16 start; - guint16 end; -} NMFibRulePortRange; - -typedef struct { - NMIPAddr src; /* FRA_SRC */ - NMIPAddr dst; /* FRA_DST */ - guint64 tun_id; /* betoh64(FRA_TUN_ID) */ - guint32 table; /* (struct fib_rule_hdr).table, FRA_TABLE */ - guint32 flags; /* (struct fib_rule_hdr).flags */ - guint32 priority; /* RA_PRIORITY */ - guint32 fwmark; /* FRA_FWMARK */ - guint32 fwmask; /* FRA_FWMASK */ - guint32 goto_target; /* FRA_GOTO */ - guint32 flow; /* FRA_FLOW */ - guint32 suppress_prefixlen_inverse; /* ~(FRA_SUPPRESS_PREFIXLEN) */ - guint32 suppress_ifgroup_inverse; /* ~(FRA_SUPPRESS_IFGROUP) */ - NMFibRuleUidRange uid_range; /* FRA_UID_RANGE */ - NMFibRulePortRange sport_range; /* FRA_SPORT_RANGE */ - NMFibRulePortRange dport_range; /* FRA_DPORT_RANGE */ - char iifname[NMP_IFNAMSIZ]; /* FRA_IIFNAME */ - char oifname[NMP_IFNAMSIZ]; /* FRA_OIFNAME */ - guint8 addr_family; /* (struct fib_rule_hdr).family */ - guint8 action; /* (struct fib_rule_hdr).action */ - guint8 tos; /* (struct fib_rule_hdr).tos */ - guint8 src_len; /* (struct fib_rule_hdr).src_len */ - guint8 dst_len; /* (struct fib_rule_hdr).dst_len */ - guint8 l3mdev; /* FRA_L3MDEV */ - guint8 protocol; /* FRA_PROTOCOL */ - guint8 ip_proto; /* FRA_IP_PROTO */ - - bool uid_range_has : 1; /* has(FRA_UID_RANGE) */ -} NMPlatformRoutingRule; - -#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0)) - -#define NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED ((guint32) 0x83126E97u) - -G_STATIC_ASSERT(((((guint64) NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) * 1000u) >> 10) - == (guint64) INT_MAX); - -typedef struct { - guint32 limit; - guint32 flows; - guint32 target; - guint32 interval; - guint32 quantum; - - /* TCA_FQ_CODEL_CE_THRESHOLD: kernel internally stores this value as - * ((val64 * NSEC_PER_USEC) >> CODEL_SHIFT). The default value (in - * the domain with this coercion) is CODEL_DISABLED_THRESHOLD (INT_MAX). - * That means, "disabled" is expressed on RTM_NEWQDISC netlink API by absence of the - * netlink attribute but also as the special value 0x83126E97u - * (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED). - * Beware: zero is not the default you must always explicitly set this value. */ - guint32 ce_threshold; - - /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel - * and kernel defaults to 32MB. - * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET - * to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request). - * This will cause kernel to choose the default (32MB). - * Beware: zero is not the default you must always explicitly set this value. */ - guint32 memory_limit; - - bool ecn : 1; -} NMPlatformQdiscFqCodel; - -typedef struct { - unsigned quantum; - int perturb_period; - guint32 limit; - unsigned divisor; - unsigned flows; - unsigned depth; -} NMPlatformQdiscSfq; - -typedef struct { - guint64 rate; - guint32 burst; - guint32 limit; - guint32 latency; -} NMPlatformQdiscTbf; - -typedef struct { - __NMPlatformObjWithIfindex_COMMON; - - /* beware, kind is embedded in an NMPObject, hence you must - * take care of the lifetime of the string. */ - const char *kind; - - int addr_family; - guint32 handle; - guint32 parent; - guint32 info; - union { - NMPlatformQdiscFqCodel fq_codel; - NMPlatformQdiscSfq sfq; - NMPlatformQdiscTbf tbf; - }; -} NMPlatformQdisc; - -typedef struct { - char sdata[32]; -} NMPlatformActionSimple; - -typedef struct { - int ifindex; - bool egress : 1; - bool ingress : 1; - bool mirror : 1; - bool redirect : 1; -} NMPlatformActionMirred; - -typedef struct { - /* beware, kind is embedded in an NMPObject, hence you must - * take care of the lifetime of the string. */ - const char *kind; - - union { - NMPlatformActionSimple simple; - NMPlatformActionMirred mirred; - }; -} NMPlatformAction; - -#define NM_PLATFORM_ACTION_KIND_SIMPLE "simple" -#define NM_PLATFORM_ACTION_KIND_MIRRED "mirred" - -typedef struct { - __NMPlatformObjWithIfindex_COMMON; - - /* beware, kind is embedded in an NMPObject, hence you must - * take care of the lifetime of the string. */ - const char *kind; - - int addr_family; - guint32 handle; - guint32 parent; - guint32 info; - NMPlatformAction action; -} NMPlatformTfilter; - -#undef __NMPlatformObjWithIfindex_COMMON - -typedef struct { - gboolean is_ip4; - NMPObjectType obj_type; - int addr_family; - gsize sizeof_route; - int (*route_cmp)(const NMPlatformIPXRoute *a, - const NMPlatformIPXRoute *b, - NMPlatformIPRouteCmpType cmp_type); - const char *(*route_to_string)(const NMPlatformIPXRoute *route, char *buf, gsize len); -} NMPlatformVTableRoute; - -typedef union { - struct { - NMPlatformVTableRoute v6; - NMPlatformVTableRoute v4; - }; - NMPlatformVTableRoute vx[2]; -} _NMPlatformVTableRouteUnion; - -extern const _NMPlatformVTableRouteUnion nm_platform_vtable_route; - -typedef struct { - guint16 id; - guint32 qos; - bool proto_ad : 1; -} NMPlatformVFVlan; - -typedef struct { - guint32 index; - guint32 min_tx_rate; - guint32 max_tx_rate; - guint num_vlans; - NMPlatformVFVlan *vlans; - struct { - guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */ - guint8 len; - } mac; - gint8 spoofchk; - gint8 trust; -} NMPlatformVF; - -typedef struct { - guint16 vid_start; - guint16 vid_end; - bool untagged : 1; - bool pvid : 1; -} NMPlatformBridgeVlan; - -typedef struct { - NMEtherAddr group_addr; - bool mcast_querier : 1; - bool mcast_query_use_ifaddr : 1; - bool mcast_snooping : 1; - bool stp_state : 1; - bool vlan_stats_enabled : 1; - guint16 group_fwd_mask; - guint16 priority; - guint16 vlan_protocol; - guint32 ageing_time; - guint32 forward_delay; - guint32 hello_time; - guint32 max_age; - guint32 mcast_last_member_count; - guint32 mcast_startup_query_count; - guint32 mcast_hash_max; - guint64 mcast_last_member_interval; - guint64 mcast_membership_interval; - guint64 mcast_querier_interval; - guint64 mcast_query_interval; - guint64 mcast_query_response_interval; - guint64 mcast_startup_query_interval; - guint8 mcast_router; -} NMPlatformLnkBridge; - -extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default; - -typedef struct { - in_addr_t local; - in_addr_t remote; - int parent_ifindex; - guint16 input_flags; - guint16 output_flags; - guint32 input_key; - guint32 output_key; - guint8 ttl; - guint8 tos; - bool path_mtu_discovery : 1; - bool is_tap : 1; -} NMPlatformLnkGre; - -typedef struct { - int p_key; - const char *mode; -} NMPlatformLnkInfiniband; - -typedef struct { - struct in6_addr local; - struct in6_addr remote; - int parent_ifindex; - guint8 ttl; - guint8 tclass; - guint8 encap_limit; - guint8 proto; - guint flow_label; - guint32 flags; - - /* IP6GRE only */ - guint32 input_key; - guint32 output_key; - guint16 input_flags; - guint16 output_flags; - bool is_tap : 1; - bool is_gre : 1; -} NMPlatformLnkIp6Tnl; - -typedef struct { - in_addr_t local; - in_addr_t remote; - int parent_ifindex; - guint8 ttl; - guint8 tos; - bool path_mtu_discovery : 1; -} NMPlatformLnkIpIp; - -typedef struct { - int parent_ifindex; - guint64 sci; /* host byte order */ - guint64 cipher_suite; - guint32 window; - guint8 icv_length; - guint8 encoding_sa; - guint8 validation; - bool encrypt : 1; - bool protect : 1; - bool include_sci : 1; - bool es : 1; - bool scb : 1; - bool replay_protect : 1; -} NMPlatformLnkMacsec; - -typedef struct { - guint mode; - bool no_promisc : 1; - bool tap : 1; -} NMPlatformLnkMacvlan; - -typedef struct { - in_addr_t local; - in_addr_t remote; - int parent_ifindex; - guint16 flags; - guint8 ttl; - guint8 tos; - guint8 proto; - bool path_mtu_discovery : 1; -} NMPlatformLnkSit; - -typedef struct { - guint32 owner; - guint32 group; - - guint8 type; - - bool owner_valid : 1; - bool group_valid : 1; - - bool pi : 1; - bool vnet_hdr : 1; - bool multi_queue : 1; - bool persist : 1; -} NMPlatformLnkTun; - -typedef struct { - /* rtnl_link_vlan_get_id(), IFLA_VLAN_ID */ - guint16 id; - NMVlanFlags flags; -} NMPlatformLnkVlan; - -typedef struct { - guint32 table; -} NMPlatformLnkVrf; - -typedef struct { - struct in6_addr group6; - struct in6_addr local6; - in_addr_t group; - in_addr_t local; - int parent_ifindex; - guint32 id; - guint32 ageing; - guint32 limit; - guint16 dst_port; - guint16 src_port_min; - guint16 src_port_max; - guint8 tos; - guint8 ttl; - bool learning : 1; - bool proxy : 1; - bool rsc : 1; - bool l2miss : 1; - bool l3miss : 1; -} NMPlatformLnkVxlan; - -#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32 -#define NMP_WIREGUARD_SYMMETRIC_KEY_LEN 32 - -typedef struct { - guint32 fwmark; - guint16 listen_port; - guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; - guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; -} NMPlatformLnkWireGuard; - -typedef enum { - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0, - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0), - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1), - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT = (1LL << 2), - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK = (1LL << 3), -} NMPlatformWireGuardChangeFlags; - -typedef enum { - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE = 0, - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME = (1LL << 0), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY = (1LL << 1), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL = (1LL << 2), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT = (1LL << 3), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS = (1LL << 4), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS = (1LL << 5), - - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT = - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, - -} NMPlatformWireGuardChangePeerFlags; - -typedef void (*NMPlatformAsyncCallback)(GError *error, gpointer user_data); - -/*****************************************************************************/ - -typedef enum { - NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED, - - /* this also includes FRA_SPORT_RANGE and FRA_DPORT_RANGE which - * were added at the same time. */ - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO, - - _NM_PLATFORM_KERNEL_SUPPORT_NUM, -} NMPlatformKernelSupportType; - -extern volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM]; - -int _nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value); - -static inline gboolean -_nm_platform_kernel_support_detected(NMPlatformKernelSupportType type) -{ - nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(_nm_platform_kernel_support_state)); - - return G_LIKELY(g_atomic_int_get(&_nm_platform_kernel_support_state[type]) != 0); -} - -static inline NMOptionBool -nm_platform_kernel_support_get_full(NMPlatformKernelSupportType type, gboolean init_if_not_set) -{ - int v; - - nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(_nm_platform_kernel_support_state)); - - v = g_atomic_int_get(&_nm_platform_kernel_support_state[type]); - if (G_UNLIKELY(v == 0)) { - if (!init_if_not_set) - return NM_OPTION_BOOL_DEFAULT; - v = _nm_platform_kernel_support_init(type, 0); - } - return (v >= 0); -} - -static inline gboolean -nm_platform_kernel_support_get(NMPlatformKernelSupportType type) -{ - return nm_platform_kernel_support_get_full(type, TRUE) != NM_OPTION_BOOL_FALSE; -} - -/*****************************************************************************/ - -struct _NMPlatformPrivate; - -struct _NMPlatform { - GObject parent; - NMPNetns * _netns; - struct _NMPlatformPrivate *_priv; -}; - -typedef struct { - GObjectClass parent; - - gboolean (*sysctl_set)(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - const char *value); - void (*sysctl_set_async)(NMPlatform * self, - const char * pathid, - int dirfd, - const char * path, - const char *const * values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable * cancellable); - char *(*sysctl_get)(NMPlatform *self, const char *pathid, int dirfd, const char *path); - - void (*refresh_all)(NMPlatform *self, NMPObjectType obj_type); - void (*process_events)(NMPlatform *self); - - int (*link_add)(NMPlatform * self, - NMLinkType type, - const char * name, - int parent, - const void * address, - size_t address_len, - guint32 mtu, - gconstpointer extra_data, - const NMPlatformLink **out_link); - gboolean (*link_delete)(NMPlatform *self, int ifindex); - gboolean (*link_refresh)(NMPlatform *self, int ifindex); - gboolean (*link_set_netns)(NMPlatform *self, int ifindex, int netns_fd); - gboolean (*link_set_up)(NMPlatform *self, int ifindex, gboolean *out_no_firmware); - gboolean (*link_set_down)(NMPlatform *self, int ifindex); - gboolean (*link_set_arp)(NMPlatform *self, int ifindex); - gboolean (*link_set_noarp)(NMPlatform *self, int ifindex); - - int (*link_set_user_ipv6ll_enabled)(NMPlatform *self, int ifindex, gboolean enabled); - gboolean (*link_set_token)(NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); - - gboolean (*link_get_permanent_address)(NMPlatform *self, - int ifindex, - guint8 * buf, - size_t * length); - int (*link_set_address)(NMPlatform *self, int ifindex, gconstpointer address, size_t length); - int (*link_set_mtu)(NMPlatform *self, int ifindex, guint32 mtu); - gboolean (*link_set_name)(NMPlatform *self, int ifindex, const char *name); - void (*link_set_sriov_params_async)(NMPlatform * self, - int ifindex, - guint num_vfs, - NMOptionBool autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data, - GCancellable * cancellable); - gboolean (*link_set_sriov_vfs)(NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs); - gboolean (*link_set_bridge_vlans)(NMPlatform * self, - int ifindex, - gboolean on_master, - const NMPlatformBridgeVlan *const *vlans); - - char *(*link_get_physical_port_id)(NMPlatform *self, int ifindex); - guint (*link_get_dev_id)(NMPlatform *self, int ifindex); - gboolean (*link_get_wake_on_lan)(NMPlatform *self, int ifindex); - gboolean (*link_get_driver_info)(NMPlatform *self, - int ifindex, - char ** out_driver_name, - char ** out_driver_version, - char ** out_fw_version); - - gboolean (*link_supports_carrier_detect)(NMPlatform *self, int ifindex); - gboolean (*link_supports_vlans)(NMPlatform *self, int ifindex); - gboolean (*link_supports_sriov)(NMPlatform *self, int ifindex); - - gboolean (*link_enslave)(NMPlatform *self, int master, int slave); - gboolean (*link_release)(NMPlatform *self, int master, int slave); - - gboolean (*link_can_assume)(NMPlatform *self, int ifindex); - - int (*link_wireguard_change)(NMPlatform * self, - int ifindex, - const NMPlatformLnkWireGuard * lnk_wireguard, - const struct _NMPWireGuardPeer * peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags); - - gboolean (*link_vlan_change)(NMPlatform * self, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map); - gboolean (*link_tun_add)(NMPlatform * self, - const char * name, - const NMPlatformLnkTun *props, - const NMPlatformLink ** out_link, - int * out_fd); - - gboolean (*infiniband_partition_add)(NMPlatform * self, - int parent, - int p_key, - const NMPlatformLink **out_link); - gboolean (*infiniband_partition_delete)(NMPlatform *self, int parent, int p_key); - - gboolean (*wifi_get_capabilities)(NMPlatform * self, - int ifindex, - NMDeviceWifiCapabilities *caps); - gboolean (*wifi_get_station)(NMPlatform * self, - int ifindex, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate); - gboolean (*wifi_get_bssid)(NMPlatform *self, int ifindex, guint8 *bssid); - guint32 (*wifi_get_frequency)(NMPlatform *self, int ifindex); - int (*wifi_get_quality)(NMPlatform *self, int ifindex); - guint32 (*wifi_get_rate)(NMPlatform *self, int ifindex); - NM80211Mode (*wifi_get_mode)(NMPlatform *self, int ifindex); - void (*wifi_set_mode)(NMPlatform *self, int ifindex, NM80211Mode mode); - void (*wifi_set_powersave)(NMPlatform *self, int ifindex, guint32 powersave); - guint32 (*wifi_find_frequency)(NMPlatform *self, int ifindex, const guint32 *freqs); - void (*wifi_indicate_addressing_running)(NMPlatform *self, int ifindex, gboolean running); - NMSettingWirelessWakeOnWLan (*wifi_get_wake_on_wlan)(NMPlatform *self, int ifindex); - gboolean (*wifi_set_wake_on_wlan)(NMPlatform * self, - int ifindex, - NMSettingWirelessWakeOnWLan wowl); - - guint32 (*mesh_get_channel)(NMPlatform *self, int ifindex); - gboolean (*mesh_set_channel)(NMPlatform *self, int ifindex, guint32 channel); - gboolean (*mesh_set_ssid)(NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); - - guint16 (*wpan_get_pan_id)(NMPlatform *self, int ifindex); - gboolean (*wpan_set_pan_id)(NMPlatform *self, int ifindex, guint16 pan_id); - guint16 (*wpan_get_short_addr)(NMPlatform *self, int ifindex); - gboolean (*wpan_set_short_addr)(NMPlatform *self, int ifindex, guint16 short_addr); - gboolean (*wpan_set_channel)(NMPlatform *self, int ifindex, guint8 page, guint8 channel); - - gboolean (*object_delete)(NMPlatform *self, const NMPObject *obj); - - gboolean (*ip4_address_add)(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags, - const char *label); - gboolean (*ip6_address_add)(NMPlatform * self, - int ifindex, - struct in6_addr address, - guint8 plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags); - gboolean (*ip4_address_delete)(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address); - gboolean (*ip6_address_delete)(NMPlatform * self, - int ifindex, - struct in6_addr address, - guint8 plen); - - int (*ip_route_add)(NMPlatform * self, - NMPNlmFlags flags, - int addr_family, - const NMPlatformIPRoute *route); - int (*ip_route_get)(NMPlatform * self, - int addr_family, - gconstpointer address, - int oif_ifindex, - NMPObject ** out_route); - - int (*routing_rule_add)(NMPlatform * self, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule); - - int (*qdisc_add)(NMPlatform *self, NMPNlmFlags flags, const NMPlatformQdisc *qdisc); - - int (*tfilter_add)(NMPlatform *self, NMPNlmFlags flags, const NMPlatformTfilter *tfilter); -} NMPlatformClass; - -/* NMPlatform signals - * - * Each signal handler is called with a type-specific object that provides - * key attributes that constitute identity of the object. They may also - * provide additional attributes for convenience. - * - * The object only intended to be used by the signal handler to determine - * the current values. It is no longer valid after the signal handler exits - * but you are free to copy the provided information and use it for later - * reference. - */ -#define NM_PLATFORM_SIGNAL_LINK_CHANGED "link-changed" -#define NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED "ip4-address-changed" -#define NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED "ip6-address-changed" -#define NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED "ip4-route-changed" -#define NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED "ip6-route-changed" -#define NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED "routing-rule-changed" -#define NM_PLATFORM_SIGNAL_QDISC_CHANGED "qdisc-changed" -#define NM_PLATFORM_SIGNAL_TFILTER_CHANGED "tfilter-changed" - -const char *nm_platform_signal_change_type_to_string(NMPlatformSignalChangeType change_type); - -/*****************************************************************************/ - -GType nm_platform_get_type(void); - -void nm_platform_setup(NMPlatform *instance); -NMPlatform *nm_platform_get(void); - -#define NM_PLATFORM_GET (nm_platform_get()) - -/*****************************************************************************/ - -static inline in_addr_t -nm_platform_ip4_broadcast_address_create(in_addr_t address, guint8 plen) -{ - return address | ~_nm_utils_ip4_prefix_to_netmask(plen); -} - -static inline in_addr_t -nm_platform_ip4_broadcast_address_from_addr(const NMPlatformIP4Address *addr) -{ - nm_assert(addr); - - if (addr->use_ip4_broadcast_address) - return addr->broadcast_address; - - /* the set broadcast-address gets ignored, and we determine a default brd base - * on the peer IFA_ADDRESS. */ - if (addr->peer_address != 0u && addr->plen < 31 /* RFC3021 */) - return nm_platform_ip4_broadcast_address_create(addr->peer_address, addr->plen); - return 0u; -} - -/*****************************************************************************/ - -/** - * nm_platform_route_table_coerce: - * @table: the route table, in its original value as received - * from rtm_table/RTA_TABLE. - * - * Returns: returns the coerced table id, that can be stored in - * NMPlatformIPRoute.table_coerced. - */ -static inline guint32 -nm_platform_route_table_coerce(guint32 table) -{ - /* For kernel, the default table is RT_TABLE_MAIN (254). - * We want that in NMPlatformIPRoute.table_coerced a numeric - * zero is the default. Hence, @table_coerced swaps the - * value 0 and 254. Use nm_platform_route_table_coerce() - * and nm_platform_route_table_uncoerce() to convert between - * the two domains. */ - switch (table) { - case 0 /* RT_TABLE_UNSPEC */: - return 254; - case 254 /* RT_TABLE_MAIN */: - return 0; - default: - return table; - } -} - -/** - * nm_platform_route_table_uncoerce: - * @table_coerced: the route table, in its coerced value - * @normalize: whether to normalize RT_TABLE_UNSPEC to - * RT_TABLE_MAIN. For kernel, routes with a table id - * RT_TABLE_UNSPEC do not exist and are treated like - * RT_TABLE_MAIN. - * - * Returns: reverts the coerced table ID in NMPlatformIPRoute.table_coerced - * to the original value as kernel understands it. - */ -static inline guint32 -nm_platform_route_table_uncoerce(guint32 table_coerced, gboolean normalize) -{ - /* this undoes nm_platform_route_table_coerce(). */ - switch (table_coerced) { - case 0 /* RT_TABLE_UNSPEC */: - return 254; - case 254 /* RT_TABLE_MAIN */: - return normalize ? 254 : 0; - default: - return table_coerced; - } -} - -static inline gboolean -nm_platform_route_table_is_main(guint32 table) -{ - /* same as - * nm_platform_route_table_uncoerce (table, TRUE) == RT_TABLE_MAIN - * and - * nm_platform_route_table_uncoerce (nm_platform_route_table_coerce (table), TRUE) == RT_TABLE_MAIN - * - * That is, the function operates the same on @table and its coerced - * form. - */ - return table == 0 || table == 254; -} - -/** - * nm_platform_route_scope_inv: - * @scope: the route scope, either its original value, or its inverse. - * - * This function is useful, because the constants such as RT_SCOPE_NOWHERE - * are 'int', so ~scope also gives an 'int'. This function gets the type - * casts to guint8 right. - * - * Returns: the bitwise inverse of the route scope. - * */ -#define nm_platform_route_scope_inv _nm_platform_uint8_inv -static inline guint8 -_nm_platform_uint8_inv(guint8 scope) -{ - return (guint8) ~scope; -} - -/** - * nm_platform_route_type_coerce: - * @table: the route type, in its original value. - * - * Returns: returns the coerced type, that can be stored in - * NMPlatformIPRoute.type_coerced. - */ -static inline guint8 -nm_platform_route_type_coerce(guint8 type) -{ - switch (type) { - case 0 /* RTN_UNSPEC */: - return 1; - case 1 /* RTN_UNICAST */: - return 0; - default: - return type; - } -} - -/** - * nm_platform_route_type_uncoerce: - * @table: the type table, in its coerced value - * - * Returns: reverts the coerced type in NMPlatformIPRoute.type_coerced - * to the original value as kernel understands it. - */ -static inline guint8 -nm_platform_route_type_uncoerce(guint8 type_coerced) -{ - return nm_platform_route_type_coerce(type_coerced); -} - -gboolean nm_platform_get_use_udev(NMPlatform *self); -gboolean nm_platform_get_log_with_ptr(NMPlatform *self); - -NMPNetns *nm_platform_netns_get(NMPlatform *self); -gboolean nm_platform_netns_push(NMPlatform *self, NMPNetns **netns); - -const char *nm_link_type_to_string(NMLinkType link_type); - -#define NMP_SYSCTL_PATHID_ABSOLUTE(path) ((const char *) NULL), -1, (path) - -#define NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname, path) \ - nm_sprintf_buf_unsafe_a(NM_STRLEN("net:/sys/class/net//\0") + NMP_IFNAMSIZ + ({ \ - const gsize _l = strlen(path); \ - \ - nm_assert(_l < 200); \ - _l; \ - }), \ - "net:/sys/class/net/%s/%s", \ - (ifname), \ - (path)), \ - (dirfd), (path) - -#define NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, path) \ - nm_sprintf_bufa(NM_STRLEN("net:/sys/class/net//" path "/\0") + NMP_IFNAMSIZ, \ - "net:/sys/class/net/%s/%s", \ - (ifname), \ - path), \ - (dirfd), ("" path "") - -int nm_platform_sysctl_open_netdir(NMPlatform *self, int ifindex, char *out_ifname); -gboolean nm_platform_sysctl_set(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - const char *value); -void nm_platform_sysctl_set_async(NMPlatform * self, - const char * pathid, - int dirfd, - const char * path, - const char *const * values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable * cancellable); -char * nm_platform_sysctl_get(NMPlatform *self, const char *pathid, int dirfd, const char *path); -gint32 nm_platform_sysctl_get_int32(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - gint32 fallback); -gint64 nm_platform_sysctl_get_int_checked(NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - guint base, - gint64 min, - gint64 max, - gint64 fallback); - -char *nm_platform_sysctl_ip_conf_get(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property); - -gint64 nm_platform_sysctl_ip_conf_get_int_checked(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - guint base, - gint64 min, - gint64 max, - gint64 fallback); - -gboolean nm_platform_sysctl_ip_conf_set(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - const char *value); - -gboolean nm_platform_sysctl_ip_conf_set_int64(NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - gint64 value); - -gboolean -nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(NMPlatform *self, const char *iface, int value); -gboolean nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(NMPlatform *self, - const char *iface, - guint value_ms); -gboolean nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(NMPlatform *self, - const char *iface, - guint value_ms); -int nm_platform_sysctl_ip_conf_get_rp_filter_ipv4(NMPlatform *platform, - const char *iface, - gboolean consider_all, - gboolean * out_due_to_all); - -const char *nm_platform_if_indextoname(NMPlatform *self, - int ifindex, - char out_ifname[static 16 /* IFNAMSIZ */]); -int nm_platform_if_nametoindex(NMPlatform *self, const char *ifname); - -const NMPObject *nm_platform_link_get_obj(NMPlatform *self, int ifindex, gboolean visible_only); -const NMPlatformLink *nm_platform_link_get(NMPlatform *self, int ifindex); -const NMPlatformLink *nm_platform_link_get_by_ifname(NMPlatform *self, const char *ifname); -const NMPlatformLink *nm_platform_link_get_by_address(NMPlatform * self, - NMLinkType link_type, - gconstpointer address, - size_t length); - -GPtrArray *nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name); - -int nm_platform_link_add(NMPlatform * self, - NMLinkType type, - const char * name, - int parent, - const void * address, - size_t address_len, - guint32 mtu, - gconstpointer extra_data, - const NMPlatformLink **out_link); - -static inline int -nm_platform_link_veth_add(NMPlatform * self, - const char * name, - const char * peer, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_VETH, name, 0, NULL, 0, 0, peer, out_link); -} - -static inline int -nm_platform_link_dummy_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_DUMMY, name, 0, NULL, 0, 0, NULL, out_link); -} - -static inline int -nm_platform_link_bridge_add(NMPlatform * self, - const char * name, - const void * address, - size_t address_len, - guint32 mtu, - const NMPlatformLnkBridge *props, - const NMPlatformLink ** out_link) -{ - return nm_platform_link_add(self, - NM_LINK_TYPE_BRIDGE, - name, - 0, - address, - address_len, - mtu, - props, - out_link); -} - -static inline int -nm_platform_link_bond_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_BOND, name, 0, NULL, 0, 0, NULL, out_link); -} - -static inline int -nm_platform_link_team_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_TEAM, name, 0, NULL, 0, 0, NULL, out_link); -} - -static inline int -nm_platform_link_wireguard_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_WIREGUARD, name, 0, NULL, 0, 0, NULL, out_link); -} - -static inline int -nm_platform_link_gre_add(NMPlatform * self, - const char * name, - const void * address, - size_t address_len, - const NMPlatformLnkGre *props, - const NMPlatformLink ** out_link) -{ - g_return_val_if_fail(props, -NME_BUG); - - return nm_platform_link_add(self, - props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, - name, - 0, - address, - address_len, - 0, - props, - out_link); -} - -static inline int -nm_platform_link_sit_add(NMPlatform * self, - const char * name, - const NMPlatformLnkSit *props, - const NMPlatformLink ** out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_SIT, name, 0, NULL, 0, 0, props, out_link); -} - -static inline int -nm_platform_link_vlan_add(NMPlatform * self, - const char * name, - int parent, - int vlanid, - guint32 vlanflags, - const NMPlatformLink **out_link) -{ - g_return_val_if_fail(parent >= 0, -NME_BUG); - g_return_val_if_fail(vlanid >= 0, -NME_BUG); - - return nm_platform_link_add(self, - NM_LINK_TYPE_VLAN, - name, - parent, - NULL, - 0, - 0, - &((NMPlatformLnkVlan){ - .id = vlanid, - .flags = vlanflags, - }), - out_link); -} - -static inline int -nm_platform_link_vrf_add(NMPlatform * self, - const char * name, - const NMPlatformLnkVrf *props, - const NMPlatformLink ** out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, 0, props, out_link); -} - -static inline int -nm_platform_link_vxlan_add(NMPlatform * self, - const char * name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink ** out_link) -{ - return nm_platform_link_add(self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, 0, props, out_link); -} - -static inline int -nm_platform_link_6lowpan_add(NMPlatform * self, - const char * name, - int parent, - const NMPlatformLink **out_link) -{ - return nm_platform_link_add(self, - NM_LINK_TYPE_6LOWPAN, - name, - parent, - NULL, - 0, - 0, - NULL, - out_link); -} - -static inline int -nm_platform_link_ip6tnl_add(NMPlatform * self, - const char * name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink ** out_link) -{ - g_return_val_if_fail(props, -NME_BUG); - g_return_val_if_fail(!props->is_gre, -NME_BUG); - - return nm_platform_link_add(self, NM_LINK_TYPE_IP6TNL, name, 0, NULL, 0, 0, props, out_link); -} - -static inline int -nm_platform_link_ip6gre_add(NMPlatform * self, - const char * name, - const void * address, - size_t address_len, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink ** out_link) -{ - g_return_val_if_fail(props, -NME_BUG); - g_return_val_if_fail(props->is_gre, -NME_BUG); - - return nm_platform_link_add(self, - props->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, - name, - 0, - address, - address_len, - 0, - props, - out_link); -} - -static inline int -nm_platform_link_ipip_add(NMPlatform * self, - const char * name, - const NMPlatformLnkIpIp *props, - const NMPlatformLink ** out_link) -{ - g_return_val_if_fail(props, -NME_BUG); - - return nm_platform_link_add(self, NM_LINK_TYPE_IPIP, name, 0, NULL, 0, 0, props, out_link); -} - -static inline int -nm_platform_link_macsec_add(NMPlatform * self, - const char * name, - int parent, - const NMPlatformLnkMacsec *props, - const NMPlatformLink ** out_link) -{ - g_return_val_if_fail(props, -NME_BUG); - g_return_val_if_fail(parent > 0, -NME_BUG); - - return nm_platform_link_add(self, - NM_LINK_TYPE_MACSEC, - name, - parent, - NULL, - 0, - 0, - props, - out_link); -} - -static inline int -nm_platform_link_macvlan_add(NMPlatform * self, - const char * name, - int parent, - const NMPlatformLnkMacvlan *props, - const NMPlatformLink ** out_link) -{ - g_return_val_if_fail(props, -NME_BUG); - g_return_val_if_fail(parent > 0, -NME_BUG); - - return nm_platform_link_add(self, - props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN, - name, - parent, - NULL, - 0, - 0, - props, - out_link); -} - -gboolean nm_platform_link_delete(NMPlatform *self, int ifindex); - -gboolean nm_platform_link_set_netns(NMPlatform *self, int ifindex, int netns_fd); - -struct _NMDedupMultiHeadEntry; -struct _NMPLookup; -const struct _NMDedupMultiHeadEntry *nm_platform_lookup(NMPlatform * self, - const struct _NMPLookup *lookup); - -#define nm_platform_iter_obj_for_each(iter, self, lookup, obj) \ - for (nm_dedup_multi_iter_init((iter), nm_platform_lookup((self), (lookup))); \ - nm_platform_dedup_multi_iter_next_obj((iter), (obj), NMP_OBJECT_TYPE_UNKNOWN);) - -gboolean nm_platform_lookup_predicate_routes_main(const NMPObject *obj, gpointer user_data); -gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel(const NMPObject *obj, - gpointer user_data); - -GPtrArray *nm_platform_lookup_clone(NMPlatform * self, - const struct _NMPLookup *lookup, - NMPObjectPredicateFunc predicate, - gpointer user_data); - -/* convenience methods to lookup the link and access fields of NMPlatformLink. */ -int nm_platform_link_get_ifindex(NMPlatform *self, const char *name); -const char *nm_platform_link_get_name(NMPlatform *self, int ifindex); -NMLinkType nm_platform_link_get_type(NMPlatform *self, int ifindex); -gboolean nm_platform_link_is_software(NMPlatform *self, int ifindex); -int nm_platform_link_get_ifi_flags(NMPlatform *self, int ifindex, guint requested_flags); -gboolean nm_platform_link_is_up(NMPlatform *self, int ifindex); -gboolean nm_platform_link_is_connected(NMPlatform *self, int ifindex); -gboolean nm_platform_link_uses_arp(NMPlatform *self, int ifindex); -guint32 nm_platform_link_get_mtu(NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_user_ipv6ll_enabled(NMPlatform *self, int ifindex); - -gconstpointer nm_platform_link_get_address(NMPlatform *self, int ifindex, size_t *length); - -int nm_platform_link_get_master(NMPlatform *self, int slave); - -gboolean nm_platform_link_can_assume(NMPlatform *self, int ifindex); - -gboolean nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex, gboolean *unmanaged); -gboolean nm_platform_link_supports_slaves(NMPlatform *self, int ifindex); -const char *nm_platform_link_get_type_name(NMPlatform *self, int ifindex); - -gboolean nm_platform_link_refresh(NMPlatform *self, int ifindex); -void nm_platform_process_events(NMPlatform *self); - -const NMPlatformLink * -nm_platform_process_events_ensure_link(NMPlatform *self, int ifindex, const char *ifname); - -gboolean nm_platform_link_set_up(NMPlatform *self, int ifindex, gboolean *out_no_firmware); -gboolean nm_platform_link_set_down(NMPlatform *self, int ifindex); -gboolean nm_platform_link_set_arp(NMPlatform *self, int ifindex); -gboolean nm_platform_link_set_noarp(NMPlatform *self, int ifindex); - -const char *nm_platform_link_get_udi(NMPlatform *self, int ifindex); -const char *nm_platform_link_get_path(NMPlatform *self, int ifindex); - -struct udev_device *nm_platform_link_get_udev_device(NMPlatform *self, int ifindex); - -int nm_platform_link_set_user_ipv6ll_enabled(NMPlatform *self, int ifindex, gboolean enabled); -gboolean nm_platform_link_set_ipv6_token(NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); - -gboolean -nm_platform_link_get_permanent_address(NMPlatform *self, int ifindex, guint8 *buf, size_t *length); -int nm_platform_link_set_address(NMPlatform *self, int ifindex, const void *address, size_t length); -int nm_platform_link_set_mtu(NMPlatform *self, int ifindex, guint32 mtu); -gboolean nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *name); - -void nm_platform_link_set_sriov_params_async(NMPlatform * self, - int ifindex, - guint num_vfs, - NMOptionBool autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data, - GCancellable * cancellable); - -gboolean -nm_platform_link_set_sriov_vfs(NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs); -gboolean nm_platform_link_set_bridge_vlans(NMPlatform * self, - int ifindex, - gboolean on_master, - const NMPlatformBridgeVlan *const *vlans); - -char * nm_platform_link_get_physical_port_id(NMPlatform *self, int ifindex); -guint nm_platform_link_get_dev_id(NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_wake_on_lan(NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_driver_info(NMPlatform *self, - int ifindex, - char ** out_driver_name, - char ** out_driver_version, - char ** out_fw_version); - -gboolean nm_platform_link_supports_carrier_detect(NMPlatform *self, int ifindex); -gboolean nm_platform_link_supports_vlans(NMPlatform *self, int ifindex); -gboolean nm_platform_link_supports_sriov(NMPlatform *self, int ifindex); - -gboolean nm_platform_link_enslave(NMPlatform *self, int master, int slave); -gboolean nm_platform_link_release(NMPlatform *self, int master, int slave); - -gboolean nm_platform_sysctl_master_set_option(NMPlatform *self, - int ifindex, - const char *option, - const char *value); -char * nm_platform_sysctl_master_get_option(NMPlatform *self, int ifindex, const char *option); -gboolean nm_platform_sysctl_slave_set_option(NMPlatform *self, - int ifindex, - const char *option, - const char *value); -char * nm_platform_sysctl_slave_get_option(NMPlatform *self, int ifindex, const char *option); - -const NMPObject *nm_platform_link_get_lnk(NMPlatform * self, - int ifindex, - NMLinkType link_type, - const NMPlatformLink **out_link); -const NMPlatformLnkBridge * -nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkGre * -nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkGre * -nm_platform_link_get_lnk_gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6tnl(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIpIp * -nm_platform_link_get_lnk_ipip(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkInfiniband * -nm_platform_link_get_lnk_infiniband(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIpIp * -nm_platform_link_get_lnk_ipip(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacsec * -nm_platform_link_get_lnk_macsec(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacvlan * -nm_platform_link_get_lnk_macvlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacvlan * -nm_platform_link_get_lnk_macvtap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkSit * -nm_platform_link_get_lnk_sit(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkTun * -nm_platform_link_get_lnk_tun(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkVlan * -nm_platform_link_get_lnk_vlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkVrf * -nm_platform_link_get_lnk_vrf(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkVxlan * -nm_platform_link_get_lnk_vxlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkWireGuard * -nm_platform_link_get_lnk_wireguard(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); - -gboolean nm_platform_link_vlan_set_ingress_map(NMPlatform *self, int ifindex, int from, int to); -gboolean nm_platform_link_vlan_set_egress_map(NMPlatform *self, int ifindex, int from, int to); -gboolean nm_platform_link_vlan_change(NMPlatform * self, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map); - -int nm_platform_link_infiniband_add(NMPlatform * self, - int parent, - int p_key, - const NMPlatformLink **out_link); -int nm_platform_link_infiniband_delete(NMPlatform *self, int parent, int p_key); -gboolean nm_platform_link_infiniband_get_properties(NMPlatform * self, - int ifindex, - int * parent, - int * p_key, - const char **mode); - -gboolean nm_platform_link_veth_get_properties(NMPlatform *self, int ifindex, int *out_peer_ifindex); -gboolean nm_platform_link_tun_get_properties(NMPlatform * self, - int ifindex, - NMPlatformLnkTun *out_properties); - -gboolean -nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps); -guint32 nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex); -gboolean nm_platform_wifi_get_station(NMPlatform * self, - int ifindex, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate); -NM80211Mode nm_platform_wifi_get_mode(NMPlatform *self, int ifindex); -void nm_platform_wifi_set_mode(NMPlatform *self, int ifindex, NM80211Mode mode); -void nm_platform_wifi_set_powersave(NMPlatform *self, int ifindex, guint32 powersave); -guint32 nm_platform_wifi_find_frequency(NMPlatform *self, int ifindex, const guint32 *freqs); -void nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex, gboolean running); -NMSettingWirelessWakeOnWLan nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex); -gboolean -nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl); - -guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex); -gboolean nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel); -gboolean nm_platform_mesh_set_ssid(NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); - -guint16 nm_platform_wpan_get_pan_id(NMPlatform *self, int ifindex); -gboolean nm_platform_wpan_set_pan_id(NMPlatform *self, int ifindex, guint16 pan_id); -guint16 nm_platform_wpan_get_short_addr(NMPlatform *self, int ifindex); -gboolean nm_platform_wpan_set_short_addr(NMPlatform *self, int ifindex, guint16 short_addr); -gboolean nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8 channel); - -void nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen); -const struct in6_addr *nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr); - -const NMPlatformIP4Address *nm_platform_ip4_address_get(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address); - -int nm_platform_link_sit_add(NMPlatform * self, - const char * name, - const NMPlatformLnkSit *props, - const NMPlatformLink ** out_link); -int nm_platform_link_tun_add(NMPlatform * self, - const char * name, - const NMPlatformLnkTun *props, - const NMPlatformLink ** out_link, - int * out_fd); -gboolean nm_platform_link_6lowpan_get_properties(NMPlatform *self, int ifindex, int *out_parent); - -int -nm_platform_link_wireguard_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link); - -int nm_platform_link_wireguard_change(NMPlatform * self, - int ifindex, - const NMPlatformLnkWireGuard * lnk_wireguard, - const struct _NMPWireGuardPeer * peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags); - -const NMPlatformIP6Address * -nm_platform_ip6_address_get(NMPlatform *self, int ifindex, const struct in6_addr *address); - -gboolean nm_platform_object_delete(NMPlatform *self, const NMPObject *route); - -gboolean nm_platform_ip4_address_add(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags, - const char *label); -gboolean nm_platform_ip6_address_add(NMPlatform * self, - int ifindex, - struct in6_addr address, - guint8 plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags); -gboolean nm_platform_ip4_address_delete(NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address); -gboolean -nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen); - -gboolean nm_platform_ip_address_sync(NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray * known_addresses, - GPtrArray * addresses_prune); - -GPtrArray *nm_platform_ip_address_get_prune_list(NMPlatform *self, - int addr_family, - int ifindex, - gboolean exclude_ipv6_temporary_addrs); - -static inline gboolean -_nm_platform_ip_address_sync(NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray * known_addresses, - gboolean full_sync) -{ - gs_unref_ptrarray GPtrArray *addresses_prune = NULL; - - addresses_prune = nm_platform_ip_address_get_prune_list(self, addr_family, ifindex, !full_sync); - return nm_platform_ip_address_sync(self, - addr_family, - ifindex, - known_addresses, - addresses_prune); -} - -static inline gboolean -nm_platform_ip4_address_sync(NMPlatform *self, int ifindex, GPtrArray *known_addresses) -{ - return _nm_platform_ip_address_sync(self, AF_INET, ifindex, known_addresses, TRUE); -} - -static inline gboolean -nm_platform_ip6_address_sync(NMPlatform *self, - int ifindex, - GPtrArray * known_addresses, - gboolean full_sync) -{ - return _nm_platform_ip_address_sync(self, AF_INET6, ifindex, known_addresses, full_sync); -} - -gboolean nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex); - -static inline gconstpointer -nm_platform_ip_address_get_peer_address(int addr_family, const NMPlatformIPAddress *addr) -{ - nm_assert_addr_family(addr_family); - nm_assert(addr); - - if (NM_IS_IPv4(addr_family)) - return &((NMPlatformIP4Address *) addr)->peer_address; - return &((NMPlatformIP6Address *) addr)->peer_address; -} - -void nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route); - -static inline guint32 -nm_platform_ip4_route_get_effective_metric(const NMPlatformIP4Route *r) -{ - nm_assert(r); - - return r->metric_any ? nm_add_clamped_u32(NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, r->metric) - : r->metric; -} - -static inline guint32 -nm_platform_ip6_route_get_effective_metric(const NMPlatformIP6Route *r) -{ - nm_assert(r); - - return r->metric_any ? nm_add_clamped_u32(NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, r->metric) - : r->metric; -} - -static inline guint32 -nm_platform_ip_route_get_effective_table(const NMPlatformIPRoute *r) -{ - nm_assert(r); - nm_assert(!r->table_any || r->table_coerced == 0); - - return r->table_any ? 254u /* RT_TABLE_MAIN */ - : nm_platform_route_table_uncoerce(r->table_coerced, TRUE); -} - -static inline gconstpointer -nm_platform_ip_route_get_gateway(int addr_family, const NMPlatformIPRoute *route) -{ - nm_assert_addr_family(addr_family); - nm_assert(route); - - if (NM_IS_IPv4(addr_family)) - return &((NMPlatformIP4Route *) route)->gateway; - return &((NMPlatformIP6Route *) route)->gateway; -} - -int nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *route); -int nm_platform_ip4_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route); -int nm_platform_ip6_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route); - -GPtrArray *nm_platform_ip_route_get_prune_list(NMPlatform * self, - int addr_family, - int ifindex, - NMIPRouteTableSyncMode route_table_sync); - -gboolean nm_platform_ip_route_sync(NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray * routes, - GPtrArray * routes_prune, - GPtrArray **out_temporary_not_available); - -gboolean nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex); - -int nm_platform_ip_route_get(NMPlatform * self, - int addr_family, - gconstpointer address, - int oif_ifindex, - NMPObject ** out_route); - -int nm_platform_routing_rule_add(NMPlatform * self, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule); - -int nm_platform_qdisc_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformQdisc *qdisc); -gboolean nm_platform_qdisc_sync(NMPlatform *self, int ifindex, GPtrArray *known_qdiscs); - -int nm_platform_tfilter_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformTfilter *tfilter); -gboolean nm_platform_tfilter_sync(NMPlatform *self, int ifindex, GPtrArray *known_tfilters); - -const char *nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len); -const char *nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len); -const char *nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len); -const char * -nm_platform_lnk_infiniband_to_string(const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); -const char *nm_platform_lnk_ip6tnl_to_string(const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); -const char *nm_platform_lnk_ipip_to_string(const NMPlatformLnkIpIp *lnk, char *buf, gsize len); -const char *nm_platform_lnk_macsec_to_string(const NMPlatformLnkMacsec *lnk, char *buf, gsize len); -const char * -nm_platform_lnk_macvlan_to_string(const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); -const char *nm_platform_lnk_sit_to_string(const NMPlatformLnkSit *lnk, char *buf, gsize len); -const char *nm_platform_lnk_tun_to_string(const NMPlatformLnkTun *lnk, char *buf, gsize len); -const char *nm_platform_lnk_vlan_to_string(const NMPlatformLnkVlan *lnk, char *buf, gsize len); -const char *nm_platform_lnk_vrf_to_string(const NMPlatformLnkVrf *lnk, char *buf, gsize len); -const char *nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize len); -const char * -nm_platform_lnk_wireguard_to_string(const NMPlatformLnkWireGuard *lnk, char *buf, gsize len); -const char * -nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len); -const char * -nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len); -const char *nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsize len); -const char *nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsize len); -const char * -nm_platform_routing_rule_to_string(const NMPlatformRoutingRule *routing_rule, char *buf, gsize len); -const char *nm_platform_qdisc_to_string(const NMPlatformQdisc *qdisc, char *buf, gsize len); -const char *nm_platform_tfilter_to_string(const NMPlatformTfilter *tfilter, char *buf, gsize len); -const char *nm_platform_vf_to_string(const NMPlatformVF *vf, char *buf, gsize len); -const char * -nm_platform_bridge_vlan_to_string(const NMPlatformBridgeVlan *vlan, char *buf, gsize len); - -const char *nm_platform_vlan_qos_mapping_to_string(const char * name, - const NMVlanQosMapping *map, - gsize n_map, - char * buf, - gsize len); - -const char * -nm_platform_wireguard_peer_to_string(const struct _NMPWireGuardPeer *peer, char *buf, gsize len); - -int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b); -int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b); -int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); -int nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a, - const NMPlatformLnkInfiniband *b); -int nm_platform_lnk_ip6tnl_cmp(const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); -int nm_platform_lnk_ipip_cmp(const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b); -int nm_platform_lnk_macsec_cmp(const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b); -int nm_platform_lnk_macvlan_cmp(const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); -int nm_platform_lnk_sit_cmp(const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); -int nm_platform_lnk_tun_cmp(const NMPlatformLnkTun *a, const NMPlatformLnkTun *b); -int nm_platform_lnk_vlan_cmp(const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); -int nm_platform_lnk_vrf_cmp(const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b); -int nm_platform_lnk_vxlan_cmp(const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b); -int nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b); -int nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); -int nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b); - -int nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1, - const NMPlatformIP4Address *a2); - -int nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1, - const NMPlatformIP6Address *a2, - gboolean prefer_temp); - -GHashTable *nm_platform_ip4_address_addr_to_hash(NMPlatform *self, int ifindex); - -int nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, - const NMPlatformIP4Route *b, - NMPlatformIPRouteCmpType cmp_type); -int nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, - const NMPlatformIP6Route *b, - NMPlatformIPRouteCmpType cmp_type); - -static inline int -nm_platform_ip4_route_cmp_full(const NMPlatformIP4Route *a, const NMPlatformIP4Route *b) -{ - return nm_platform_ip4_route_cmp(a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL); -} - -static inline int -nm_platform_ip6_route_cmp_full(const NMPlatformIP6Route *a, const NMPlatformIP6Route *b) -{ - return nm_platform_ip6_route_cmp(a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL); -} - -int nm_platform_routing_rule_cmp(const NMPlatformRoutingRule *a, - const NMPlatformRoutingRule *b, - NMPlatformRoutingRuleCmpType cmp_type); - -static inline int -nm_platform_routing_rule_cmp_full(const NMPlatformRoutingRule *a, const NMPlatformRoutingRule *b) -{ - return nm_platform_routing_rule_cmp(a, b, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL); -} - -int nm_platform_qdisc_cmp(const NMPlatformQdisc *a, const NMPlatformQdisc *b); -int nm_platform_qdisc_cmp_full(const NMPlatformQdisc *a, - const NMPlatformQdisc *b, - gboolean compare_handle); -int nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b); - -void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h); -void nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h); -void nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h); -void nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, - NMPlatformIPRouteCmpType cmp_type, - NMHashState * h); -void nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, - NMPlatformIPRouteCmpType cmp_type, - NMHashState * h); -void nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj, - NMPlatformRoutingRuleCmpType cmp_type, - NMHashState * h); -void nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h); -void nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h); -void nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h); -void nm_platform_lnk_ip6tnl_hash_update(const NMPlatformLnkIp6Tnl *obj, NMHashState *h); -void nm_platform_lnk_ipip_hash_update(const NMPlatformLnkIpIp *obj, NMHashState *h); -void nm_platform_lnk_macsec_hash_update(const NMPlatformLnkMacsec *obj, NMHashState *h); -void nm_platform_lnk_macvlan_hash_update(const NMPlatformLnkMacvlan *obj, NMHashState *h); -void nm_platform_lnk_sit_hash_update(const NMPlatformLnkSit *obj, NMHashState *h); -void nm_platform_lnk_tun_hash_update(const NMPlatformLnkTun *obj, NMHashState *h); -void nm_platform_lnk_vlan_hash_update(const NMPlatformLnkVlan *obj, NMHashState *h); -void nm_platform_lnk_vrf_hash_update(const NMPlatformLnkVrf *obj, NMHashState *h); -void nm_platform_lnk_vxlan_hash_update(const NMPlatformLnkVxlan *obj, NMHashState *h); -void nm_platform_lnk_wireguard_hash_update(const NMPlatformLnkWireGuard *obj, NMHashState *h); - -void nm_platform_qdisc_hash_update(const NMPlatformQdisc *obj, NMHashState *h); -void nm_platform_tfilter_hash_update(const NMPlatformTfilter *obj, NMHashState *h); - -#define NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN ((gsize) 162) - -const char *nm_platform_link_flags2str(unsigned flags, char *buf, gsize len); -const char *nm_platform_link_inet6_addrgenmode2str(guint8 mode, char *buf, gsize len); -const char *nm_platform_addr_flags2str(unsigned flags, char *buf, gsize len); -const char *nm_platform_route_scope2str(int scope, char *buf, gsize len); - -int nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); - -gboolean nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, - int ifindex, - _NMSettingWiredWakeOnLan wol, - const char * wol_password); -gboolean nm_platform_ethtool_set_link_settings(NMPlatform * self, - int ifindex, - gboolean autoneg, - guint32 speed, - NMPlatformLinkDuplexType duplex); -gboolean nm_platform_ethtool_get_link_settings(NMPlatform * self, - int ifindex, - gboolean * out_autoneg, - guint32 * out_speed, - NMPlatformLinkDuplexType *out_duplex); - -NMEthtoolFeatureStates *nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex); -gboolean nm_platform_ethtool_set_features( - NMPlatform * self, - int ifindex, - const NMEthtoolFeatureStates *features, - const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */); - -gboolean nm_platform_ethtool_get_link_coalesce(NMPlatform * self, - int ifindex, - NMEthtoolCoalesceState *coalesce); - -gboolean nm_platform_ethtool_set_coalesce(NMPlatform * self, - int ifindex, - const NMEthtoolCoalesceState *coalesce); - -gboolean nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring); - -gboolean -nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring); - -void nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, - int ifindex, - GPtrArray * ip4_dev_route_blacklist); - -struct _NMDedupMultiIndex *nm_platform_get_multi_idx(NMPlatform *self); - -/*****************************************************************************/ - -gboolean nm_platform_ip6_address_match(const NMPlatformIP6Address *addr, - NMPlatformMatchFlags match_flag); - -#endif /* __NETWORKMANAGER_PLATFORM_H__ */ diff --git a/src/core/platform/nmp-object.c b/src/core/platform/nmp-object.c deleted file mode 100644 index 6a26595e..00000000 --- a/src/core/platform/nmp-object.c +++ /dev/null @@ -1,3457 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2015 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nmp-object.h" - -#include -#include -#include -#include - -#include "nm-utils.h" -#include "nm-glib-aux/nm-secret-utils.h" - -#include "nm-core-utils.h" -#include "nm-platform/nm-platform-utils.h" - -#include "wifi/nm-wifi-utils.h" -#include "wpan/nm-wpan-utils.h" - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, obj, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ - const NMPObject *const __obj = (obj); \ - \ - _nm_log(__level, \ - _NMLOG_DOMAIN, \ - 0, \ - NULL, \ - NULL, \ - "nmp-object[%p/%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __obj, \ - (__obj ? NMP_OBJECT_GET_CLASS(__obj)->obj_type_name \ - : "???") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -typedef struct { - NMDedupMultiIdxType parent; - NMPCacheIdType cache_id_type; -} DedupMultiIdxType; - -struct _NMPCache { - /* the cache contains only one hash table for all object types, and similarly - * it contains only one NMMultiIndex. - * This works, because different object types don't ever compare equal and - * because their index ids also don't overlap. - * - * For routes and addresses, the cache contains an address if (and only if) the - * object was reported via netlink. - * For links, the cache contain a link if it was reported by either netlink - * or udev. That means, a link object can be alive, even if it was already - * removed via netlink. - * - * This effectively merges the udev-device cache into the NMPCache. - */ - - NMDedupMultiIndex *multi_idx; - - /* an idx_type entry for each NMP_CACHE_ID_TYPE. Note that NONE (zero) - * is skipped, so the index is shifted by one: idx_type[cache_id_type - 1]. - * - * Don't bother, use _idx_type_get() instead! */ - DedupMultiIdxType idx_types[NMP_CACHE_ID_TYPE_MAX]; - - gboolean use_udev; -}; - -/*****************************************************************************/ - -int -nm_sock_addr_union_cmp(const NMSockAddrUnion *a, const NMSockAddrUnion *b) -{ - nm_assert(!a || NM_IN_SET(a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); - nm_assert(!b || NM_IN_SET(b->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); - - NM_CMP_SELF(a, b); - - NM_CMP_FIELD(a, b, sa.sa_family); - switch (a->sa.sa_family) { - case AF_INET: - NM_CMP_DIRECT(ntohl(a->in.sin_addr.s_addr), ntohl(b->in.sin_addr.s_addr)); - NM_CMP_DIRECT(htons(a->in.sin_port), htons(b->in.sin_port)); - break; - case AF_INET6: - NM_CMP_DIRECT_IN6ADDR(&a->in6.sin6_addr, &b->in6.sin6_addr); - NM_CMP_DIRECT(htons(a->in6.sin6_port), htons(b->in6.sin6_port)); - NM_CMP_FIELD(a, b, in6.sin6_scope_id); - NM_CMP_FIELD(a, b, in6.sin6_flowinfo); - break; - } - return 0; -} - -void -nm_sock_addr_union_hash_update(const NMSockAddrUnion *a, NMHashState *h) -{ - if (!a) { - nm_hash_update_val(h, 1241364739u); - return; - } - - nm_assert(NM_IN_SET(a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); - - switch (a->sa.sa_family) { - case AF_INET: - nm_hash_update_vals(h, a->in.sin_family, a->in.sin_addr.s_addr, a->in.sin_port); - return; - case AF_INET6: - nm_hash_update_vals(h, - a->in6.sin6_family, - a->in6.sin6_addr, - a->in6.sin6_port, - a->in6.sin6_scope_id, - a->in6.sin6_flowinfo); - return; - default: - nm_hash_update_val(h, a->sa.sa_family); - return; - } -} - -/** - * nm_sock_addr_union_cpy: - * @dst: the destination #NMSockAddrUnion. It will always be fully initialized, - * to one of the address families AF_INET, AF_INET6, or AF_UNSPEC (in case of - * error). - * @src: (allow-none): the source buffer with an sockaddr to copy. It may be unaligned in - * memory. If not %NULL, the buffer must be at least large enough to contain - * sa.sa_family, and then, depending on sa.sa_family, it must be large enough - * to hold struct sockaddr_in or struct sockaddr_in6. - * - * @dst will always be fully initialized (including setting all un-used bytes to zero). - */ -void -nm_sock_addr_union_cpy(NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */) -{ - struct sockaddr sa; - gsize src_len; - - nm_assert(dst); - - *dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC; - - if (!src) - return; - - memcpy(&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof(sa.sa_family)); - - if (sa.sa_family == AF_INET) - src_len = sizeof(struct sockaddr_in); - else if (sa.sa_family == AF_INET6) - src_len = sizeof(struct sockaddr_in6); - else - return; - - memcpy(dst, src, src_len); - nm_assert(dst->sa.sa_family == sa.sa_family); -} - -/** - * nm_sock_addr_union_cpy_untrusted: - * @dst: the destination #NMSockAddrUnion. It will always be fully initialized, - * to one of the address families AF_INET, AF_INET6, or AF_UNSPEC (in case of - * error). - * @src: the source buffer with an sockaddr to copy. It may be unaligned in - * memory. - * @src_len: the length of @src in bytes. - * - * The function requires @src_len to be either sizeof(struct sockaddr_in) or sizeof (struct sockaddr_in6). - * If that's the case, then @src will be interpreted as such structure (unaligned), and - * accessed. It will check sa.sa_family to match the expected sizes, and if it does, the - * struct will be copied. - * - * On any failure, @dst will be set to sa.sa_family AF_UNSPEC. - * @dst will always be fully initialized (including setting all un-used bytes to zero). - */ -void -nm_sock_addr_union_cpy_untrusted(NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */, - gsize src_len) -{ - int f_expected; - struct sockaddr sa; - - nm_assert(dst); - - *dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC; - - if (src_len == sizeof(struct sockaddr_in)) - f_expected = AF_INET; - else if (src_len == sizeof(struct sockaddr_in6)) - f_expected = AF_INET6; - else - return; - - memcpy(&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof(sa.sa_family)); - - if (sa.sa_family != f_expected) - return; - - memcpy(dst, src, src_len); - nm_assert(dst->sa.sa_family == sa.sa_family); -} - -const char * -nm_sock_addr_union_to_string(const NMSockAddrUnion *sa, char *buf, gsize len) -{ - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - char s_scope_id[40]; - - if (!nm_utils_to_string_buffer_init_null(sa, &buf, &len)) - return buf; - - /* maybe we should use getnameinfo(), but here implement it ourself. - * - * We want to see the actual bytes for debugging (as we understand them), - * and now what getnameinfo() makes of it. Also, it's simpler this way. */ - - switch (sa->sa.sa_family) { - case AF_INET: - g_snprintf(buf, - len, - "%s:%u", - _nm_utils_inet4_ntop(sa->in.sin_addr.s_addr, s_addr), - (guint) htons(sa->in.sin_port)); - break; - case AF_INET6: - g_snprintf(buf, - len, - "[%s%s]:%u", - _nm_utils_inet6_ntop(&sa->in6.sin6_addr, s_addr), - (sa->in6.sin6_scope_id != 0 - ? nm_sprintf_buf(s_scope_id, "%u", sa->in6.sin6_scope_id) - : ""), - (guint) htons(sa->in6.sin6_port)); - break; - case AF_UNSPEC: - g_snprintf(buf, len, "unspec"); - break; - default: - g_snprintf(buf, len, "{addr-family:%u}", (unsigned) sa->sa.sa_family); - break; - } - - return buf; -} - -/*****************************************************************************/ - -static const NMDedupMultiIdxTypeClass _dedup_multi_idx_type_class; - -static void -_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj, - NMHashState * h) -{ - const NMPObject *o = (NMPObject *) obj; - - nm_assert(idx_type && idx_type->klass == &_dedup_multi_idx_type_class); - nm_assert(NMP_OBJECT_GET_TYPE(o) != NMP_OBJECT_TYPE_UNKNOWN); - - nmp_object_id_hash_update(o, h); -} - -static gboolean -_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj_a, - const NMDedupMultiObj * obj_b) -{ - const NMPObject *o_a = (NMPObject *) obj_a; - const NMPObject *o_b = (NMPObject *) obj_b; - - nm_assert(idx_type && idx_type->klass == &_dedup_multi_idx_type_class); - nm_assert(NMP_OBJECT_GET_TYPE(o_a) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert(NMP_OBJECT_GET_TYPE(o_b) != NMP_OBJECT_TYPE_UNKNOWN); - - return nmp_object_id_equal(o_a, o_b); -} - -static guint -_idx_obj_part(const DedupMultiIdxType *idx_type, - const NMPObject * obj_a, - const NMPObject * obj_b, - NMHashState * h) -{ - NMPObjectType obj_type; - - /* the hash/equals functions are strongly related. So, keep them - * side-by-side and do it all in _idx_obj_part(). */ - - nm_assert(idx_type); - nm_assert(idx_type->parent.klass == &_dedup_multi_idx_type_class); - nm_assert(obj_a); - nm_assert(NMP_OBJECT_GET_TYPE(obj_a) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert(!obj_b || (NMP_OBJECT_GET_TYPE(obj_b) != NMP_OBJECT_TYPE_UNKNOWN)); - nm_assert(!h || !obj_b); - - switch (idx_type->cache_id_type) { - case NMP_CACHE_ID_TYPE_OBJECT_TYPE: - if (obj_b) - return NMP_OBJECT_GET_TYPE(obj_a) == NMP_OBJECT_GET_TYPE(obj_b); - if (h) { - nm_hash_update_vals(h, idx_type->cache_id_type, NMP_OBJECT_GET_TYPE(obj_a)); - } - return 1; - - case NMP_CACHE_ID_TYPE_LINK_BY_IFNAME: - if (NMP_OBJECT_GET_TYPE(obj_a) != NMP_OBJECT_TYPE_LINK) { - /* first check, whether obj_a is suitable for this idx_type. - * If not, return 0 (which is correct for partitionable(), hash() and equal() - * functions. */ - if (h) - nm_hash_update_val(h, obj_a); - return 0; - } - if (obj_b) { - /* we are in equal() mode. Compare obj_b with obj_a. */ - return NMP_OBJECT_GET_TYPE(obj_b) == NMP_OBJECT_TYPE_LINK - && nm_streq(obj_a->link.name, obj_b->link.name); - } - if (h) { - nm_hash_update_val(h, idx_type->cache_id_type); - nm_hash_update_strarr(h, obj_a->link.name); - } - /* just return 1, to indicate that obj_a is partitionable by this idx_type. */ - return 1; - - case NMP_CACHE_ID_TYPE_DEFAULT_ROUTES: - if (!NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_a), - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE) - || !NM_PLATFORM_IP_ROUTE_IS_DEFAULT(&obj_a->ip_route) - || !nmp_object_is_visible(obj_a)) { - if (h) - nm_hash_update_val(h, obj_a); - return 0; - } - if (obj_b) { - return NMP_OBJECT_GET_TYPE(obj_a) == NMP_OBJECT_GET_TYPE(obj_b) - && NM_PLATFORM_IP_ROUTE_IS_DEFAULT(&obj_b->ip_route) - && nmp_object_is_visible(obj_b); - } - if (h) { - nm_hash_update_vals(h, idx_type->cache_id_type, NMP_OBJECT_GET_TYPE(obj_a)); - } - return 1; - - case NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX: - if (!NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_a), - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE, - NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER) - || !nmp_object_is_visible(obj_a)) { - if (h) - nm_hash_update_val(h, obj_a); - return 0; - } - nm_assert(NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_a)->ifindex > 0); - if (obj_b) { - return NMP_OBJECT_GET_TYPE(obj_a) == NMP_OBJECT_GET_TYPE(obj_b) - && NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_a)->ifindex - == NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_b)->ifindex - && nmp_object_is_visible(obj_b); - } - if (h) { - nm_hash_update_vals(h, idx_type->cache_id_type, obj_a->obj_with_ifindex.ifindex); - } - return 1; - - case NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID: - obj_type = NMP_OBJECT_GET_TYPE(obj_a); - if (!NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) - || NMP_OBJECT_CAST_IP_ROUTE(obj_a)->ifindex <= 0) { - if (h) - nm_hash_update_val(h, obj_a); - return 0; - } - if (obj_b) { - return obj_type == NMP_OBJECT_GET_TYPE(obj_b) - && NMP_OBJECT_CAST_IP_ROUTE(obj_b)->ifindex > 0 - && (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE - ? (nm_platform_ip4_route_cmp(&obj_a->ip4_route, - &obj_b->ip4_route, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) - == 0) - : (nm_platform_ip6_route_cmp(&obj_a->ip6_route, - &obj_b->ip6_route, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) - == 0)); - } - if (h) { - nm_hash_update_val(h, idx_type->cache_id_type); - if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) - nm_platform_ip4_route_hash_update(&obj_a->ip4_route, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, - h); - else - nm_platform_ip6_route_hash_update(&obj_a->ip6_route, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, - h); - } - return 1; - - case NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY: - obj_type = NMP_OBJECT_GET_TYPE(obj_a); - /* currently, only routing rules are supported for this cache-id-type. */ - if (obj_type != NMP_OBJECT_TYPE_ROUTING_RULE - || !NM_IN_SET(obj_a->routing_rule.addr_family, AF_INET, AF_INET6)) { - if (h) - nm_hash_update_val(h, obj_a); - return 0; - } - if (obj_b) { - return NMP_OBJECT_GET_TYPE(obj_b) == NMP_OBJECT_TYPE_ROUTING_RULE - && obj_a->routing_rule.addr_family == obj_b->routing_rule.addr_family; - } - if (h) { - nm_hash_update_vals(h, idx_type->cache_id_type, obj_a->routing_rule.addr_family); - } - return 1; - - case NMP_CACHE_ID_TYPE_NONE: - case __NMP_CACHE_ID_TYPE_MAX: - break; - } - nm_assert_not_reached(); - return 0; -} - -static gboolean -_idx_obj_partitionable(const NMDedupMultiIdxType *idx_type, const NMDedupMultiObj *obj) -{ - return _idx_obj_part((DedupMultiIdxType *) idx_type, (NMPObject *) obj, NULL, NULL) != 0; -} - -static void -_idx_obj_partition_hash_update(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj, - NMHashState * h) -{ - _idx_obj_part((DedupMultiIdxType *) idx_type, (NMPObject *) obj, NULL, h); -} - -static gboolean -_idx_obj_partition_equal(const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj * obj_a, - const NMDedupMultiObj * obj_b) -{ - return _idx_obj_part((DedupMultiIdxType *) idx_type, - (NMPObject *) obj_a, - (NMPObject *) obj_b, - NULL); -} - -static const NMDedupMultiIdxTypeClass _dedup_multi_idx_type_class = { - .idx_obj_id_hash_update = _idx_obj_id_hash_update, - .idx_obj_id_equal = _idx_obj_id_equal, - .idx_obj_partitionable = _idx_obj_partitionable, - .idx_obj_partition_hash_update = _idx_obj_partition_hash_update, - .idx_obj_partition_equal = _idx_obj_partition_equal, -}; - -static void -_dedup_multi_idx_type_init(DedupMultiIdxType *idx_type, NMPCacheIdType cache_id_type) -{ - nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &_dedup_multi_idx_type_class); - idx_type->cache_id_type = cache_id_type; -} - -/*****************************************************************************/ - -static void -_vlan_xgress_qos_mappings_hash_update(guint n_map, const NMVlanQosMapping *map, NMHashState *h) -{ - /* ensure no padding. */ - G_STATIC_ASSERT(sizeof(NMVlanQosMapping) == 2 * sizeof(guint32)); - - nm_hash_update_val(h, n_map); - if (n_map) - nm_hash_update(h, map, n_map * sizeof(*map)); -} - -static int -_vlan_xgress_qos_mappings_cmp(guint n_map, - const NMVlanQosMapping *map1, - const NMVlanQosMapping *map2) -{ - guint i; - - for (i = 0; i < n_map; i++) { - if (map1[i].from != map2[i].from) - return map1[i].from < map2[i].from ? -1 : 1; - if (map1[i].to != map2[i].to) - return map1[i].to < map2[i].to ? -1 : 1; - } - return 0; -} - -static void -_vlan_xgress_qos_mappings_cpy(guint * dst_n_map, - NMVlanQosMapping ** dst_map, - guint src_n_map, - const NMVlanQosMapping *src_map) -{ - if (src_n_map == 0) { - nm_clear_g_free(dst_map); - *dst_n_map = 0; - } else if (src_n_map != *dst_n_map - || _vlan_xgress_qos_mappings_cmp(src_n_map, *dst_map, src_map) != 0) { - nm_clear_g_free(dst_map); - *dst_n_map = src_n_map; - if (src_n_map > 0) - *dst_map = nm_memdup(src_map, sizeof(*src_map) * src_n_map); - } -} - -/*****************************************************************************/ - -static void -_wireguard_allowed_ip_hash_update(const NMPWireGuardAllowedIP *ip, NMHashState *h) -{ - nm_hash_update_vals(h, ip->family, ip->mask); - - if (ip->family == AF_INET) - nm_hash_update_val(h, ip->addr.addr4); - else if (ip->family == AF_INET6) - nm_hash_update_val(h, ip->addr.addr6); -} - -static int -_wireguard_allowed_ip_cmp(const NMPWireGuardAllowedIP *a, const NMPWireGuardAllowedIP *b) -{ - NM_CMP_SELF(a, b); - - NM_CMP_FIELD(a, b, family); - NM_CMP_FIELD(a, b, mask); - - if (a->family == AF_INET) - NM_CMP_FIELD(a, b, addr.addr4); - else if (a->family == AF_INET6) - NM_CMP_FIELD_IN6ADDR(a, b, addr.addr6); - - return 0; -} - -static void -_wireguard_peer_hash_update(const NMPWireGuardPeer *peer, NMHashState *h) -{ - guint i; - - nm_hash_update(h, peer->public_key, sizeof(peer->public_key)); - nm_hash_update(h, peer->preshared_key, sizeof(peer->preshared_key)); - nm_hash_update_vals(h, - peer->persistent_keepalive_interval, - peer->allowed_ips_len, - peer->rx_bytes, - peer->tx_bytes, - peer->last_handshake_time.tv_sec, - peer->last_handshake_time.tv_nsec); - - nm_sock_addr_union_hash_update(&peer->endpoint, h); - - for (i = 0; i < peer->allowed_ips_len; i++) - _wireguard_allowed_ip_hash_update(&peer->allowed_ips[i], h); -} - -static int -_wireguard_peer_cmp(const NMPWireGuardPeer *a, const NMPWireGuardPeer *b) -{ - guint i; - - NM_CMP_SELF(a, b); - - NM_CMP_FIELD(a, b, last_handshake_time.tv_sec); - NM_CMP_FIELD(a, b, last_handshake_time.tv_nsec); - NM_CMP_FIELD(a, b, rx_bytes); - NM_CMP_FIELD(a, b, tx_bytes); - NM_CMP_FIELD(a, b, allowed_ips_len); - NM_CMP_FIELD(a, b, persistent_keepalive_interval); - NM_CMP_FIELD(a, b, endpoint.sa.sa_family); - NM_CMP_FIELD_MEMCMP(a, b, public_key); - NM_CMP_FIELD_MEMCMP(a, b, preshared_key); - - NM_CMP_RETURN(nm_sock_addr_union_cmp(&a->endpoint, &b->endpoint)); - - for (i = 0; i < a->allowed_ips_len; i++) { - NM_CMP_RETURN(_wireguard_allowed_ip_cmp(&a->allowed_ips[i], &b->allowed_ips[i])); - } - - return 0; -} - -/*****************************************************************************/ - -static const char * -_link_get_driver(struct udev_device *udevice, const char *kind, int ifindex) -{ - const char *driver = NULL; - - nm_assert(kind == g_intern_string(kind)); - - if (udevice) { - driver = nmp_utils_udev_get_driver(udevice); - if (driver) - return driver; - } - - if (kind) - return kind; - - if (ifindex > 0) { - NMPUtilsEthtoolDriverInfo driver_info; - - if (nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) { - if (driver_info.driver[0]) - return g_intern_string(driver_info.driver); - } - } - - return "unknown"; -} - -void -_nmp_object_fixup_link_udev_fields(NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev) -{ - const char *driver = NULL; - gboolean initialized = FALSE; - NMPObject * obj; - - nm_assert(obj_orig || *obj_new); - nm_assert(obj_new); - nm_assert(!obj_orig || NMP_OBJECT_GET_TYPE(obj_orig) == NMP_OBJECT_TYPE_LINK); - nm_assert(!*obj_new || NMP_OBJECT_GET_TYPE(*obj_new) == NMP_OBJECT_TYPE_LINK); - - obj = *obj_new ?: obj_orig; - - /* The link contains internal fields that are combined by - * properties from netlink and udev. Update those properties */ - - /* When a link is not in netlink, its udev fields don't matter. */ - if (obj->_link.netlink.is_in_netlink) { - driver = _link_get_driver(obj->_link.udev.device, obj->link.kind, obj->link.ifindex); - if (obj->_link.udev.device) - initialized = TRUE; - else if (!use_udev) { - /* If we don't use udev, we immediately mark the link as initialized. - * - * For that, we consult @use_udev argument, that is cached via - * nmp_cache_use_udev_get(). It is on purpose not to test - * for a writable /sys on every call. A minor reason for that is - * performance, but the real reason is reproducibility. - * */ - initialized = TRUE; - } - } - - if (nm_streq0(obj->link.driver, driver) && obj->link.initialized == initialized) - return; - - if (!*obj_new) - obj = *obj_new = nmp_object_clone(obj, FALSE); - - obj->link.driver = driver; - obj->link.initialized = initialized; -} - -static void -_nmp_object_fixup_link_master_connected(NMPObject ** obj_new, - NMPObject * obj_orig, - const NMPCache *cache) -{ - NMPObject *obj; - - nm_assert(obj_orig || *obj_new); - nm_assert(obj_new); - nm_assert(!obj_orig || NMP_OBJECT_GET_TYPE(obj_orig) == NMP_OBJECT_TYPE_LINK); - nm_assert(!*obj_new || NMP_OBJECT_GET_TYPE(*obj_new) == NMP_OBJECT_TYPE_LINK); - - obj = *obj_new ?: obj_orig; - - if (nmp_cache_link_connected_needs_toggle(cache, obj, NULL, NULL)) { - if (!*obj_new) - obj = *obj_new = nmp_object_clone(obj, FALSE); - obj->link.connected = !obj->link.connected; - } -} - -/*****************************************************************************/ - -static void -_vt_cmd_obj_dispose_link(NMPObject *obj) -{ - if (obj->_link.udev.device) { - udev_device_unref(obj->_link.udev.device); - obj->_link.udev.device = NULL; - } - g_clear_object(&obj->_link.ext_data); - nmp_object_unref(obj->_link.netlink.lnk); -} - -static void -_vt_cmd_obj_dispose_lnk_vlan(NMPObject *obj) -{ - g_free((gpointer) obj->_lnk_vlan.ingress_qos_map); - g_free((gpointer) obj->_lnk_vlan.egress_qos_map); -} - -static void -_wireguard_clear(NMPObjectLnkWireGuard *lnk) -{ - guint i; - - nm_explicit_bzero(lnk->_public.private_key, sizeof(lnk->_public.private_key)); - for (i = 0; i < lnk->peers_len; i++) { - NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &lnk->peers[i]; - - nm_explicit_bzero(peer->preshared_key, sizeof(peer->preshared_key)); - } - g_free((gpointer) lnk->peers); - g_free((gpointer) lnk->_allowed_ips_buf); -} - -static void -_vt_cmd_obj_dispose_lnk_wireguard(NMPObject *obj) -{ - _wireguard_clear(&obj->_lnk_wireguard); -} - -static NMPObject * -_nmp_object_new_from_class(const NMPClass *klass) -{ - NMPObject *obj; - - nm_assert(klass); - nm_assert(klass->sizeof_data > 0); - nm_assert(klass->sizeof_public > 0 && klass->sizeof_public <= klass->sizeof_data); - - obj = g_slice_alloc0(klass->sizeof_data + G_STRUCT_OFFSET(NMPObject, object)); - obj->_class = klass; - obj->parent._ref_count = 1; - return obj; -} - -NMPObject * -nmp_object_new(NMPObjectType obj_type, gconstpointer plobj) -{ - const NMPClass *klass = nmp_class_from_type(obj_type); - NMPObject * obj; - - obj = _nmp_object_new_from_class(klass); - if (plobj) - memcpy(&obj->object, plobj, klass->sizeof_public); - return obj; -} - -NMPObject * -nmp_object_new_link(int ifindex) -{ - NMPObject *obj; - - obj = nmp_object_new(NMP_OBJECT_TYPE_LINK, NULL); - obj->link.ifindex = ifindex; - return obj; -} - -/*****************************************************************************/ - -static void -_nmp_object_stackinit_from_class(NMPObject *obj, const NMPClass *klass) -{ - nm_assert(obj); - nm_assert(klass); - - *obj = (NMPObject){ - .parent = - { - .klass = (const NMDedupMultiObjClass *) klass, - ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, - }, - }; -} - -static NMPObject * -_nmp_object_stackinit_from_type(NMPObject *obj, NMPObjectType obj_type) -{ - const NMPClass *klass; - - nm_assert(obj); - klass = nmp_class_from_type(obj_type); - nm_assert(klass); - - *obj = (NMPObject){ - .parent = - { - .klass = (const NMDedupMultiObjClass *) klass, - ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, - }, - }; - return obj; -} - -const NMPObject * -nmp_object_stackinit(NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj) -{ - const NMPClass *klass = nmp_class_from_type(obj_type); - - _nmp_object_stackinit_from_class(obj, klass); - if (plobj) - memcpy(&obj->object, plobj, klass->sizeof_public); - return obj; -} - -const NMPObject * -nmp_object_stackinit_id(NMPObject *obj, const NMPObject *src) -{ - const NMPClass *klass; - - nm_assert(NMP_OBJECT_IS_VALID(src)); - nm_assert(obj); - - klass = NMP_OBJECT_GET_CLASS(src); - _nmp_object_stackinit_from_class(obj, klass); - if (klass->cmd_plobj_id_copy) - klass->cmd_plobj_id_copy(&obj->object, &src->object); - return obj; -} - -const NMPObject * -nmp_object_stackinit_id_link(NMPObject *obj, int ifindex) -{ - _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_LINK); - obj->link.ifindex = ifindex; - return obj; -} - -const NMPObject * -nmp_object_stackinit_id_ip4_address(NMPObject *obj, - int ifindex, - guint32 address, - guint8 plen, - guint32 peer_address) -{ - _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_IP4_ADDRESS); - obj->ip4_address.ifindex = ifindex; - obj->ip4_address.address = address; - obj->ip4_address.plen = plen; - obj->ip4_address.peer_address = peer_address; - return obj; -} - -const NMPObject * -nmp_object_stackinit_id_ip6_address(NMPObject *obj, int ifindex, const struct in6_addr *address) -{ - _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_IP6_ADDRESS); - obj->ip4_address.ifindex = ifindex; - if (address) - obj->ip6_address.address = *address; - return obj; -} - -/*****************************************************************************/ - -const char * -nmp_object_to_string(const NMPObject * obj, - NMPObjectToStringMode to_string_mode, - char * buf, - gsize buf_size) -{ - const NMPClass *klass; - char buf2[sizeof(_nm_utils_to_string_buffer)]; - - if (!nm_utils_to_string_buffer_init_null(obj, &buf, &buf_size)) - return buf; - - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL); - - klass = NMP_OBJECT_GET_CLASS(obj); - - if (klass->cmd_obj_to_string) - return klass->cmd_obj_to_string(obj, to_string_mode, buf, buf_size); - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - if (!klass->cmd_plobj_to_string_id) { - g_snprintf(buf, buf_size, "%p", obj); - return buf; - } - return klass->cmd_plobj_to_string_id(&obj->object, buf, buf_size); - case NMP_OBJECT_TO_STRING_ALL: - g_snprintf( - buf, - buf_size, - "[%s,%p,%u,%calive,%cvisible; %s]", - klass->obj_type_name, - obj, - obj->parent._ref_count, - nmp_object_is_alive(obj) ? '+' : '-', - nmp_object_is_visible(obj) ? '+' : '-', - NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf2, sizeof(buf2))); - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf, buf_size); - return buf; - default: - g_return_val_if_reached("ERROR"); - } -} - -static const char * -_vt_cmd_obj_to_string_link(const NMPObject * obj, - NMPObjectToStringMode to_string_mode, - char * buf, - gsize buf_size) -{ - const NMPClass *klass = NMP_OBJECT_GET_CLASS(obj); - char * b = buf; - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - return klass->cmd_plobj_to_string_id(&obj->object, buf, buf_size); - case NMP_OBJECT_TO_STRING_ALL: - nm_utils_strbuf_append(&b, - &buf_size, - "[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; ", - klass->obj_type_name, - obj, - obj->parent._ref_count, - nmp_object_is_alive(obj) ? '+' : '-', - nmp_object_is_visible(obj) ? '+' : '-', - obj->_link.netlink.is_in_netlink ? '+' : '-', - obj->_link.udev.device); - NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, b, buf_size); - nm_utils_strbuf_seek_end(&b, &buf_size); - if (obj->_link.netlink.lnk) { - nm_utils_strbuf_append_str(&b, &buf_size, "; "); - nmp_object_to_string(obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_ALL, b, buf_size); - nm_utils_strbuf_seek_end(&b, &buf_size); - } - nm_utils_strbuf_append_c(&b, &buf_size, ']'); - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, b, buf_size); - if (obj->_link.netlink.lnk) { - nm_utils_strbuf_seek_end(&b, &buf_size); - nm_utils_strbuf_append_str(&b, &buf_size, "; "); - nmp_object_to_string(obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, b, buf_size); - } - return buf; - default: - g_return_val_if_reached("ERROR"); - } -} - -static const char * -_vt_cmd_obj_to_string_lnk_vlan(const NMPObject * obj, - NMPObjectToStringMode to_string_mode, - char * buf, - gsize buf_size) -{ - const NMPClass *klass; - char buf2[sizeof(_nm_utils_to_string_buffer)]; - char * b; - gsize l; - - klass = NMP_OBJECT_GET_CLASS(obj); - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - g_snprintf(buf, buf_size, "%p", obj); - return buf; - case NMP_OBJECT_TO_STRING_ALL: - - g_snprintf(buf, - buf_size, - "[%s,%p,%u,%calive,%cvisible; %s]", - klass->obj_type_name, - obj, - obj->parent._ref_count, - nmp_object_is_alive(obj) ? '+' : '-', - nmp_object_is_visible(obj) ? '+' : '-', - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof(buf2))); - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf, buf_size); - - b = buf; - l = strlen(b); - b += l; - buf_size -= l; - - if (obj->_lnk_vlan.n_ingress_qos_map) { - nm_platform_vlan_qos_mapping_to_string(" ingress-qos-map", - obj->_lnk_vlan.ingress_qos_map, - obj->_lnk_vlan.n_ingress_qos_map, - b, - buf_size); - l = strlen(b); - b += l; - buf_size -= l; - } - if (obj->_lnk_vlan.n_egress_qos_map) { - nm_platform_vlan_qos_mapping_to_string(" egress-qos-map", - obj->_lnk_vlan.egress_qos_map, - obj->_lnk_vlan.n_egress_qos_map, - b, - buf_size); - l = strlen(b); - b += l; - buf_size -= l; - } - - return buf; - default: - g_return_val_if_reached("ERROR"); - } -} - -static const char * -_vt_cmd_obj_to_string_lnk_wireguard(const NMPObject * obj, - NMPObjectToStringMode to_string_mode, - char * buf, - gsize buf_size) -{ - const NMPClass *klass; - char buf2[sizeof(_nm_utils_to_string_buffer)]; - char * b; - guint i; - - klass = NMP_OBJECT_GET_CLASS(obj); - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - g_snprintf(buf, buf_size, "%p", obj); - return buf; - case NMP_OBJECT_TO_STRING_ALL: - b = buf; - - nm_utils_strbuf_append( - &b, - &buf_size, - "[%s,%p,%u,%calive,%cvisible; %s" - "%s", - klass->obj_type_name, - obj, - obj->parent._ref_count, - nmp_object_is_alive(obj) ? '+' : '-', - nmp_object_is_visible(obj) ? '+' : '-', - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof(buf2)), - obj->_lnk_wireguard.peers_len > 0 ? " peers {" : ""); - - for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) { - const NMPWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i]; - - nm_utils_strbuf_append_str(&b, &buf_size, " { "); - nm_platform_wireguard_peer_to_string(peer, b, buf_size); - nm_utils_strbuf_seek_end(&b, &buf_size); - nm_utils_strbuf_append_str(&b, &buf_size, " }"); - } - if (obj->_lnk_wireguard.peers_len) - nm_utils_strbuf_append_str(&b, &buf_size, " }"); - - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf, buf_size); - - return buf; - default: - g_return_val_if_reached("ERROR"); - } -} - -#define _vt_cmd_plobj_to_string_id(type, plat_type, ...) \ - static const char *_vt_cmd_plobj_to_string_id_##type(const NMPlatformObject *_obj, \ - char * buf, \ - gsize buf_len) \ - { \ - plat_type *const obj = (plat_type *) _obj; \ - _nm_unused char buf1[NM_UTILS_INET_ADDRSTRLEN]; \ - _nm_unused char buf2[NM_UTILS_INET_ADDRSTRLEN]; \ - \ - g_snprintf(buf, buf_len, __VA_ARGS__); \ - return buf; \ - } \ - _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON - -_vt_cmd_plobj_to_string_id(link, NMPlatformLink, "%d", obj->ifindex); - -_vt_cmd_plobj_to_string_id(ip4_address, - NMPlatformIP4Address, - "%d: %s/%d%s%s", - obj->ifindex, - _nm_utils_inet4_ntop(obj->address, buf1), - obj->plen, - obj->peer_address != obj->address ? "," : "", - obj->peer_address != obj->address ? _nm_utils_inet4_ntop( - nm_utils_ip4_address_clear_host_address(obj->peer_address, - obj->plen), - buf2) - : ""); - -_vt_cmd_plobj_to_string_id(ip6_address, - NMPlatformIP6Address, - "%d: %s", - obj->ifindex, - _nm_utils_inet6_ntop(&obj->address, buf1)); - -_vt_cmd_plobj_to_string_id(qdisc, NMPlatformQdisc, "%d: %d", obj->ifindex, obj->parent); - -_vt_cmd_plobj_to_string_id(tfilter, NMPlatformTfilter, "%d: %d", obj->ifindex, obj->parent); - -void -nmp_object_hash_update(const NMPObject *obj, NMHashState *h) -{ - const NMPClass *klass; - - g_return_if_fail(NMP_OBJECT_IS_VALID(obj)); - - klass = NMP_OBJECT_GET_CLASS(obj); - - nm_hash_update_val(h, klass->obj_type); - if (klass->cmd_obj_hash_update) - klass->cmd_obj_hash_update(obj, h); - else if (klass->cmd_plobj_hash_update) - klass->cmd_plobj_hash_update(&obj->object, h); - else - nm_hash_update_val(h, obj); -} - -static void -_vt_cmd_obj_hash_update_link(const NMPObject *obj, NMHashState *h) -{ - nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LINK); - - nm_platform_link_hash_update(&obj->link, h); - nm_hash_update_vals(h, - obj->_link.netlink.is_in_netlink, - obj->_link.wireguard_family_id, - obj->_link.udev.device); - if (obj->_link.netlink.lnk) - nmp_object_hash_update(obj->_link.netlink.lnk, h); -} - -static void -_vt_cmd_obj_hash_update_lnk_vlan(const NMPObject *obj, NMHashState *h) -{ - nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LNK_VLAN); - - nm_platform_lnk_vlan_hash_update(&obj->lnk_vlan, h); - _vlan_xgress_qos_mappings_hash_update(obj->_lnk_vlan.n_ingress_qos_map, - obj->_lnk_vlan.ingress_qos_map, - h); - _vlan_xgress_qos_mappings_hash_update(obj->_lnk_vlan.n_egress_qos_map, - obj->_lnk_vlan.egress_qos_map, - h); -} - -static void -_vt_cmd_obj_hash_update_lnk_wireguard(const NMPObject *obj, NMHashState *h) -{ - guint i; - - nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD); - - nm_platform_lnk_wireguard_hash_update(&obj->lnk_wireguard, h); - - nm_hash_update_val(h, obj->_lnk_wireguard.peers_len); - for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) - _wireguard_peer_hash_update(&obj->_lnk_wireguard.peers[i], h); -} - -int -nmp_object_cmp(const NMPObject *obj1, const NMPObject *obj2) -{ - const NMPClass *klass1, *klass2; - - NM_CMP_SELF(obj1, obj2); - - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj1), -1); - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj2), 1); - - klass1 = NMP_OBJECT_GET_CLASS(obj1); - klass2 = NMP_OBJECT_GET_CLASS(obj2); - - if (klass1 != klass2) { - nm_assert(klass1->obj_type != klass2->obj_type); - return klass1->obj_type < klass2->obj_type ? -1 : 1; - } - - if (klass1->cmd_obj_cmp) - return klass1->cmd_obj_cmp(obj1, obj2); - return klass1->cmd_plobj_cmp(&obj1->object, &obj2->object); -} - -static int -_vt_cmd_obj_cmp_link(const NMPObject *obj1, const NMPObject *obj2) -{ - NM_CMP_RETURN(nm_platform_link_cmp(&obj1->link, &obj2->link)); - NM_CMP_DIRECT(obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink); - NM_CMP_RETURN(nmp_object_cmp(obj1->_link.netlink.lnk, obj2->_link.netlink.lnk)); - NM_CMP_DIRECT(obj1->_link.wireguard_family_id, obj2->_link.wireguard_family_id); - - if (obj1->_link.udev.device != obj2->_link.udev.device) { - if (!obj1->_link.udev.device) - return -1; - if (!obj2->_link.udev.device) - return 1; - - /* Only compare based on pointer values. That is ugly because it's not a - * stable sort order. - * - * Have this check as very last. */ - return (obj1->_link.udev.device < obj2->_link.udev.device) ? -1 : 1; - } - - return 0; -} - -static int -_vt_cmd_obj_cmp_lnk_vlan(const NMPObject *obj1, const NMPObject *obj2) -{ - int c; - - c = nm_platform_lnk_vlan_cmp(&obj1->lnk_vlan, &obj2->lnk_vlan); - if (c) - return c; - - if (obj1->_lnk_vlan.n_ingress_qos_map != obj2->_lnk_vlan.n_ingress_qos_map) - return obj1->_lnk_vlan.n_ingress_qos_map < obj2->_lnk_vlan.n_ingress_qos_map ? -1 : 1; - if (obj1->_lnk_vlan.n_egress_qos_map != obj2->_lnk_vlan.n_egress_qos_map) - return obj1->_lnk_vlan.n_egress_qos_map < obj2->_lnk_vlan.n_egress_qos_map ? -1 : 1; - - c = _vlan_xgress_qos_mappings_cmp(obj1->_lnk_vlan.n_ingress_qos_map, - obj1->_lnk_vlan.ingress_qos_map, - obj2->_lnk_vlan.ingress_qos_map); - if (c) - return c; - c = _vlan_xgress_qos_mappings_cmp(obj1->_lnk_vlan.n_egress_qos_map, - obj1->_lnk_vlan.egress_qos_map, - obj2->_lnk_vlan.egress_qos_map); - - return c; -} - -static int -_vt_cmd_obj_cmp_lnk_wireguard(const NMPObject *obj1, const NMPObject *obj2) -{ - guint i; - - NM_CMP_RETURN(nm_platform_lnk_wireguard_cmp(&obj1->lnk_wireguard, &obj2->lnk_wireguard)); - - NM_CMP_FIELD(obj1, obj2, _lnk_wireguard.peers_len); - - for (i = 0; i < obj1->_lnk_wireguard.peers_len; i++) - NM_CMP_RETURN( - _wireguard_peer_cmp(&obj1->_lnk_wireguard.peers[i], &obj2->_lnk_wireguard.peers[i])); - - return 0; -} - -/* @src is a const object, which is not entirely correct for link types, where - * we increase the ref count for src->_link.udev.device. - * Hence, nmp_object_copy() can violate the const promise of @src. - * */ -void -nmp_object_copy(NMPObject *dst, const NMPObject *src, gboolean id_only) -{ - g_return_if_fail(NMP_OBJECT_IS_VALID(dst)); - g_return_if_fail(NMP_OBJECT_IS_VALID(src)); - g_return_if_fail(!NMP_OBJECT_IS_STACKINIT(dst)); - - if (src != dst) { - const NMPClass *klass = NMP_OBJECT_GET_CLASS(dst); - - 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) - klass->cmd_obj_copy(dst, src); - else - memcpy(&dst->object, &src->object, klass->sizeof_data); - } -} - -static void -_vt_cmd_obj_copy_link(NMPObject *dst, const NMPObject *src) -{ - if (dst->_link.udev.device != src->_link.udev.device) { - if (src->_link.udev.device) - udev_device_ref(src->_link.udev.device); - if (dst->_link.udev.device) - udev_device_unref(dst->_link.udev.device); - dst->_link.udev.device = src->_link.udev.device; - } - if (dst->_link.netlink.lnk != src->_link.netlink.lnk) { - if (src->_link.netlink.lnk) - nmp_object_ref(src->_link.netlink.lnk); - if (dst->_link.netlink.lnk) - nmp_object_unref(dst->_link.netlink.lnk); - dst->_link.netlink.lnk = src->_link.netlink.lnk; - } - if (dst->_link.ext_data != src->_link.ext_data) { - if (dst->_link.ext_data) - g_clear_object(&dst->_link.ext_data); - if (src->_link.ext_data) - dst->_link.ext_data = g_object_ref(src->_link.ext_data); - } - dst->_link = src->_link; -} - -static void -_vt_cmd_obj_copy_lnk_vlan(NMPObject *dst, const NMPObject *src) -{ - dst->lnk_vlan = src->lnk_vlan; - _vlan_xgress_qos_mappings_cpy( - &dst->_lnk_vlan.n_ingress_qos_map, - NM_UNCONST_PPTR(NMVlanQosMapping, &dst->_lnk_vlan.ingress_qos_map), - src->_lnk_vlan.n_ingress_qos_map, - src->_lnk_vlan.ingress_qos_map); - _vlan_xgress_qos_mappings_cpy(&dst->_lnk_vlan.n_egress_qos_map, - NM_UNCONST_PPTR(NMVlanQosMapping, &dst->_lnk_vlan.egress_qos_map), - src->_lnk_vlan.n_egress_qos_map, - src->_lnk_vlan.egress_qos_map); -} - -static void -_vt_cmd_obj_copy_lnk_wireguard(NMPObject *dst, const NMPObject *src) -{ - guint i; - - nm_assert(dst != src); - - _wireguard_clear(&dst->_lnk_wireguard); - - dst->_lnk_wireguard = src->_lnk_wireguard; - - dst->_lnk_wireguard.peers = nm_memdup(dst->_lnk_wireguard.peers, - sizeof(NMPWireGuardPeer) * dst->_lnk_wireguard.peers_len); - dst->_lnk_wireguard._allowed_ips_buf = - nm_memdup(dst->_lnk_wireguard._allowed_ips_buf, - sizeof(NMPWireGuardAllowedIP) * dst->_lnk_wireguard._allowed_ips_buf_len); - - /* all the peers' pointers point into the buffer. They need to be readjusted. */ - for (i = 0; i < dst->_lnk_wireguard.peers_len; i++) { - NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &dst->_lnk_wireguard.peers[i]; - - if (peer->allowed_ips_len == 0) { - nm_assert(!peer->allowed_ips); - continue; - } - nm_assert(dst->_lnk_wireguard._allowed_ips_buf_len > 0); - nm_assert(src->_lnk_wireguard._allowed_ips_buf); - nm_assert(peer->allowed_ips >= src->_lnk_wireguard._allowed_ips_buf); - nm_assert( - &peer->allowed_ips[peer->allowed_ips_len] - <= &src->_lnk_wireguard._allowed_ips_buf[src->_lnk_wireguard._allowed_ips_buf_len]); - - peer->allowed_ips = - &dst->_lnk_wireguard - ._allowed_ips_buf[peer->allowed_ips - src->_lnk_wireguard._allowed_ips_buf]; - } - - nm_assert(nmp_object_equal(src, dst)); -} - -#define _vt_cmd_plobj_id_copy(type, plat_type, cmd) \ - static void _vt_cmd_plobj_id_copy_##type(NMPlatformObject *_dst, const NMPlatformObject *_src) \ - { \ - plat_type *const dst = (plat_type *) _dst; \ - const plat_type *const src = (const plat_type *) _src; \ - { \ - cmd \ - } \ - } \ - _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON - -_vt_cmd_plobj_id_copy(link, NMPlatformLink, { dst->ifindex = src->ifindex; }); - -_vt_cmd_plobj_id_copy(ip4_address, NMPlatformIP4Address, { - dst->ifindex = src->ifindex; - dst->plen = src->plen; - dst->address = src->address; - dst->peer_address = src->peer_address; -}); - -_vt_cmd_plobj_id_copy(ip6_address, NMPlatformIP6Address, { - dst->ifindex = src->ifindex; - dst->address = src->address; -}); - -_vt_cmd_plobj_id_copy(ip4_route, NMPlatformIP4Route, { - *dst = *src; - nm_assert(nm_platform_ip4_route_cmp(dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); -}); - -_vt_cmd_plobj_id_copy(ip6_route, NMPlatformIP6Route, { - *dst = *src; - nm_assert(nm_platform_ip6_route_cmp(dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); -}); - -_vt_cmd_plobj_id_copy(routing_rule, NMPlatformRoutingRule, { - *dst = *src; - nm_assert(nm_platform_routing_rule_cmp(dst, src, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); -}); - -/* Uses internally nmp_object_copy(), hence it also violates the const - * promise for @obj. - * */ -NMPObject * -nmp_object_clone(const NMPObject *obj, gboolean id_only) -{ - NMPObject *dst; - - if (!obj) - return NULL; - - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL); - - dst = _nmp_object_new_from_class(NMP_OBJECT_GET_CLASS(obj)); - nmp_object_copy(dst, obj, id_only); - return dst; -} - -int -nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2) -{ - const NMPClass *klass, *klass2; - - NM_CMP_SELF(obj1, obj2); - - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj1), FALSE); - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj2), FALSE); - - klass = NMP_OBJECT_GET_CLASS(obj1); - nm_assert(!klass->cmd_plobj_id_hash_update == !klass->cmd_plobj_id_cmp); - - klass2 = NMP_OBJECT_GET_CLASS(obj2); - nm_assert(klass); - if (klass != klass2) { - nm_assert(klass2); - NM_CMP_DIRECT(klass->obj_type, klass2->obj_type); - /* resort to pointer comparison */ - NM_CMP_DIRECT_PTR(klass, klass2); - return 0; - } - - if (!klass->cmd_plobj_id_cmp) { - /* the klass doesn't implement ID cmp(). That means, different objects - * never compare equal, but the cmp() according to their pointer value. */ - NM_CMP_DIRECT_PTR(obj1, obj2); - return 0; - } - - return klass->cmd_plobj_id_cmp(&obj1->object, &obj2->object); -} - -#define _vt_cmd_plobj_id_cmp(type, plat_type, cmd) \ - static int _vt_cmd_plobj_id_cmp_##type(const NMPlatformObject *_obj1, \ - const NMPlatformObject *_obj2) \ - { \ - const plat_type *const obj1 = (const plat_type *) _obj1; \ - const plat_type *const obj2 = (const plat_type *) _obj2; \ - \ - NM_CMP_SELF(obj1, obj2); \ - { \ - cmd; \ - } \ - return 0; \ - } \ - _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON - -_vt_cmd_plobj_id_cmp(link, NMPlatformLink, { NM_CMP_FIELD(obj1, obj2, ifindex); }); - -_vt_cmd_plobj_id_cmp(ip4_address, NMPlatformIP4Address, { - NM_CMP_FIELD(obj1, obj2, ifindex); - NM_CMP_FIELD(obj1, obj2, plen); - NM_CMP_FIELD(obj1, obj2, address); - /* for IPv4 addresses, you can add the same local address with differing peer-address - * (IFA_ADDRESS), provided that their net-part differs. */ - NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(obj1->peer_address, obj2->peer_address, obj1->plen); -}); - -_vt_cmd_plobj_id_cmp(ip6_address, NMPlatformIP6Address, { - NM_CMP_FIELD(obj1, obj2, ifindex); - /* for IPv6 addresses, the prefix length is not part of the primary identifier. */ - NM_CMP_FIELD_IN6ADDR(obj1, obj2, address); -}); - -_vt_cmd_plobj_id_cmp(qdisc, NMPlatformQdisc, { - NM_CMP_FIELD(obj1, obj2, ifindex); - NM_CMP_FIELD(obj1, obj2, parent); -}); - -_vt_cmd_plobj_id_cmp(tfilter, NMPlatformTfilter, { - NM_CMP_FIELD(obj1, obj2, ifindex); - NM_CMP_FIELD(obj1, obj2, handle); -}); - -static int -_vt_cmd_plobj_id_cmp_ip4_route(const NMPlatformObject *obj1, const NMPlatformObject *obj2) -{ - return nm_platform_ip4_route_cmp((NMPlatformIP4Route *) obj1, - (NMPlatformIP4Route *) obj2, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID); -} - -static int -_vt_cmd_plobj_id_cmp_ip6_route(const NMPlatformObject *obj1, const NMPlatformObject *obj2) -{ - return nm_platform_ip6_route_cmp((NMPlatformIP6Route *) obj1, - (NMPlatformIP6Route *) obj2, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID); -} - -static int -_vt_cmd_plobj_id_cmp_routing_rule(const NMPlatformObject *obj1, const NMPlatformObject *obj2) -{ - return nm_platform_routing_rule_cmp((NMPlatformRoutingRule *) obj1, - (NMPlatformRoutingRule *) obj2, - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID); -} - -void -nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h) -{ - const NMPClass *klass; - - g_return_if_fail(NMP_OBJECT_IS_VALID(obj)); - - klass = NMP_OBJECT_GET_CLASS(obj); - - nm_assert(!klass->cmd_plobj_id_hash_update == !klass->cmd_plobj_id_cmp); - - if (!klass->cmd_plobj_id_hash_update) { - /* The klass doesn't implement ID compare. It means, to use pointer - * equality. */ - nm_hash_update_val(h, obj); - return; - } - - nm_hash_update_val(h, klass->obj_type); - klass->cmd_plobj_id_hash_update(&obj->object, h); -} - -guint -nmp_object_id_hash(const NMPObject *obj) -{ - NMHashState h; - - if (!obj) - return nm_hash_static(914932607u); - - nm_hash_init(&h, 914932607u); - nmp_object_id_hash_update(obj, &h); - return nm_hash_complete(&h); -} - -#define _vt_cmd_plobj_id_hash_update(type, plat_type, cmd) \ - static void _vt_cmd_plobj_id_hash_update_##type(const NMPlatformObject *_obj, NMHashState *h) \ - { \ - const plat_type *const obj = (const plat_type *) _obj; \ - { \ - cmd; \ - } \ - } \ - _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON - -_vt_cmd_plobj_id_hash_update(link, NMPlatformLink, { nm_hash_update_val(h, obj->ifindex); }); - -_vt_cmd_plobj_id_hash_update(ip4_address, NMPlatformIP4Address, { - nm_hash_update_vals( - h, - obj->ifindex, - obj->plen, - obj->address, - /* for IPv4 we must also consider the net-part of the peer-address (IFA_ADDRESS) */ - nm_utils_ip4_address_clear_host_address(obj->peer_address, obj->plen)); -}); - -_vt_cmd_plobj_id_hash_update(ip6_address, NMPlatformIP6Address, { - nm_hash_update_vals( - h, - obj->ifindex, - /* for IPv6 addresses, the prefix length is not part of the primary identifier. */ - obj->address); -}); - -_vt_cmd_plobj_id_hash_update(ip4_route, NMPlatformIP4Route, { - nm_platform_ip4_route_hash_update(obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, h); -}); - -_vt_cmd_plobj_id_hash_update(ip6_route, NMPlatformIP6Route, { - nm_platform_ip6_route_hash_update(obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, h); -}); - -_vt_cmd_plobj_id_hash_update(routing_rule, NMPlatformRoutingRule, { - nm_platform_routing_rule_hash_update(obj, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, h); -}); - -_vt_cmd_plobj_id_hash_update(qdisc, NMPlatformQdisc, { - nm_hash_update_vals(h, obj->ifindex, obj->parent); -}); - -_vt_cmd_plobj_id_hash_update(tfilter, NMPlatformTfilter, { - nm_hash_update_vals(h, obj->ifindex, obj->handle); -}); - -static void -_vt_cmd_plobj_hash_update_ip4_route(const NMPlatformObject *obj, NMHashState *h) -{ - return nm_platform_ip4_route_hash_update((const NMPlatformIP4Route *) obj, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, - h); -} - -static void -_vt_cmd_plobj_hash_update_ip6_route(const NMPlatformObject *obj, NMHashState *h) -{ - return nm_platform_ip6_route_hash_update((const NMPlatformIP6Route *) obj, - NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, - h); -} - -static void -_vt_cmd_plobj_hash_update_routing_rule(const NMPlatformObject *obj, NMHashState *h) -{ - return nm_platform_routing_rule_hash_update((const NMPlatformRoutingRule *) obj, - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL, - h); -} - -guint -nmp_object_indirect_id_hash(gconstpointer a) -{ - const NMPObject *const *p_obj = a; - - return nmp_object_id_hash(*p_obj); -} - -gboolean -nmp_object_indirect_id_equal(gconstpointer a, gconstpointer b) -{ - const NMPObject *const *p_obj_a = a; - const NMPObject *const *p_obj_b = b; - - return nmp_object_id_equal(*p_obj_a, *p_obj_b); -} - -/*****************************************************************************/ - -gboolean -nmp_object_is_alive(const NMPObject *obj) -{ - const NMPClass *klass; - - /* for convenience, allow NULL. */ - if (!obj) - return FALSE; - - klass = NMP_OBJECT_GET_CLASS(obj); - return !klass->cmd_obj_is_alive || klass->cmd_obj_is_alive(obj); -} - -static gboolean -_vt_cmd_obj_is_alive_link(const NMPObject *obj) -{ - return NMP_OBJECT_CAST_LINK(obj)->ifindex > 0 - && (obj->_link.netlink.is_in_netlink || obj->_link.udev.device); -} - -static gboolean -_vt_cmd_obj_is_alive_ipx_address(const NMPObject *obj) -{ - return NMP_OBJECT_CAST_IP_ADDRESS(obj)->ifindex > 0; -} - -static gboolean -_vt_cmd_obj_is_alive_ipx_route(const NMPObject *obj) -{ - /* We want to ignore routes that are RTM_F_CLONED but we still - * let nmp_object_from_nl() create such route objects, instead of - * returning NULL right away. - * - * The idea is, that if we have the same route (according to its id) - * in the cache with !RTM_F_CLONED, an update that changes the route - * to be RTM_F_CLONED must remove the instance. - * - * If nmp_object_from_nl() would just return NULL, we couldn't look - * into the cache to see if it contains a route that now disappears - * (because it changed to be cloned). - * - * Instead we create a dead object, and nmp_cache_update_netlink() - * will remove the old version of the update. - **/ - return NMP_OBJECT_CAST_IP_ROUTE(obj)->ifindex > 0 - && !NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, RTM_F_CLONED); -} - -static gboolean -_vt_cmd_obj_is_alive_routing_rule(const NMPObject *obj) -{ - return NM_IN_SET(obj->routing_rule.addr_family, AF_INET, AF_INET6); -} - -static gboolean -_vt_cmd_obj_is_alive_qdisc(const NMPObject *obj) -{ - return NMP_OBJECT_CAST_QDISC(obj)->ifindex > 0; -} - -static gboolean -_vt_cmd_obj_is_alive_tfilter(const NMPObject *obj) -{ - return NMP_OBJECT_CAST_TFILTER(obj)->ifindex > 0; -} - -gboolean -nmp_object_is_visible(const NMPObject *obj) -{ - const NMPClass *klass; - - /* for convenience, allow NULL. */ - if (!obj) - return FALSE; - - klass = NMP_OBJECT_GET_CLASS(obj); - - /* a dead object is never visible. */ - if (klass->cmd_obj_is_alive && !klass->cmd_obj_is_alive(obj)) - return FALSE; - - return !klass->cmd_obj_is_visible || klass->cmd_obj_is_visible(obj); -} - -static gboolean -_vt_cmd_obj_is_visible_link(const NMPObject *obj) -{ - return obj->_link.netlink.is_in_netlink && obj->link.name[0]; -} - -/*****************************************************************************/ - -static const guint8 _supported_cache_ids_object[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - 0, -}; - -static const guint8 _supported_cache_ids_link[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, - 0, -}; - -static const guint8 _supported_cache_ids_ipx_address[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - 0, -}; - -static const guint8 _supported_cache_ids_ipx_route[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - NMP_CACHE_ID_TYPE_DEFAULT_ROUTES, - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - 0, -}; - -static const guint8 _supported_cache_ids_routing_rules[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY, - 0, -}; - -/*****************************************************************************/ - -static void -_vt_dedup_obj_destroy(NMDedupMultiObj *obj) -{ - NMPObject * o = (NMPObject *) obj; - const NMPClass *klass; - - nm_assert(o->parent._ref_count == 0); - nm_assert(!o->parent._multi_idx); - - klass = o->_class; - if (klass->cmd_obj_dispose) - klass->cmd_obj_dispose(o); - g_slice_free1(klass->sizeof_data + G_STRUCT_OFFSET(NMPObject, object), o); -} - -static const NMDedupMultiObj * -_vt_dedup_obj_clone(const NMDedupMultiObj *obj) -{ - return (const NMDedupMultiObj *) nmp_object_clone((const NMPObject *) obj, FALSE); -} - -#define DEDUP_MULTI_OBJ_CLASS_INIT() \ - { \ - .obj_clone = _vt_dedup_obj_clone, .obj_destroy = _vt_dedup_obj_destroy, \ - .obj_full_hash_update = \ - (void (*)(const NMDedupMultiObj *obj, NMHashState *h)) nmp_object_hash_update, \ - .obj_full_equal = (gboolean(*)(const NMDedupMultiObj *obj_a, \ - const NMDedupMultiObj *obj_b)) nmp_object_equal, \ - } - -/*****************************************************************************/ - -static NMDedupMultiIdxType * -_idx_type_get(const NMPCache *cache, NMPCacheIdType cache_id_type) -{ - nm_assert(cache); - nm_assert(cache_id_type > NMP_CACHE_ID_TYPE_NONE); - nm_assert(cache_id_type <= NMP_CACHE_ID_TYPE_MAX); - nm_assert((int) cache_id_type - 1 >= 0); - nm_assert((int) cache_id_type - 1 < G_N_ELEMENTS(cache->idx_types)); - - return (NMDedupMultiIdxType *) &cache->idx_types[cache_id_type - 1]; -} - -gboolean -nmp_cache_use_udev_get(const NMPCache *cache) -{ - g_return_val_if_fail(cache, TRUE); - - return cache->use_udev; -} - -/*****************************************************************************/ - -gboolean -nmp_cache_link_connected_for_slave(int ifindex_master, const NMPObject *slave) -{ - nm_assert(NMP_OBJECT_GET_TYPE(slave) == NMP_OBJECT_TYPE_LINK); - - return ifindex_master > 0 && slave->link.master == ifindex_master && slave->link.connected - && nmp_object_is_visible(slave); -} - -/** - * nmp_cache_link_connected_needs_toggle: - * @cache: the platform cache - * @master: the link object, that is checked whether its connected property - * needs to be toggled. - * @potential_slave: (allow-none): an additional link object that is treated - * as if it was inside @cache. If given, it shaddows a link in the cache - * with the same ifindex. - * @ignore_slave: (allow-none): if set, the check will pretend that @ignore_slave - * is not in the cache. - * - * NMPlatformLink has two connected flags: (master->link.flags&IFF_LOWER_UP) (as reported - * from netlink) and master->link.connected. For bond and bridge master, kernel reports - * those links as IFF_LOWER_UP if they have no slaves attached. We want to present instead - * a combined @connected flag that shows masters without slaves as down. - * - * Check if the connected flag of @master should be toggled according to the content - * of @cache (including @potential_slave). - * - * Returns: %TRUE, if @master->link.connected should be flipped/toggled. - **/ -gboolean -nmp_cache_link_connected_needs_toggle(const NMPCache * cache, - const NMPObject *master, - const NMPObject *potential_slave, - const NMPObject *ignore_slave) -{ - gboolean is_lower_up = FALSE; - - if (!master || NMP_OBJECT_GET_TYPE(master) != NMP_OBJECT_TYPE_LINK || master->link.ifindex <= 0 - || !nmp_object_is_visible(master) - || !NM_IN_SET(master->link.type, NM_LINK_TYPE_BRIDGE, NM_LINK_TYPE_BOND)) - return FALSE; - - /* if native IFF_LOWER_UP is down, link.connected must also be down - * regardless of the slaves. */ - if (!NM_FLAGS_HAS(master->link.n_ifi_flags, IFF_LOWER_UP)) - return !!master->link.connected; - - if (potential_slave && NMP_OBJECT_GET_TYPE(potential_slave) != NMP_OBJECT_TYPE_LINK) - potential_slave = NULL; - - if (potential_slave - && nmp_cache_link_connected_for_slave(master->link.ifindex, potential_slave)) - is_lower_up = TRUE; - else { - NMPLookup lookup; - NMDedupMultiIter iter; - const NMPlatformLink *link = NULL; - - nmp_cache_iter_for_each_link ( - &iter, - nmp_cache_lookup(cache, nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK)), - &link) { - const NMPObject *obj = NMP_OBJECT_UP_CAST((NMPlatformObject *) link); - - if ((!potential_slave || potential_slave->link.ifindex != link->ifindex) - && ignore_slave != obj - && nmp_cache_link_connected_for_slave(master->link.ifindex, obj)) { - is_lower_up = TRUE; - break; - } - } - } - return !!master->link.connected != is_lower_up; -} - -/** - * nmp_cache_link_connected_needs_toggle_by_ifindex: - * @cache: - * @master_ifindex: the ifindex of a potential master that should be checked - * whether it needs toggling. - * @potential_slave: (allow-none): passed to nmp_cache_link_connected_needs_toggle(). - * It considers @potential_slave as being inside the cache, replacing an existing - * link with the same ifindex. - * @ignore_slave: (allow-onne): passed to nmp_cache_link_connected_needs_toggle(). - * - * The flag obj->link.connected depends on the state of other links in the - * @cache. See also nmp_cache_link_connected_needs_toggle(). Given an ifindex - * of a master, check if the cache contains such a master link that needs - * toggling of the connected flag. - * - * Returns: NULL if there is no master link with ifindex @master_ifindex that should be toggled. - * Otherwise, return the link object from inside the cache with the given ifindex. - * The connected flag of that master should be toggled. - */ -const NMPObject * -nmp_cache_link_connected_needs_toggle_by_ifindex(const NMPCache * cache, - int master_ifindex, - const NMPObject *potential_slave, - const NMPObject *ignore_slave) -{ - const NMPObject *master; - - if (master_ifindex > 0) { - master = nmp_cache_lookup_link(cache, master_ifindex); - if (nmp_cache_link_connected_needs_toggle(cache, master, potential_slave, ignore_slave)) - return master; - } - return NULL; -} - -/*****************************************************************************/ - -static const NMDedupMultiEntry * -_lookup_entry_with_idx_type(const NMPCache * cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj) -{ - const NMDedupMultiEntry *entry; - - nm_assert(cache); - nm_assert(NMP_OBJECT_IS_VALID(obj)); - - entry = - nm_dedup_multi_index_lookup_obj(cache->multi_idx, _idx_type_get(cache, cache_id_type), obj); - nm_assert(!entry - || (NMP_OBJECT_IS_VALID(entry->obj) - && NMP_OBJECT_GET_CLASS(entry->obj) == NMP_OBJECT_GET_CLASS(obj))); - return entry; -} - -static const NMDedupMultiEntry * -_lookup_entry(const NMPCache *cache, const NMPObject *obj) -{ - return _lookup_entry_with_idx_type(cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj); -} - -const NMDedupMultiEntry * -nmp_cache_lookup_entry_with_idx_type(const NMPCache * cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj) -{ - g_return_val_if_fail(cache, NULL); - g_return_val_if_fail(obj, NULL); - g_return_val_if_fail(cache_id_type > NMP_CACHE_ID_TYPE_NONE - && cache_id_type <= NMP_CACHE_ID_TYPE_MAX, - NULL); - - return _lookup_entry_with_idx_type(cache, cache_id_type, obj); -} - -const NMDedupMultiEntry * -nmp_cache_lookup_entry(const NMPCache *cache, const NMPObject *obj) -{ - g_return_val_if_fail(cache, NULL); - g_return_val_if_fail(obj, NULL); - - return _lookup_entry(cache, obj); -} - -const NMDedupMultiEntry * -nmp_cache_lookup_entry_link(const NMPCache *cache, int ifindex) -{ - NMPObject obj_needle; - - g_return_val_if_fail(cache, NULL); - g_return_val_if_fail(ifindex > 0, NULL); - - nmp_object_stackinit_id_link(&obj_needle, ifindex); - return _lookup_entry(cache, &obj_needle); -} - -const NMPObject * -nmp_cache_lookup_obj(const NMPCache *cache, const NMPObject *obj) -{ - return nm_dedup_multi_entry_get_obj(nmp_cache_lookup_entry(cache, obj)); -} - -const NMPObject * -nmp_cache_lookup_link(const NMPCache *cache, int ifindex) -{ - return nm_dedup_multi_entry_get_obj(nmp_cache_lookup_entry_link(cache, ifindex)); -} - -/*****************************************************************************/ - -const NMDedupMultiHeadEntry * -nmp_cache_lookup_all(const NMPCache * cache, - NMPCacheIdType cache_id_type, - const NMPObject *select_obj) -{ - nm_assert(cache); - nm_assert(NMP_OBJECT_IS_VALID(select_obj)); - - return nm_dedup_multi_index_lookup_head(cache->multi_idx, - _idx_type_get(cache, cache_id_type), - select_obj); -} - -static const NMPLookup * -_L(const NMPLookup *lookup) -{ -#if NM_MORE_ASSERTS - DedupMultiIdxType idx_type; - - nm_assert(lookup); - _dedup_multi_idx_type_init(&idx_type, lookup->cache_id_type); - nm_assert( - idx_type.parent.klass->idx_obj_partitionable((NMDedupMultiIdxType *) &idx_type, - (NMDedupMultiObj *) &lookup->selector_obj)); -#endif - return lookup; -} - -const NMPLookup * -nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type) -{ - nm_assert(lookup); - - switch (obj_type) { - case NMP_OBJECT_TYPE_LINK: - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - case NMP_OBJECT_TYPE_ROUTING_RULE: - case NMP_OBJECT_TYPE_QDISC: - case NMP_OBJECT_TYPE_TFILTER: - _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); - lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_TYPE; - return _L(lookup); - default: - nm_assert_not_reached(); - return NULL; - } -} - -const NMPLookup * -nmp_lookup_init_link_by_ifname(NMPLookup *lookup, const char *ifname) -{ - NMPObject *o; - - nm_assert(lookup); - nm_assert(ifname); - nm_assert(strlen(ifname) < IFNAMSIZ); - - o = _nmp_object_stackinit_from_type(&lookup->selector_obj, NMP_OBJECT_TYPE_LINK); - if (g_strlcpy(o->link.name, ifname, sizeof(o->link.name)) >= sizeof(o->link.name)) - g_return_val_if_reached(NULL); - lookup->cache_id_type = NMP_CACHE_ID_TYPE_LINK_BY_IFNAME; - return _L(lookup); -} - -const NMPLookup * -nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex) -{ - NMPObject *o; - - nm_assert(lookup); - nm_assert(NM_IN_SET(obj_type, - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE, - NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER)); - - if (ifindex <= 0) { - return nmp_lookup_init_obj_type(lookup, obj_type); - } - - o = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); - o->obj_with_ifindex.ifindex = ifindex; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX; - return _L(lookup); -} - -const NMPLookup * -nmp_lookup_init_route_default(NMPLookup *lookup, NMPObjectType obj_type) -{ - NMPObject *o; - - nm_assert(lookup); - nm_assert(NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - - o = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); - o->ip_route.ifindex = 1; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_DEFAULT_ROUTES; - return _L(lookup); -} - -const NMPLookup * -nmp_lookup_init_route_by_weak_id(NMPLookup *lookup, const NMPObject *obj) -{ - const NMPlatformIP4Route *r4; - const NMPlatformIP6Route *r6; - - nm_assert(lookup); - - switch (NMP_OBJECT_GET_TYPE(obj)) { - case NMP_OBJECT_TYPE_IP4_ROUTE: - r4 = NMP_OBJECT_CAST_IP4_ROUTE(obj); - return nmp_lookup_init_ip4_route_by_weak_id(lookup, - r4->network, - r4->plen, - r4->metric, - r4->tos); - case NMP_OBJECT_TYPE_IP6_ROUTE: - r6 = NMP_OBJECT_CAST_IP6_ROUTE(obj); - return nmp_lookup_init_ip6_route_by_weak_id(lookup, - &r6->network, - r6->plen, - r6->metric, - &r6->src, - r6->src_plen); - default: - nm_assert_not_reached(); - return NULL; - } -} - -const NMPLookup * -nmp_lookup_init_ip4_route_by_weak_id(NMPLookup *lookup, - in_addr_t network, - guint plen, - guint32 metric, - guint8 tos) -{ - NMPObject *o; - - nm_assert(lookup); - - o = _nmp_object_stackinit_from_type(&lookup->selector_obj, NMP_OBJECT_TYPE_IP4_ROUTE); - o->ip4_route.ifindex = 1; - o->ip4_route.plen = plen; - o->ip4_route.metric = metric; - if (network) - o->ip4_route.network = network; - o->ip4_route.tos = tos; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID; - return _L(lookup); -} - -const NMPLookup * -nmp_lookup_init_ip6_route_by_weak_id(NMPLookup * lookup, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen) -{ - NMPObject *o; - - nm_assert(lookup); - - o = _nmp_object_stackinit_from_type(&lookup->selector_obj, NMP_OBJECT_TYPE_IP6_ROUTE); - o->ip6_route.ifindex = 1; - o->ip6_route.plen = plen; - o->ip6_route.metric = metric; - if (network) - o->ip6_route.network = *network; - if (src) - o->ip6_route.src = *src; - o->ip6_route.src_plen = src_plen; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID; - return _L(lookup); -} - -const NMPLookup * -nmp_lookup_init_object_by_addr_family(NMPLookup *lookup, NMPObjectType obj_type, int addr_family) -{ - NMPObject *o; - - nm_assert(lookup); - nm_assert(NM_IN_SET(obj_type, NMP_OBJECT_TYPE_ROUTING_RULE)); - - if (addr_family == AF_UNSPEC) - return nmp_lookup_init_obj_type(lookup, obj_type); - - nm_assert_addr_family(addr_family); - o = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); - NMP_OBJECT_CAST_ROUTING_RULE(o)->addr_family = addr_family; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY; - return _L(lookup); -} - -/*****************************************************************************/ - -GArray * -nmp_cache_lookup_to_array(const NMDedupMultiHeadEntry *head_entry, - NMPObjectType obj_type, - gboolean visible_only) -{ - const NMPClass * klass = nmp_class_from_type(obj_type); - NMDedupMultiIter iter; - const NMPObject *o; - GArray * array; - - g_return_val_if_fail(klass, NULL); - - array = g_array_sized_new(FALSE, FALSE, klass->sizeof_public, head_entry ? head_entry->len : 0); - nmp_cache_iter_for_each (&iter, head_entry, &o) { - nm_assert(NMP_OBJECT_GET_CLASS(o) == klass); - if (visible_only && !nmp_object_is_visible(o)) - continue; - g_array_append_vals(array, &o->object, 1); - } - return array; -} - -/*****************************************************************************/ - -const NMPObject * -nmp_cache_lookup_link_full(const NMPCache * cache, - int ifindex, - const char * ifname, - gboolean visible_only, - NMLinkType link_type, - NMPObjectMatchFn match_fn, - gpointer user_data) -{ - NMPObject obj_needle; - const NMPObject * obj; - NMDedupMultiIter iter; - const NMDedupMultiHeadEntry *head_entry; - const NMPlatformLink * link = NULL; - NMPLookup lookup; - - if (ifindex > 0) { - obj = nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&obj_needle, ifindex)); - - if (!obj || (visible_only && !nmp_object_is_visible(obj)) - || (link_type != NM_LINK_TYPE_NONE && obj->link.type != link_type) - || (ifname && strcmp(obj->link.name, ifname)) - || (match_fn && !match_fn(obj, user_data))) - return NULL; - return obj; - } else if (!ifname && !match_fn) - return NULL; - else { - const NMPObject *obj_best = NULL; - - if (ifname) { - if (strlen(ifname) >= IFNAMSIZ) - return NULL; - nmp_lookup_init_link_by_ifname(&lookup, ifname); - } else - nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); - - head_entry = nmp_cache_lookup(cache, &lookup); - nmp_cache_iter_for_each_link (&iter, head_entry, &link) { - obj = NMP_OBJECT_UP_CAST(link); - - if (link_type != NM_LINK_TYPE_NONE && obj->link.type != link_type) - continue; - if (visible_only && !nmp_object_is_visible(obj)) - continue; - if (match_fn && !match_fn(obj, user_data)) - continue; - - /* if there are multiple candidates, prefer the visible ones. */ - if (visible_only || nmp_object_is_visible(obj)) - return obj; - if (!obj_best) - obj_best = obj; - } - return obj_best; - } -} - -/*****************************************************************************/ - -static NMDedupMultiIdxMode -_obj_get_add_mode(const NMPObject *obj) -{ - /* new objects are usually appended to the list. Except for - * addresses, which are prepended during `ip address add`. - * - * Actually, for routes it is more complicated, because depending on - * `ip route append`, `ip route replace`, `ip route prepend`, the object - * will be added at the tail, at the front, or even replace an element - * in the list. However, that is handled separately by nmp_cache_update_netlink_route() - * and of no concern here. */ - if (NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS)) - return NM_DEDUP_MULTI_IDX_MODE_PREPEND; - return NM_DEDUP_MULTI_IDX_MODE_APPEND; -} - -static void -_idxcache_update_order_for_dump(NMPCache *cache, const NMDedupMultiEntry *entry) -{ - const NMPClass * klass; - const guint8 * i_idx_type; - const NMDedupMultiEntry *entry2; - - nm_dedup_multi_entry_reorder(entry, NULL, TRUE); - - klass = NMP_OBJECT_GET_CLASS(entry->obj); - for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) { - NMPCacheIdType id_type = *i_idx_type; - - if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) - continue; - - entry2 = nm_dedup_multi_index_lookup_obj(cache->multi_idx, - _idx_type_get(cache, id_type), - entry->obj); - if (!entry2) - continue; - - nm_assert(entry2 != entry); - nm_assert(entry2->obj == entry->obj); - - nm_dedup_multi_entry_reorder(entry2, NULL, TRUE); - } -} - -static void -_idxcache_update_other_cache_ids(NMPCache * cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj_old, - const NMPObject *obj_new, - gboolean is_dump) -{ - const NMDedupMultiEntry *entry_new; - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_order; - NMDedupMultiIdxType * idx_type; - - nm_assert(obj_new || obj_old); - nm_assert(!obj_new || NMP_OBJECT_GET_TYPE(obj_new) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert(!obj_old || NMP_OBJECT_GET_TYPE(obj_old) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert(!obj_old || !obj_new - || NMP_OBJECT_GET_CLASS(obj_new) == NMP_OBJECT_GET_CLASS(obj_old)); - nm_assert(!obj_old || !obj_new || !nmp_object_equal(obj_new, obj_old)); - nm_assert(!obj_new || obj_new == nm_dedup_multi_index_obj_find(cache->multi_idx, obj_new)); - nm_assert(!obj_old || obj_old == nm_dedup_multi_index_obj_find(cache->multi_idx, obj_old)); - - idx_type = _idx_type_get(cache, cache_id_type); - - if (obj_old) { - entry_old = nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type, obj_old); - if (!obj_new) { - if (entry_old) - nm_dedup_multi_index_remove_entry(cache->multi_idx, entry_old); - return; - } - } else - entry_old = NULL; - - if (obj_new) { - if (obj_old && nm_dedup_multi_idx_type_id_equal(idx_type, obj_old, obj_new) - && nm_dedup_multi_idx_type_partition_equal(idx_type, obj_old, obj_new)) { - /* optimize. We just looked up the @obj_old entry and @obj_new compares equal - * according to idx_obj_id_equal(). entry_new is the same as entry_old. */ - entry_new = entry_old; - } else { - entry_new = nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type, obj_new); - } - - if (entry_new) - entry_order = entry_new; - else if (entry_old - && nm_dedup_multi_idx_type_partition_equal(idx_type, entry_old->obj, obj_new)) - entry_order = entry_old; - else - entry_order = NULL; - nm_dedup_multi_index_add_full( - cache->multi_idx, - idx_type, - obj_new, - is_dump ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE : _obj_get_add_mode(obj_new), - is_dump ? NULL : entry_order, - entry_new ?: NM_DEDUP_MULTI_ENTRY_MISSING, - entry_new ? entry_new->head : (entry_order ? entry_order->head : NULL), - &entry_new, - NULL); - -#if NM_MORE_ASSERTS - if (entry_new) { - nm_assert(idx_type->klass->idx_obj_partitionable); - nm_assert(idx_type->klass->idx_obj_partition_equal); - nm_assert(idx_type->klass->idx_obj_partitionable(idx_type, entry_new->obj)); - nm_assert(idx_type->klass->idx_obj_partition_equal(idx_type, - (gpointer) obj_new, - entry_new->obj)); - } -#endif - } else - entry_new = NULL; - - if (entry_old && entry_old != entry_new) - nm_dedup_multi_index_remove_entry(cache->multi_idx, entry_old); -} - -static void -_idxcache_update(NMPCache * cache, - const NMDedupMultiEntry * entry_old, - NMPObject * obj_new, - gboolean is_dump, - const NMDedupMultiEntry **out_entry_new) -{ - const NMPClass * klass; - const guint8 * i_idx_type; - NMDedupMultiIdxType * idx_type_o = _idx_type_get(cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE); - const NMDedupMultiEntry *entry_new = NULL; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - - /* we update an object in the cache. - * - * Note that @entry_old MUST be what is currently tracked in multi_idx, and it must - * have the same ID as @obj_new. */ - - nm_assert(cache); - nm_assert(entry_old || obj_new); - nm_assert(!obj_new || nmp_object_is_alive(obj_new)); - nm_assert( - !entry_old - || entry_old - == nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type_o, entry_old->obj)); - nm_assert(!obj_new - || entry_old - == nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type_o, obj_new)); - nm_assert(!entry_old || entry_old->head->idx_type == idx_type_o); - nm_assert(!entry_old || !obj_new - || nm_dedup_multi_idx_type_partition_equal(idx_type_o, entry_old->obj, obj_new)); - nm_assert(!entry_old || !obj_new - || nm_dedup_multi_idx_type_id_equal(idx_type_o, entry_old->obj, obj_new)); - nm_assert(!entry_old || !obj_new - || (obj_new->parent.klass == ((const NMPObject *) entry_old->obj)->parent.klass - && !obj_new->parent.klass->obj_full_equal((NMDedupMultiObj *) obj_new, - entry_old->obj))); - - /* keep a reference to the pre-existing entry */ - if (entry_old) - obj_old = nmp_object_ref(entry_old->obj); - - /* first update the main index NMP_CACHE_ID_TYPE_OBJECT_TYPE. - * We already know the pre-existing @entry old, so all that - * nm_dedup_multi_index_add_full() effectively does, is update the - * obj reference. - * - * We also get the new boxed object, which we need below. */ - if (obj_new) { - nm_auto_nmpobj NMPObject *obj_old2 = NULL; - - nm_dedup_multi_index_add_full(cache->multi_idx, - idx_type_o, - obj_new, - is_dump ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE - : _obj_get_add_mode(obj_new), - NULL, - entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING, - NULL, - &entry_new, - (const NMDedupMultiObj **) &obj_old2); - nm_assert(entry_new); - nm_assert(obj_old == obj_old2); - nm_assert(!entry_old || entry_old == entry_new); - } else - nm_dedup_multi_index_remove_entry(cache->multi_idx, entry_old); - - /* now update all other indexes. We know the previously boxed entry, and the - * newly boxed one. */ - klass = NMP_OBJECT_GET_CLASS(entry_new ? entry_new->obj : obj_old); - for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) { - NMPCacheIdType id_type = *i_idx_type; - - if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) - continue; - _idxcache_update_other_cache_ids(cache, - id_type, - obj_old, - entry_new ? entry_new->obj : NULL, - is_dump); - } - - NM_SET_OUT(out_entry_new, entry_new); -} - -NMPCacheOpsType -nmp_cache_remove(NMPCache * cache, - const NMPObject * obj_needle, - gboolean equals_by_ptr, - gboolean only_dirty, - const NMPObject **out_obj_old) -{ - const NMDedupMultiEntry *entry_old; - const NMPObject * obj_old; - - entry_old = _lookup_entry(cache, obj_needle); - - if (!entry_old) { - NM_SET_OUT(out_obj_old, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_old = entry_old->obj; - - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - - if (equals_by_ptr && obj_old != obj_needle) { - /* We found an identical object, but we only delete it if it's the same pointer as - * @obj_needle. */ - return NMP_CACHE_OPS_UNCHANGED; - } - if (only_dirty && !entry_old->dirty) { - /* the entry is not dirty. Skip. */ - return NMP_CACHE_OPS_UNCHANGED; - } - _idxcache_update(cache, entry_old, NULL, FALSE, NULL); - return NMP_CACHE_OPS_REMOVED; -} - -NMPCacheOpsType -nmp_cache_remove_netlink(NMPCache * cache, - const NMPObject * obj_needle, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) -{ - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new = NULL; - const NMPObject * obj_old; - nm_auto_nmpobj NMPObject *obj_new = NULL; - - entry_old = _lookup_entry(cache, obj_needle); - - if (!entry_old) { - NM_SET_OUT(out_obj_old, NULL); - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_old = entry_old->obj; - - if (NMP_OBJECT_GET_TYPE(obj_needle) == NMP_OBJECT_TYPE_LINK) { - /* For nmp_cache_remove_netlink() we have an incomplete @obj_needle instance to be - * removed from netlink. Link objects are alive without being in netlink when they - * have a udev-device. All we want to do in this case is clear the netlink.is_in_netlink - * flag. */ - - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - - if (!obj_old->_link.netlink.is_in_netlink) { - nm_assert(obj_old->_link.udev.device); - NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - if (!obj_old->_link.udev.device) { - /* the update would make @obj_old invalid. Remove it. */ - _idxcache_update(cache, entry_old, NULL, FALSE, NULL); - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_REMOVED; - } - - obj_new = nmp_object_clone(obj_old, FALSE); - obj_new->_link.netlink.is_in_netlink = FALSE; - - _nmp_object_fixup_link_master_connected(&obj_new, NULL, cache); - _nmp_object_fixup_link_udev_fields(&obj_new, NULL, cache->use_udev); - - _idxcache_update(cache, entry_old, obj_new, FALSE, &entry_new); - NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; - } - - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - NM_SET_OUT(out_obj_new, NULL); - _idxcache_update(cache, entry_old, NULL, FALSE, NULL); - return NMP_CACHE_OPS_REMOVED; -} - -/** - * nmp_cache_update_netlink: - * @cache: the platform cache - * @obj_hand_over: a #NMPObject instance as received from netlink and created via - * nmp_object_from_nl(). Especially for link, it must not have the udev - * replated fields set. - * This instance will be modified and might be put into the cache. When - * calling nmp_cache_update_netlink() you hand @obj over to the cache. - * Except, that the cache will increment the ref count as appropriate. You - * must still unref the obj to release your part of the ownership. - * @is_dump: whether this update comes during a dump of object of the same kind. - * kernel dumps objects in a certain order, which matters especially for routes. - * Before a dump we mark all objects as dirty, and remove all untouched objects - * afterwards. Hence, during a dump, every update should move the object to the - * end of the list, to obtain the correct order. That means, to use NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE, - * instead of NM_DEDUP_MULTI_IDX_MODE_APPEND. - * @out_obj_old: (allow-none) (out): return the object with same ID as @obj_hand_over, - * that was in the cache before update. If an object is returned, the caller must - * unref it afterwards. - * @out_obj_new: (allow-none) (out): return the object from the cache after update. - * The caller must unref this object. - * - * Returns: how the cache changed. - * - * Even if there was no change in the cache (NMP_CACHE_OPS_UNCHANGED), @out_obj_old - * and @out_obj_new will be set accordingly. - **/ -NMPCacheOpsType -nmp_cache_update_netlink(NMPCache * cache, - NMPObject * obj_hand_over, - gboolean is_dump, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) -{ - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new; - const NMPObject * obj_old; - gboolean is_alive; - - nm_assert(cache); - nm_assert(NMP_OBJECT_IS_VALID(obj_hand_over)); - nm_assert(!NMP_OBJECT_IS_STACKINIT(obj_hand_over)); - /* A link object from netlink must have the udev related fields unset. - * We could implement to handle that, but there is no need to support such - * a use-case */ - nm_assert(NMP_OBJECT_GET_TYPE(obj_hand_over) != NMP_OBJECT_TYPE_LINK - || (!obj_hand_over->_link.udev.device && !obj_hand_over->link.driver)); - nm_assert(nm_dedup_multi_index_obj_find(cache->multi_idx, obj_hand_over) != obj_hand_over); - - entry_old = _lookup_entry(cache, obj_hand_over); - - if (!entry_old) { - NM_SET_OUT(out_obj_old, NULL); - - if (!nmp_object_is_alive(obj_hand_over)) { - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - if (NMP_OBJECT_GET_TYPE(obj_hand_over) == NMP_OBJECT_TYPE_LINK) { - _nmp_object_fixup_link_master_connected(&obj_hand_over, NULL, cache); - _nmp_object_fixup_link_udev_fields(&obj_hand_over, NULL, cache->use_udev); - } - - _idxcache_update(cache, entry_old, obj_hand_over, is_dump, &entry_new); - NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); - return NMP_CACHE_OPS_ADDED; - } - - obj_old = entry_old->obj; - - if (NMP_OBJECT_GET_TYPE(obj_hand_over) == NMP_OBJECT_TYPE_LINK) { - if (!obj_hand_over->_link.netlink.is_in_netlink) { - if (!obj_old->_link.netlink.is_in_netlink) { - nm_assert(obj_old->_link.udev.device); - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - if (obj_old->_link.udev.device) { - /* @obj_hand_over is not in netlink. - * - * This is similar to nmp_cache_remove_netlink(), but there we preserve the - * preexisting netlink properties. The use case of that is when kernel_get_object() - * cannot load an object (based on the id of a needle). - * - * Here we keep the data provided from @obj_hand_over. The usecase is when receiving - * a valid @obj_hand_over instance from netlink with RTM_DELROUTE. - */ - is_alive = TRUE; - } else - is_alive = FALSE; - } else - is_alive = TRUE; - - if (is_alive) { - _nmp_object_fixup_link_master_connected(&obj_hand_over, NULL, cache); - - /* Merge the netlink parts with what we have from udev. */ - udev_device_unref(obj_hand_over->_link.udev.device); - obj_hand_over->_link.udev.device = - obj_old->_link.udev.device ? udev_device_ref(obj_old->_link.udev.device) : NULL; - _nmp_object_fixup_link_udev_fields(&obj_hand_over, NULL, cache->use_udev); - - if (obj_hand_over->_link.netlink.lnk) { - nm_auto_nmpobj const NMPObject *lnk_old = obj_hand_over->_link.netlink.lnk; - - /* let's dedup/intern the lnk object. */ - obj_hand_over->_link.netlink.lnk = - nm_dedup_multi_index_obj_intern(cache->multi_idx, lnk_old); - } - } - } else - is_alive = nmp_object_is_alive(obj_hand_over); - - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - - if (!is_alive) { - /* the update would make @obj_old invalid. Remove it. */ - _idxcache_update(cache, entry_old, NULL, FALSE, NULL); - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_REMOVED; - } - - if (nmp_object_equal(obj_old, obj_hand_over)) { - if (is_dump) - _idxcache_update_order_for_dump(cache, entry_old); - nm_dedup_multi_entry_set_dirty(entry_old, FALSE); - NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - _idxcache_update(cache, entry_old, obj_hand_over, is_dump, &entry_new); - NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; -} - -NMPCacheOpsType -nmp_cache_update_netlink_route(NMPCache * cache, - NMPObject * obj_hand_over, - gboolean is_dump, - guint16 nlmsgflags, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new, - const NMPObject **out_obj_replace, - gboolean * out_resync_required) -{ - NMDedupMultiIter iter; - const NMDedupMultiEntry * entry_old; - const NMDedupMultiEntry * entry_new; - const NMDedupMultiEntry * entry_cur; - const NMDedupMultiEntry * entry_replace; - const NMDedupMultiHeadEntry *head_entry; - gboolean is_alive; - NMPCacheOpsType ops_type = NMP_CACHE_OPS_UNCHANGED; - gboolean resync_required; - - nm_assert(cache); - nm_assert(NMP_OBJECT_IS_VALID(obj_hand_over)); - nm_assert(!NMP_OBJECT_IS_STACKINIT(obj_hand_over)); - /* A link object from netlink must have the udev related fields unset. - * We could implement to handle that, but there is no need to support such - * a use-case */ - nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_hand_over), - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - nm_assert(nm_dedup_multi_index_obj_find(cache->multi_idx, obj_hand_over) != obj_hand_over); - - entry_old = _lookup_entry(cache, obj_hand_over); - entry_new = NULL; - - NM_SET_OUT(out_obj_old, nmp_object_ref(nm_dedup_multi_entry_get_obj(entry_old))); - - if (!entry_old) { - if (!nmp_object_is_alive(obj_hand_over)) - goto update_done; - - _idxcache_update(cache, NULL, obj_hand_over, is_dump, &entry_new); - ops_type = NMP_CACHE_OPS_ADDED; - goto update_done; - } - - is_alive = nmp_object_is_alive(obj_hand_over); - - if (!is_alive) { - /* the update would make @entry_old invalid. Remove it. */ - _idxcache_update(cache, entry_old, NULL, FALSE, NULL); - ops_type = NMP_CACHE_OPS_REMOVED; - goto update_done; - } - - if (nmp_object_equal(entry_old->obj, obj_hand_over)) { - if (is_dump) - _idxcache_update_order_for_dump(cache, entry_old); - nm_dedup_multi_entry_set_dirty(entry_old, FALSE); - goto update_done; - } - - _idxcache_update(cache, entry_old, obj_hand_over, is_dump, &entry_new); - ops_type = NMP_CACHE_OPS_UPDATED; - -update_done: - NM_SET_OUT(out_obj_new, nmp_object_ref(nm_dedup_multi_entry_get_obj(entry_new))); - - /* a RTM_GETROUTE event may signal that another object was replaced. - * Find out whether that is the case and return it as @obj_replaced. - * - * Also, fixup the order of @entry_new within NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID - * index. For most parts, we don't care about the order of objects (including routes). - * But NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID we must keep in the correct order, to - * properly find @obj_replaced. */ - resync_required = FALSE; - entry_replace = NULL; - if (is_dump) - goto out; - - if (!entry_new) { - if (NM_FLAGS_HAS(nlmsgflags, NLM_F_REPLACE) - && nmp_cache_lookup_all(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, obj_hand_over)) { - /* hm. @obj_hand_over was not added, meaning it was not alive. - * However, we track some other objects with the same weak-id. - * It's unclear what that means. To be sure, resync. */ - resync_required = TRUE; - } - goto out; - } - - /* FIXME: for routes, we only maintain the order correctly for the BY_WEAK_ID - * index. For all other indexes their order becomes messed up. */ - entry_cur = - _lookup_entry_with_idx_type(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, entry_new->obj); - if (!entry_cur) { - nm_assert_not_reached(); - goto out; - } - nm_assert(entry_cur->obj == entry_new->obj); - - head_entry = entry_cur->head; - nm_assert(head_entry - == nmp_cache_lookup_all(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, entry_cur->obj)); - - if (head_entry->len == 1) { - /* there is only one object, and we expect it to be @obj_new. */ - nm_assert(nm_dedup_multi_head_entry_get_idx(head_entry, 0) == entry_cur); - goto out; - } - - switch (nlmsgflags & (NLM_F_REPLACE | NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND)) { - case NLM_F_REPLACE: - /* ip route change */ - - /* get the first element (but skip @obj_new). */ - nm_dedup_multi_iter_init(&iter, head_entry); - if (!nm_dedup_multi_iter_next(&iter)) - nm_assert_not_reached(); - if (iter.current == entry_cur) { - if (!nm_dedup_multi_iter_next(&iter)) - nm_assert_not_reached(); - } - entry_replace = iter.current; - - nm_assert(entry_replace && entry_cur != entry_replace); - - nm_dedup_multi_entry_reorder(entry_cur, entry_replace, FALSE); - break; - case NLM_F_CREATE | NLM_F_APPEND: - /* ip route append */ - nm_dedup_multi_entry_reorder(entry_cur, NULL, TRUE); - break; - case NLM_F_CREATE: - /* ip route prepend */ - nm_dedup_multi_entry_reorder(entry_cur, NULL, FALSE); - break; - default: - /* this is an unexpected case, probably a bug that we need to handle better. */ - resync_required = TRUE; - break; - } - -out: - NM_SET_OUT(out_obj_replace, nmp_object_ref(nm_dedup_multi_entry_get_obj(entry_replace))); - NM_SET_OUT(out_resync_required, resync_required); - return ops_type; -} - -NMPCacheOpsType -nmp_cache_update_link_udev(NMPCache * cache, - int ifindex, - struct udev_device *udevice, - const NMPObject ** out_obj_old, - const NMPObject ** out_obj_new) -{ - const NMPObject *obj_old; - nm_auto_nmpobj NMPObject *obj_new = NULL; - const NMDedupMultiEntry * entry_old; - const NMDedupMultiEntry * entry_new; - - entry_old = nmp_cache_lookup_entry_link(cache, ifindex); - - if (!entry_old) { - if (!udevice) { - NM_SET_OUT(out_obj_old, NULL); - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_new = nmp_object_new(NMP_OBJECT_TYPE_LINK, NULL); - obj_new->link.ifindex = ifindex; - obj_new->_link.udev.device = udev_device_ref(udevice); - - _nmp_object_fixup_link_udev_fields(&obj_new, NULL, cache->use_udev); - - _idxcache_update(cache, NULL, obj_new, FALSE, &entry_new); - NM_SET_OUT(out_obj_old, NULL); - NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); - return NMP_CACHE_OPS_ADDED; - } else { - obj_old = entry_old->obj; - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - - if (obj_old->_link.udev.device == udevice) { - NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - if (!udevice && !obj_old->_link.netlink.is_in_netlink) { - /* the update would make @obj_old invalid. Remove it. */ - _idxcache_update(cache, entry_old, NULL, FALSE, NULL); - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_REMOVED; - } - - obj_new = nmp_object_clone(obj_old, FALSE); - - udev_device_unref(obj_new->_link.udev.device); - obj_new->_link.udev.device = udevice ? udev_device_ref(udevice) : NULL; - - _nmp_object_fixup_link_udev_fields(&obj_new, NULL, cache->use_udev); - - _idxcache_update(cache, entry_old, obj_new, FALSE, &entry_new); - NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; - } -} - -NMPCacheOpsType -nmp_cache_update_link_master_connected(NMPCache * cache, - int ifindex, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) -{ - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new = NULL; - const NMPObject * obj_old; - nm_auto_nmpobj NMPObject *obj_new = NULL; - - entry_old = nmp_cache_lookup_entry_link(cache, ifindex); - - if (!entry_old) { - NM_SET_OUT(out_obj_old, NULL); - NM_SET_OUT(out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_old = entry_old->obj; - - if (!nmp_cache_link_connected_needs_toggle(cache, obj_old, NULL, NULL)) { - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_new = nmp_object_clone(obj_old, FALSE); - obj_new->link.connected = !obj_old->link.connected; - - NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - _idxcache_update(cache, entry_old, obj_new, FALSE, &entry_new); - NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; -} - -/*****************************************************************************/ - -void -nmp_cache_dirty_set_all_main(NMPCache *cache, const NMPLookup *lookup) -{ - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - - nm_assert(cache); - nm_assert(lookup); - - head_entry = nmp_cache_lookup(cache, lookup); - - nm_dedup_multi_iter_init(&iter, head_entry); - while (nm_dedup_multi_iter_next(&iter)) { - const NMDedupMultiEntry *main_entry; - - main_entry = nmp_cache_reresolve_main_entry(cache, iter.current, lookup); - - nm_dedup_multi_entry_set_dirty(main_entry, TRUE); - } -} - -/*****************************************************************************/ - -NMPCache * -nmp_cache_new(NMDedupMultiIndex *multi_idx, gboolean use_udev) -{ - NMPCache *cache = g_slice_new0(NMPCache); - guint i; - - for (i = NMP_CACHE_ID_TYPE_NONE + 1; i <= NMP_CACHE_ID_TYPE_MAX; i++) - _dedup_multi_idx_type_init((DedupMultiIdxType *) _idx_type_get(cache, i), i); - - cache->multi_idx = nm_dedup_multi_index_ref(multi_idx); - - cache->use_udev = !!use_udev; - return cache; -} - -void -nmp_cache_free(NMPCache *cache) -{ - guint i; - - for (i = NMP_CACHE_ID_TYPE_NONE + 1; i <= NMP_CACHE_ID_TYPE_MAX; i++) - nm_dedup_multi_index_remove_idx(cache->multi_idx, _idx_type_get(cache, i)); - - nm_dedup_multi_index_unref(cache->multi_idx); - - g_slice_free(NMPCache, cache); -} - -/*****************************************************************************/ - -void -nmtst_assert_nmp_cache_is_consistent(const NMPCache *cache) -{} - -/*****************************************************************************/ - -/* below, ensure that addr_family get's automatically initialize to AF_UNSPEC. */ -G_STATIC_ASSERT(AF_UNSPEC == 0); - -typedef const char *(*CmdPlobjToStringFunc)(const NMPlatformObject *obj, char *buf, gsize len); -typedef const char *(*CmdPlobjToStringIdFunc)(const NMPlatformObject *obj, char *buf, gsize len); -typedef void (*CmdPlobjHashUpdateFunc)(const NMPlatformObject *obj, NMHashState *h); -typedef int (*CmdPlobjCmpFunc)(const NMPlatformObject *obj1, const NMPlatformObject *obj2); - -const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { - [NMP_OBJECT_TYPE_LINK - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LINK, - .sizeof_data = sizeof(NMPObjectLink), - .sizeof_public = sizeof(NMPlatformLink), - .obj_type_name = "link", - .rtm_gettype = RTM_GETLINK, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK, - .signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED, - .supported_cache_ids = _supported_cache_ids_link, - .cmd_obj_hash_update = _vt_cmd_obj_hash_update_link, - .cmd_obj_cmp = _vt_cmd_obj_cmp_link, - .cmd_obj_copy = _vt_cmd_obj_copy_link, - .cmd_obj_dispose = _vt_cmd_obj_dispose_link, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_link, - .cmd_obj_is_visible = _vt_cmd_obj_is_visible_link, - .cmd_obj_to_string = _vt_cmd_obj_to_string_link, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_link, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_link, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_link, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_link, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_link_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_link_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_link_cmp, - }, - [NMP_OBJECT_TYPE_IP4_ADDRESS - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS, - .sizeof_data = sizeof(NMPObjectIP4Address), - .sizeof_public = sizeof(NMPlatformIP4Address), - .obj_type_name = "ip4-address", - .addr_family = AF_INET, - .rtm_gettype = RTM_GETADDR, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, - .signal_type = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_address, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_address, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_address, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_address, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip4_address, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip4_address_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_ip4_address_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip4_address_cmp, - }, - [NMP_OBJECT_TYPE_IP6_ADDRESS - - 1] = {.parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS, - .sizeof_data = sizeof(NMPObjectIP6Address), - .sizeof_public = sizeof(NMPlatformIP6Address), - .obj_type_name = "ip6-address", - .addr_family = AF_INET6, - .rtm_gettype = RTM_GETADDR, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, - .signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_address, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_address, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_address, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_address, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip6_address_to_string, - .cmd_plobj_hash_update = - (CmdPlobjHashUpdateFunc) nm_platform_ip6_address_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip6_address_cmp}, - [NMP_OBJECT_TYPE_IP4_ROUTE - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, - .sizeof_data = sizeof(NMPObjectIP4Route), - .sizeof_public = sizeof(NMPlatformIP4Route), - .obj_type_name = "ip4-route", - .addr_family = AF_INET, - .rtm_gettype = RTM_GETROUTE, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, - .signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_route, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_route, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_route, - .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_ip4_route_to_string, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip4_route_to_string, - .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_ip4_route, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip4_route_cmp_full, - }, - [NMP_OBJECT_TYPE_IP6_ROUTE - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, - .sizeof_data = sizeof(NMPObjectIP6Route), - .sizeof_public = sizeof(NMPlatformIP6Route), - .obj_type_name = "ip6-route", - .addr_family = AF_INET6, - .rtm_gettype = RTM_GETROUTE, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, - .signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_route, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_route, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_route, - .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_ip6_route_to_string, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip6_route_to_string, - .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_ip6_route, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip6_route_cmp_full, - }, - [NMP_OBJECT_TYPE_ROUTING_RULE - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_ROUTING_RULE, - .sizeof_data = sizeof(NMPObjectRoutingRule), - .sizeof_public = sizeof(NMPlatformRoutingRule), - .obj_type_name = "routing-rule", - .rtm_gettype = RTM_GETRULE, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, - .signal_type = NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, - .supported_cache_ids = _supported_cache_ids_routing_rules, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_routing_rule, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_routing_rule, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_routing_rule, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_routing_rule, - .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_routing_rule_to_string, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_routing_rule_to_string, - .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_routing_rule, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_routing_rule_cmp_full, - }, - [NMP_OBJECT_TYPE_QDISC - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_QDISC, - .sizeof_data = sizeof(NMPObjectQdisc), - .sizeof_public = sizeof(NMPlatformQdisc), - .obj_type_name = "qdisc", - .rtm_gettype = RTM_GETQDISC, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_QDISC, - .signal_type = NM_PLATFORM_SIGNAL_QDISC_CHANGED, - .supported_cache_ids = _supported_cache_ids_object, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_qdisc, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_qdisc, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_qdisc, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_qdisc, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_qdisc_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_qdisc_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_qdisc_cmp, - }, - [NMP_OBJECT_TYPE_TFILTER - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_TFILTER, - .sizeof_data = sizeof(NMPObjectTfilter), - .sizeof_public = sizeof(NMPlatformTfilter), - .obj_type_name = "tfilter", - .rtm_gettype = RTM_GETTFILTER, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_TFILTER, - .signal_type = NM_PLATFORM_SIGNAL_TFILTER_CHANGED, - .supported_cache_ids = _supported_cache_ids_object, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_tfilter, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_tfilter, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_tfilter, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_tfilter, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_tfilter_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_tfilter_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_tfilter_cmp, - }, - [NMP_OBJECT_TYPE_LNK_BRIDGE - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_BRIDGE, - .sizeof_data = sizeof(NMPObjectLnkBridge), - .sizeof_public = sizeof(NMPlatformLnkBridge), - .obj_type_name = "bridge", - .lnk_link_type = NM_LINK_TYPE_BRIDGE, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_bridge_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_bridge_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_bridge_cmp, - }, - [NMP_OBJECT_TYPE_LNK_GRE - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_GRE, - .sizeof_data = sizeof(NMPObjectLnkGre), - .sizeof_public = sizeof(NMPlatformLnkGre), - .obj_type_name = "gre", - .lnk_link_type = NM_LINK_TYPE_GRE, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_gre_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_gre_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_gre_cmp, - }, - [NMP_OBJECT_TYPE_LNK_GRETAP - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_GRETAP, - .sizeof_data = sizeof(NMPObjectLnkGre), - .sizeof_public = sizeof(NMPlatformLnkGre), - .obj_type_name = "gretap", - .lnk_link_type = NM_LINK_TYPE_GRETAP, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_gre_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_gre_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_gre_cmp, - }, - [NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND, - .sizeof_data = sizeof(NMPObjectLnkInfiniband), - .sizeof_public = sizeof(NMPlatformLnkInfiniband), - .obj_type_name = "infiniband", - .lnk_link_type = NM_LINK_TYPE_INFINIBAND, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_infiniband_to_string, - .cmd_plobj_hash_update = - (CmdPlobjHashUpdateFunc) nm_platform_lnk_infiniband_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_infiniband_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IP6TNL - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IP6TNL, - .sizeof_data = sizeof(NMPObjectLnkIp6Tnl), - .sizeof_public = sizeof(NMPlatformLnkIp6Tnl), - .obj_type_name = "ip6tnl", - .lnk_link_type = NM_LINK_TYPE_IP6TNL, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ip6tnl_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ip6tnl_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ip6tnl_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IP6GRE - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRE, - .sizeof_data = sizeof(NMPObjectLnkIp6Tnl), - .sizeof_public = sizeof(NMPlatformLnkIp6Tnl), - .obj_type_name = "ip6gre", - .lnk_link_type = NM_LINK_TYPE_IP6GRE, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ip6tnl_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ip6tnl_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ip6tnl_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IP6GRETAP - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRETAP, - .sizeof_data = sizeof(NMPObjectLnkIp6Tnl), - .sizeof_public = sizeof(NMPlatformLnkIp6Tnl), - .obj_type_name = "ip6gretap", - .lnk_link_type = NM_LINK_TYPE_IP6GRETAP, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ip6tnl_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ip6tnl_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ip6tnl_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IPIP - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, - .sizeof_data = sizeof(NMPObjectLnkIpIp), - .sizeof_public = sizeof(NMPlatformLnkIpIp), - .obj_type_name = "ipip", - .lnk_link_type = NM_LINK_TYPE_IPIP, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ipip_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ipip_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ipip_cmp, - }, - [NMP_OBJECT_TYPE_LNK_MACSEC - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_MACSEC, - .sizeof_data = sizeof(NMPObjectLnkMacsec), - .sizeof_public = sizeof(NMPlatformLnkMacsec), - .obj_type_name = "macsec", - .lnk_link_type = NM_LINK_TYPE_MACSEC, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_macsec_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_macsec_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_macsec_cmp, - }, - [NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN, - .sizeof_data = sizeof(NMPObjectLnkMacvlan), - .sizeof_public = sizeof(NMPlatformLnkMacvlan), - .obj_type_name = "macvlan", - .lnk_link_type = NM_LINK_TYPE_MACVLAN, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_macvlan_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_macvlan_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_macvlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_MACVTAP - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_MACVTAP, - .sizeof_data = sizeof(NMPObjectLnkMacvtap), - .sizeof_public = sizeof(NMPlatformLnkMacvlan), - .obj_type_name = "macvtap", - .lnk_link_type = NM_LINK_TYPE_MACVTAP, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_macvlan_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_macvlan_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_macvlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_SIT - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_SIT, - .sizeof_data = sizeof(NMPObjectLnkSit), - .sizeof_public = sizeof(NMPlatformLnkSit), - .obj_type_name = "sit", - .lnk_link_type = NM_LINK_TYPE_SIT, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_sit_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_sit_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_sit_cmp, - }, - [NMP_OBJECT_TYPE_LNK_TUN - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_TUN, - .sizeof_data = sizeof(NMPObjectLnkTun), - .sizeof_public = sizeof(NMPlatformLnkTun), - .obj_type_name = "tun", - .lnk_link_type = NM_LINK_TYPE_TUN, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_tun_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_tun_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_tun_cmp, - }, - [NMP_OBJECT_TYPE_LNK_VLAN - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_VLAN, - .sizeof_data = sizeof(NMPObjectLnkVlan), - .sizeof_public = sizeof(NMPlatformLnkVlan), - .obj_type_name = "vlan", - .lnk_link_type = NM_LINK_TYPE_VLAN, - .cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_vlan, - .cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_vlan, - .cmd_obj_copy = _vt_cmd_obj_copy_lnk_vlan, - .cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_vlan, - .cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_vlan, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_vlan_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_vlan_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_vlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_VRF - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_VRF, - .sizeof_data = sizeof(NMPObjectLnkVrf), - .sizeof_public = sizeof(NMPlatformLnkVrf), - .obj_type_name = "vrf", - .lnk_link_type = NM_LINK_TYPE_VRF, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_vrf_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_vrf_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_vrf_cmp, - }, - [NMP_OBJECT_TYPE_LNK_VXLAN - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_VXLAN, - .sizeof_data = sizeof(NMPObjectLnkVxlan), - .sizeof_public = sizeof(NMPlatformLnkVxlan), - .obj_type_name = "vxlan", - .lnk_link_type = NM_LINK_TYPE_VXLAN, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_vxlan_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_vxlan_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_vxlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_WIREGUARD - 1] = - { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_WIREGUARD, - .sizeof_data = sizeof(NMPObjectLnkWireGuard), - .sizeof_public = sizeof(NMPlatformLnkWireGuard), - .obj_type_name = "wireguard", - .lnk_link_type = NM_LINK_TYPE_WIREGUARD, - .cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_wireguard, - .cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_wireguard, - .cmd_obj_copy = _vt_cmd_obj_copy_lnk_wireguard, - .cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_wireguard, - .cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_wireguard, - .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_wireguard_to_string, - .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_wireguard_hash_update, - .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_wireguard_cmp, - }, -}; diff --git a/src/core/platform/nmp-object.h b/src/core/platform/nmp-object.h deleted file mode 100644 index 19f6bcd7..00000000 --- a/src/core/platform/nmp-object.h +++ /dev/null @@ -1,1144 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2015 - 2018 Red Hat, Inc. - */ - -#ifndef __NMP_OBJECT_H__ -#define __NMP_OBJECT_H__ - -#include - -#include "nm-glib-aux/nm-obj.h" -#include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-platform.h" - -struct udev_device; - -/*****************************************************************************/ - -/* "struct __kernel_timespec" uses "long long", but we use gint64. In practice, - * these are the same types. */ -G_STATIC_ASSERT(sizeof(long long) == sizeof(gint64)); - -typedef struct { - /* like "struct __kernel_timespec". */ - gint64 tv_sec; - gint64 tv_nsec; -} NMPTimespec64; - -/*****************************************************************************/ - -typedef union { - struct sockaddr sa; - struct sockaddr_in in; - struct sockaddr_in6 in6; -} NMSockAddrUnion; - -G_STATIC_ASSERT(sizeof(NMSockAddrUnion) == sizeof(((NMSockAddrUnion *) NULL)->in6)); - -/* we initialize the largest union member, to ensure that all fields are initialized. */ - -#define NM_SOCK_ADDR_UNION_INIT_UNSPEC \ - { \ - .in6 = { \ - .sin6_family = AF_UNSPEC, \ - }, \ - } - -int nm_sock_addr_union_cmp(const NMSockAddrUnion *a, const NMSockAddrUnion *b); - -void nm_sock_addr_union_hash_update(const NMSockAddrUnion *a, NMHashState *h); - -void nm_sock_addr_union_cpy(NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */); - -void nm_sock_addr_union_cpy_untrusted(NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */, - gsize src_len); - -const char *nm_sock_addr_union_to_string(const NMSockAddrUnion *sa, char *buf, gsize len); - -/*****************************************************************************/ - -typedef struct { - NMIPAddr addr; - guint8 family; - guint8 mask; -} NMPWireGuardAllowedIP; - -typedef struct _NMPWireGuardPeer { - NMSockAddrUnion endpoint; - - NMPTimespec64 last_handshake_time; - - guint64 rx_bytes; - guint64 tx_bytes; - - union { - const NMPWireGuardAllowedIP *allowed_ips; - guint _construct_idx_start; - }; - union { - guint allowed_ips_len; - guint _construct_idx_end; - }; - - guint16 persistent_keepalive_interval; - - guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; - guint8 preshared_key[NMP_WIREGUARD_SYMMETRIC_KEY_LEN]; -} NMPWireGuardPeer; - -/*****************************************************************************/ - -typedef enum { /*< skip >*/ - NMP_OBJECT_TO_STRING_ID, - NMP_OBJECT_TO_STRING_PUBLIC, - NMP_OBJECT_TO_STRING_ALL, -} NMPObjectToStringMode; - -typedef enum { /*< skip >*/ - NMP_CACHE_OPS_UNCHANGED = NM_PLATFORM_SIGNAL_NONE, - NMP_CACHE_OPS_ADDED = NM_PLATFORM_SIGNAL_ADDED, - NMP_CACHE_OPS_UPDATED = NM_PLATFORM_SIGNAL_CHANGED, - NMP_CACHE_OPS_REMOVED = NM_PLATFORM_SIGNAL_REMOVED, -} NMPCacheOpsType; - -/* The NMPCacheIdType are the different index types. - * - * An object of a certain object-type, can be candidate to being - * indexed by a certain NMPCacheIdType or not. For example, all - * objects are indexed via an index of type NMP_CACHE_ID_TYPE_OBJECT_TYPE, - * but only route objects can be indexed by NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT. - * - * Of one index type, there can be multiple indexes or not. - * For example, of the index type NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX there - * are multiple instances (for different route/addresses, v4/v6, per-ifindex). - * - * But one object, can only be indexed by one particular index of a - * type. For example, a certain address instance is only indexed by - * the index NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX with - * matching v4/v6 and ifindex -- or maybe not at all if it isn't visible. - * */ -typedef enum { /*< skip >*/ - NMP_CACHE_ID_TYPE_NONE, - - /* all the objects of a certain type. - * - * This index is special. It is the only one that contains *all* object. - * Other indexes may consider some object as non "partitionable", hence - * they don't track all objects. - * - * Hence, this index type is used when looking at all objects (still - * partitioned by type). - * - * Also, note that links may be considered invisible. This index type - * expose all links, even invisible ones. For addresses/routes, this - * distinction doesn't exist, as all addresses/routes that are alive - * are visible as well. */ - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - - /* index for the link objects by ifname. */ - NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, - - /* indices for the visible default-routes, ignoring ifindex. - * This index only contains two partitions: all visible default-routes, - * separate for IPv4 and IPv6. */ - NMP_CACHE_ID_TYPE_DEFAULT_ROUTES, - - /* all the objects that have an ifindex (by object-type) for an ifindex. */ - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - - /* Consider all the destination fields of a route, that is, the ID without the ifindex - * and gateway (meaning: network/plen,metric). - * The reason for this is that `ip route change` can replace an existing route - * and modify its ifindex/gateway. Effectively, that means it deletes an existing - * route and adds a different one (as the ID of the route changes). However, it only - * sends one RTM_NEWADDR notification without notifying about the deletion. We detect - * that by having this index to contain overlapping routes which require special - * cache-resync. */ - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - - /* a filter for objects that track an explicit address family. - * - * Note that currently on NMPObjectRoutingRule is indexed by this filter. */ - NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY, - - __NMP_CACHE_ID_TYPE_MAX, - NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1, -} NMPCacheIdType; - -typedef struct { - NMDedupMultiObjClass parent; - const char * obj_type_name; - const char * signal_type; - const guint8 * supported_cache_ids; - int sizeof_data; - int sizeof_public; - int addr_family; - int rtm_gettype; - NMPObjectType obj_type; - NMPlatformSignalIdType signal_type_id; - - /* Only for NMPObjectLnk* types. */ - NMLinkType lnk_link_type; - - void (*cmd_obj_hash_update)(const NMPObject *obj, NMHashState *h); - int (*cmd_obj_cmp)(const NMPObject *obj1, const NMPObject *obj2); - void (*cmd_obj_copy)(NMPObject *dst, const NMPObject *src); - void (*cmd_obj_dispose)(NMPObject *obj); - gboolean (*cmd_obj_is_alive)(const NMPObject *obj); - gboolean (*cmd_obj_is_visible)(const NMPObject *obj); - const char *(*cmd_obj_to_string)(const NMPObject * obj, - NMPObjectToStringMode to_string_mode, - char * buf, - gsize buf_size); - - /* functions that operate on NMPlatformObject */ - void (*cmd_plobj_id_copy)(NMPlatformObject *dst, const NMPlatformObject *src); - int (*cmd_plobj_id_cmp)(const NMPlatformObject *obj1, const NMPlatformObject *obj2); - void (*cmd_plobj_id_hash_update)(const NMPlatformObject *obj, NMHashState *h); - const char *(*cmd_plobj_to_string_id)(const NMPlatformObject *obj, char *buf, gsize buf_size); - const char *(*cmd_plobj_to_string)(const NMPlatformObject *obj, char *buf, gsize len); - void (*cmd_plobj_hash_update)(const NMPlatformObject *obj, NMHashState *h); - int (*cmd_plobj_cmp)(const NMPlatformObject *obj1, const NMPlatformObject *obj2); -} NMPClass; - -extern const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX]; - -typedef struct { - NMPlatformLink _public; - - struct { - bool is_in_netlink; - - /* Additional data that depends on the link-type (IFLA_INFO_DATA) */ - const NMPObject *lnk; - } netlink; - - struct { - /* note that "struct udev_device" references the library context - * "struct udev", but doesn't own it. - * - * Hence, the udev.device shall not be used after the library - * context is destroyed. - * - * In case of NMPObjectLink instances that you obtained from the - * platform cache, that means that you shall no keep references - * to those instances that outlife the NMPlatform instance. - * - * In practice, the requirement is less strict and you'll be even - * fine if the platform instance (and the "struct udev" instance) - * are already destroyed while you still hold onto a reference to - * the NMPObjectLink instance. Just don't make use of udev functions - * that cause access to the udev library context. - */ - struct udev_device *device; - } udev; - - /* Auxiliary data object for Wi-Fi and WPAN */ - GObject *ext_data; - - /* FIXME: not every NMPObjectLink should pay the price for tracking - * the wireguard family id. This should be tracked via ext_data, which - * would be exactly the right place. */ - int wireguard_family_id; -} NMPObjectLink; - -typedef struct { - NMPlatformLnkBridge _public; -} NMPObjectLnkBridge; - -typedef struct { - NMPlatformLnkGre _public; -} NMPObjectLnkGre; - -typedef struct { - NMPlatformLnkInfiniband _public; -} NMPObjectLnkInfiniband; - -typedef struct { - NMPlatformLnkIp6Tnl _public; -} NMPObjectLnkIp6Tnl; - -typedef struct { - NMPlatformLnkIpIp _public; -} NMPObjectLnkIpIp; - -typedef struct { - NMPlatformLnkMacsec _public; -} NMPObjectLnkMacsec; - -typedef struct { - NMPlatformLnkMacvlan _public; -} NMPObjectLnkMacvlan; - -typedef NMPObjectLnkMacvlan NMPObjectLnkMacvtap; - -typedef struct { - NMPlatformLnkSit _public; -} NMPObjectLnkSit; - -typedef struct { - NMPlatformLnkTun _public; -} NMPObjectLnkTun; - -typedef struct { - NMPlatformLnkVlan _public; - - guint n_ingress_qos_map; - guint n_egress_qos_map; - const NMVlanQosMapping *ingress_qos_map; - const NMVlanQosMapping *egress_qos_map; -} NMPObjectLnkVlan; - -typedef struct { - NMPlatformLnkVrf _public; -} NMPObjectLnkVrf; - -typedef struct { - NMPlatformLnkVxlan _public; -} NMPObjectLnkVxlan; - -typedef struct { - NMPlatformLnkWireGuard _public; - const NMPWireGuardPeer * peers; - const NMPWireGuardAllowedIP *_allowed_ips_buf; - guint peers_len; - guint _allowed_ips_buf_len; -} NMPObjectLnkWireGuard; - -typedef struct { - NMPlatformIP4Address _public; -} NMPObjectIP4Address; - -typedef struct { - NMPlatformIP4Route _public; -} NMPObjectIP4Route; - -typedef struct { - NMPlatformIP6Address _public; -} NMPObjectIP6Address; - -typedef struct { - NMPlatformIP6Route _public; -} NMPObjectIP6Route; - -typedef struct { - NMPlatformRoutingRule _public; -} NMPObjectRoutingRule; - -typedef struct { - NMPlatformQdisc _public; -} NMPObjectQdisc; - -typedef struct { - NMPlatformTfilter _public; -} NMPObjectTfilter; - -struct _NMPObject { - union { - NMDedupMultiObj parent; - const NMPClass *_class; - }; - union { - NMPlatformObject object; - - NMPlatformObjWithIfindex obj_with_ifindex; - - NMPlatformLink link; - NMPObjectLink _link; - - NMPlatformLnkBridge lnk_bridge; - NMPObjectLnkBridge _lnk_bridge; - - NMPlatformLnkGre lnk_gre; - NMPObjectLnkGre _lnk_gre; - - NMPlatformLnkInfiniband lnk_infiniband; - NMPObjectLnkInfiniband _lnk_infiniband; - - NMPlatformLnkIpIp lnk_ipip; - NMPObjectLnkIpIp _lnk_ipip; - - NMPlatformLnkIp6Tnl lnk_ip6tnl; - NMPObjectLnkIp6Tnl _lnk_ip6tnl; - - NMPlatformLnkMacsec lnk_macsec; - NMPObjectLnkMacsec _lnk_macsec; - - NMPlatformLnkMacvlan lnk_macvlan; - NMPObjectLnkMacvlan _lnk_macvlan; - - NMPlatformLnkSit lnk_sit; - NMPObjectLnkSit _lnk_sit; - - NMPlatformLnkTun lnk_tun; - NMPObjectLnkTun _lnk_tun; - - NMPlatformLnkVlan lnk_vlan; - NMPObjectLnkVlan _lnk_vlan; - - NMPlatformLnkVrf lnk_vrf; - NMPObjectLnkVrf _lnk_vrf; - - NMPlatformLnkVxlan lnk_vxlan; - NMPObjectLnkVxlan _lnk_vxlan; - - NMPlatformLnkWireGuard lnk_wireguard; - NMPObjectLnkWireGuard _lnk_wireguard; - - NMPlatformIPAddress ip_address; - NMPlatformIPXAddress ipx_address; - NMPlatformIP4Address ip4_address; - NMPlatformIP6Address ip6_address; - NMPObjectIP4Address _ip4_address; - NMPObjectIP6Address _ip6_address; - - NMPlatformIPRoute ip_route; - NMPlatformIPXRoute ipx_route; - NMPlatformIP4Route ip4_route; - NMPlatformIP6Route ip6_route; - NMPObjectIP4Route _ip4_route; - NMPObjectIP6Route _ip6_route; - - NMPlatformRoutingRule routing_rule; - NMPObjectRoutingRule _routing_rule; - - NMPlatformQdisc qdisc; - NMPObjectQdisc _qdisc; - NMPlatformTfilter tfilter; - NMPObjectTfilter _tfilter; - }; -}; - -/*****************************************************************************/ - -static inline gboolean -NMP_CLASS_IS_VALID(const NMPClass *klass) -{ - return klass >= &_nmp_classes[0] && klass <= &_nmp_classes[G_N_ELEMENTS(_nmp_classes)] - && ((((char *) klass) - ((char *) _nmp_classes)) % (sizeof(_nmp_classes[0]))) == 0; -} - -static inline const NMPClass * -nmp_class_from_type(NMPObjectType obj_type) -{ - nm_assert(obj_type > 0); - nm_assert(obj_type <= G_N_ELEMENTS(_nmp_classes)); - nm_assert(_nmp_classes[obj_type - 1].obj_type == obj_type); - nm_assert(NMP_CLASS_IS_VALID(&_nmp_classes[obj_type - 1])); - - return &_nmp_classes[obj_type - 1]; -} - -static inline NMPObject * -NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj) -{ - NMPObject *obj; - - obj = plobj ? (NMPObject *) (&(((char *) plobj)[-((int) G_STRUCT_OFFSET(NMPObject, object))])) - : NULL; - nm_assert(!obj || (obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID(obj->_class))); - return obj; -} -#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST((const NMPlatformObject *) (plobj))) - -static inline gboolean -NMP_OBJECT_IS_VALID(const NMPObject *obj) -{ - nm_assert(!obj || (obj && obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID(obj->_class))); - - /* There isn't really much to check. Either @obj is NULL, or we must - * assume that it points to valid memory. */ - return obj != NULL; -} - -static inline gboolean -NMP_OBJECT_IS_STACKINIT(const NMPObject *obj) -{ - nm_assert(!obj || NMP_OBJECT_IS_VALID(obj)); - - return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT; -} - -static inline const NMPClass * -NMP_OBJECT_GET_CLASS(const NMPObject *obj) -{ - nm_assert(NMP_OBJECT_IS_VALID(obj)); - - return obj->_class; -} - -static inline NMPObjectType -NMP_OBJECT_GET_TYPE(const NMPObject *obj) -{ - nm_assert(!obj || NMP_OBJECT_IS_VALID(obj)); - - return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN; -} - -static inline gboolean -_NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type) -{ - switch (obj_type) { - case NMP_OBJECT_TYPE_LINK: - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - - case NMP_OBJECT_TYPE_QDISC: - - case NMP_OBJECT_TYPE_TFILTER: - - case NMP_OBJECT_TYPE_LNK_BRIDGE: - case NMP_OBJECT_TYPE_LNK_GRE: - case NMP_OBJECT_TYPE_LNK_GRETAP: - case NMP_OBJECT_TYPE_LNK_INFINIBAND: - case NMP_OBJECT_TYPE_LNK_IP6TNL: - case NMP_OBJECT_TYPE_LNK_IP6GRE: - case NMP_OBJECT_TYPE_LNK_IP6GRETAP: - case NMP_OBJECT_TYPE_LNK_IPIP: - case NMP_OBJECT_TYPE_LNK_MACSEC: - case NMP_OBJECT_TYPE_LNK_MACVLAN: - case NMP_OBJECT_TYPE_LNK_MACVTAP: - case NMP_OBJECT_TYPE_LNK_SIT: - case NMP_OBJECT_TYPE_LNK_TUN: - case NMP_OBJECT_TYPE_LNK_VLAN: - case NMP_OBJECT_TYPE_LNK_VRF: - case NMP_OBJECT_TYPE_LNK_VXLAN: - case NMP_OBJECT_TYPE_LNK_WIREGUARD: - return TRUE; - - case NMP_OBJECT_TYPE_ROUTING_RULE: - return FALSE; - - case NMP_OBJECT_TYPE_UNKNOWN: - case __NMP_OBJECT_TYPE_LAST: - break; - } - nm_assert_not_reached(); - return FALSE; -} - -#define NMP_OBJECT_CAST_OBJECT(obj) \ - ({ \ - typeof(obj) _obj = (obj); \ - \ - nm_assert ( !_obj \ - || nmp_class_from_type (NMP_OBJECT_GET_TYPE (_obj)))); \ - _obj ? &NM_CONSTCAST(NMPObject, _obj)->object : NULL; \ - }) - -#define NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj) \ - ({ \ - typeof(obj) _obj = (obj); \ - \ - nm_assert(!_obj || _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMP_OBJECT_GET_TYPE(_obj))); \ - _obj ? &NM_CONSTCAST(NMPObject, _obj)->obj_with_ifindex : NULL; \ - }) - -#define _NMP_OBJECT_CAST(obj, field, ...) \ - ({ \ - typeof(obj) _obj = (obj); \ - \ - nm_assert(!_obj || NM_IN_SET(NMP_OBJECT_GET_TYPE(_obj), __VA_ARGS__)); \ - _obj ? &NM_CONSTCAST(NMPObject, _obj)->field : NULL; \ - }) - -#define NMP_OBJECT_CAST_LINK(obj) _NMP_OBJECT_CAST(obj, link, NMP_OBJECT_TYPE_LINK) -#define NMP_OBJECT_CAST_IP_ADDRESS(obj) \ - _NMP_OBJECT_CAST(obj, ip_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS) -#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) \ - _NMP_OBJECT_CAST(obj, ipx_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS) -#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \ - _NMP_OBJECT_CAST(obj, ip4_address, NMP_OBJECT_TYPE_IP4_ADDRESS) -#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \ - _NMP_OBJECT_CAST(obj, ip6_address, NMP_OBJECT_TYPE_IP6_ADDRESS) -#define NMP_OBJECT_CAST_IP_ROUTE(obj) \ - _NMP_OBJECT_CAST(obj, ip_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) -#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \ - _NMP_OBJECT_CAST(obj, ipx_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) -#define NMP_OBJECT_CAST_IP4_ROUTE(obj) _NMP_OBJECT_CAST(obj, ip4_route, NMP_OBJECT_TYPE_IP4_ROUTE) -#define NMP_OBJECT_CAST_IP6_ROUTE(obj) _NMP_OBJECT_CAST(obj, ip6_route, NMP_OBJECT_TYPE_IP6_ROUTE) -#define NMP_OBJECT_CAST_ROUTING_RULE(obj) \ - _NMP_OBJECT_CAST(obj, routing_rule, NMP_OBJECT_TYPE_ROUTING_RULE) -#define NMP_OBJECT_CAST_QDISC(obj) _NMP_OBJECT_CAST(obj, qdisc, NMP_OBJECT_TYPE_QDISC) -#define NMP_OBJECT_CAST_TFILTER(obj) _NMP_OBJECT_CAST(obj, tfilter, NMP_OBJECT_TYPE_TFILTER) -#define NMP_OBJECT_CAST_LNK_WIREGUARD(obj) \ - _NMP_OBJECT_CAST(obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD) -#define NMP_OBJECT_CAST_LNK_BRIDGE(obj) \ - _NMP_OBJECT_CAST(obj, lnk_bridge, NMP_OBJECT_TYPE_LNK_BRIDGE) - -static inline int -NMP_OBJECT_TYPE_TO_ADDR_FAMILY(NMPObjectType obj_type) -{ - return nmp_class_from_type(obj_type)->addr_family; -} - -static inline int -NMP_OBJECT_GET_ADDR_FAMILY(const NMPObject *obj) -{ - return NMP_OBJECT_GET_CLASS(obj)->addr_family; -} - -static inline const NMPObject * -nmp_object_ref(const NMPObject *obj) -{ - if (!obj) { - /* for convenience, allow NULL. */ - return NULL; - } - - /* ref and unref accept const pointers. NMPObject is supposed to be shared - * and kept immutable. Disallowing to take/return a reference to a const - * NMPObject is cumbersome, because callers are precisely expected to - * keep a ref on the otherwise immutable object. */ - g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL); - g_return_val_if_fail(obj->parent._ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL); - - return (const NMPObject *) nm_dedup_multi_obj_ref((const NMDedupMultiObj *) obj); -} - -static inline void -nmp_object_unref(const NMPObject *obj) -{ - if (obj) { - nm_assert(NMP_OBJECT_IS_VALID(obj)); - - nm_dedup_multi_obj_unref((const NMDedupMultiObj *) obj); - } -} - -#define nm_clear_nmp_object(ptr) \ - ({ \ - typeof(ptr) _ptr = (ptr); \ - typeof(*_ptr) _pptr; \ - gboolean _changed = FALSE; \ - \ - if (_ptr && (_pptr = *_ptr)) { \ - *_ptr = NULL; \ - nmp_object_unref(_pptr); \ - _changed = TRUE; \ - } \ - _changed; \ - }) - -static inline gboolean -nmp_object_ref_set(const NMPObject **pp, const NMPObject *obj) -{ - gboolean _changed = FALSE; - const NMPObject *p; - - nm_assert(!pp || !*pp || NMP_OBJECT_IS_VALID(*pp)); - nm_assert(!obj || NMP_OBJECT_IS_VALID(obj)); - - if (pp && ((p = *pp) != obj)) { - nmp_object_ref(obj); - *pp = obj; - nmp_object_unref(p); - _changed = TRUE; - } - return _changed; -} - -NMPObject *nmp_object_new(NMPObjectType obj_type, gconstpointer plobj); -NMPObject *nmp_object_new_link(int ifindex); - -const NMPObject *nmp_object_stackinit(NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj); - -static inline NMPObject * -nmp_object_stackinit_obj(NMPObject *obj, const NMPObject *src) -{ - return obj == src - ? obj - : (NMPObject *) nmp_object_stackinit(obj, NMP_OBJECT_GET_TYPE(src), &src->object); -} - -const NMPObject *nmp_object_stackinit_id(NMPObject *obj, const NMPObject *src); -const NMPObject *nmp_object_stackinit_id_link(NMPObject *obj, int ifindex); -const NMPObject *nmp_object_stackinit_id_ip4_address(NMPObject *obj, - int ifindex, - guint32 address, - guint8 plen, - guint32 peer_address); -const NMPObject * -nmp_object_stackinit_id_ip6_address(NMPObject *obj, int ifindex, const struct in6_addr *address); - -const char *nmp_object_to_string(const NMPObject * obj, - NMPObjectToStringMode to_string_mode, - char * buf, - gsize buf_size); -void nmp_object_hash_update(const NMPObject *obj, NMHashState *h); -int nmp_object_cmp(const NMPObject *obj1, const NMPObject *obj2); - -static inline gboolean -nmp_object_equal(const NMPObject *obj1, const NMPObject *obj2) -{ - return nmp_object_cmp(obj1, obj2) == 0; -} - -void nmp_object_copy(NMPObject *dst, const NMPObject *src, gboolean id_only); -NMPObject *nmp_object_clone(const NMPObject *obj, gboolean id_only); - -int nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2); -void nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h); -guint nmp_object_id_hash(const NMPObject *obj); - -static inline gboolean -nmp_object_id_equal(const NMPObject *obj1, const NMPObject *obj2) -{ - return nmp_object_id_cmp(obj1, obj2) == 0; -} - -guint nmp_object_indirect_id_hash(gconstpointer a); -gboolean nmp_object_indirect_id_equal(gconstpointer a, gconstpointer b); - -gboolean nmp_object_is_alive(const NMPObject *obj); -gboolean nmp_object_is_visible(const NMPObject *obj); - -void -_nmp_object_fixup_link_udev_fields(NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev); - -static inline void -_nm_auto_nmpobj_cleanup(gpointer p) -{ - nmp_object_unref(*((const NMPObject **) p)); -} -#define nm_auto_nmpobj nm_auto(_nm_auto_nmpobj_cleanup) - -typedef struct _NMPCache NMPCache; - -typedef void (*NMPCachePreHook)(NMPCache * cache, - const NMPObject *old, - const NMPObject *new, - NMPCacheOpsType ops_type, - gpointer user_data); -typedef gboolean (*NMPObjectMatchFn)(const NMPObject *obj, gpointer user_data); - -const NMDedupMultiEntry *nmp_cache_lookup_entry(const NMPCache *cache, const NMPObject *obj); -const NMDedupMultiEntry *nmp_cache_lookup_entry_with_idx_type(const NMPCache * cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj); -const NMDedupMultiEntry *nmp_cache_lookup_entry_link(const NMPCache *cache, int ifindex); -const NMPObject * nmp_cache_lookup_obj(const NMPCache *cache, const NMPObject *obj); -const NMPObject * nmp_cache_lookup_link(const NMPCache *cache, int ifindex); - -typedef struct _NMPLookup NMPLookup; - -struct _NMPLookup { - NMPCacheIdType cache_id_type; - NMPObject selector_obj; -}; - -const NMDedupMultiHeadEntry *nmp_cache_lookup_all(const NMPCache * cache, - NMPCacheIdType cache_id_type, - const NMPObject *select_obj); - -static inline const NMDedupMultiHeadEntry * -nmp_cache_lookup(const NMPCache *cache, const NMPLookup *lookup) -{ - return nmp_cache_lookup_all(cache, lookup->cache_id_type, &lookup->selector_obj); -} - -const NMPLookup *nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type); -const NMPLookup *nmp_lookup_init_link_by_ifname(NMPLookup *lookup, const char *ifname); -const NMPLookup *nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex); -const NMPLookup *nmp_lookup_init_route_default(NMPLookup *lookup, NMPObjectType obj_type); -const NMPLookup *nmp_lookup_init_route_by_weak_id(NMPLookup *lookup, const NMPObject *obj); -const NMPLookup *nmp_lookup_init_ip4_route_by_weak_id(NMPLookup *lookup, - in_addr_t network, - guint plen, - guint32 metric, - guint8 tos); -const NMPLookup *nmp_lookup_init_ip6_route_by_weak_id(NMPLookup * lookup, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen); -const NMPLookup * -nmp_lookup_init_object_by_addr_family(NMPLookup *lookup, NMPObjectType obj_type, int addr_family); - -GArray *nmp_cache_lookup_to_array(const NMDedupMultiHeadEntry *head_entry, - NMPObjectType obj_type, - gboolean visible_only); - -static inline gboolean -nmp_cache_iter_next(NMDedupMultiIter *iter, const NMPObject **out_obj) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next(iter); - nm_assert(!has_next || NMP_OBJECT_IS_VALID(iter->current->obj)); - if (out_obj) - *out_obj = has_next ? iter->current->obj : NULL; - return has_next; -} - -static inline gboolean -nmp_cache_iter_next_link(NMDedupMultiIter *iter, const NMPlatformLink **out_obj) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next(iter); - nm_assert(!has_next || NMP_OBJECT_GET_TYPE(iter->current->obj) == NMP_OBJECT_TYPE_LINK); - if (out_obj) - *out_obj = has_next ? &(((const NMPObject *) iter->current->obj)->link) : NULL; - return has_next; -} - -#define nmp_cache_iter_for_each(iter, head, obj) \ - for (nm_dedup_multi_iter_init((iter), (head)); nmp_cache_iter_next((iter), (obj));) - -#define nmp_cache_iter_for_each_link(iter, head, obj) \ - for (nm_dedup_multi_iter_init((iter), (head)); nmp_cache_iter_next_link((iter), (obj));) - -const NMPObject *nmp_cache_lookup_link_full(const NMPCache * cache, - int ifindex, - const char * ifname, - gboolean visible_only, - NMLinkType link_type, - NMPObjectMatchFn match_fn, - gpointer user_data); - -gboolean nmp_cache_link_connected_for_slave(int ifindex_master, const NMPObject *slave); -gboolean nmp_cache_link_connected_needs_toggle(const NMPCache * cache, - const NMPObject *master, - const NMPObject *potential_slave, - const NMPObject *ignore_slave); -const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex(const NMPCache * cache, - int master_ifindex, - const NMPObject *potential_slave, - const NMPObject *ignore_slave); - -gboolean nmp_cache_use_udev_get(const NMPCache *cache); - -void nmtst_assert_nmp_cache_is_consistent(const NMPCache *cache); - -NMPCacheOpsType nmp_cache_remove(NMPCache * cache, - const NMPObject * obj_needle, - gboolean equals_by_ptr, - gboolean only_dirty, - const NMPObject **out_obj_old); -NMPCacheOpsType nmp_cache_remove_netlink(NMPCache * cache, - const NMPObject * obj_needle, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); -NMPCacheOpsType nmp_cache_update_netlink(NMPCache * cache, - NMPObject * obj_hand_over, - gboolean is_dump, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); -NMPCacheOpsType nmp_cache_update_netlink_route(NMPCache * cache, - NMPObject * obj_hand_over, - gboolean is_dump, - guint16 nlmsgflags, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new, - const NMPObject **out_obj_replace, - gboolean * out_resync_required); -NMPCacheOpsType nmp_cache_update_link_udev(NMPCache * cache, - int ifindex, - struct udev_device *udevice, - const NMPObject ** out_obj_old, - const NMPObject ** out_obj_new); -NMPCacheOpsType nmp_cache_update_link_master_connected(NMPCache * cache, - int ifindex, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); - -static inline const NMDedupMultiEntry * -nmp_cache_reresolve_main_entry(NMPCache * cache, - const NMDedupMultiEntry *entry, - const NMPLookup * lookup) -{ - const NMDedupMultiEntry *main_entry; - - nm_assert(cache); - nm_assert(entry); - nm_assert(lookup); - - if (lookup->cache_id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) { - nm_assert(entry == nmp_cache_lookup_entry(cache, entry->obj)); - return entry; - } - - /* we only track the dirty flag for the OBJECT-TYPE index. That means, - * for other lookup types we need to check the dirty flag of the main-entry. */ - main_entry = nmp_cache_lookup_entry(cache, entry->obj); - - nm_assert(main_entry); - nm_assert(main_entry->obj == entry->obj); - - return main_entry; -} - -void nmp_cache_dirty_set_all_main(NMPCache *cache, const NMPLookup *lookup); - -NMPCache *nmp_cache_new(NMDedupMultiIndex *multi_idx, gboolean use_udev); -void nmp_cache_free(NMPCache *cache); - -static inline void -ASSERT_nmp_cache_ops(const NMPCache * cache, - NMPCacheOpsType ops_type, - const NMPObject *obj_old, - const NMPObject *obj_new) -{ -#if NM_MORE_ASSERTS - nm_assert(cache); - nm_assert(obj_old || obj_new); - nm_assert(!obj_old - || (NMP_OBJECT_IS_VALID(obj_old) && !NMP_OBJECT_IS_STACKINIT(obj_old) - && nmp_object_is_alive(obj_old))); - nm_assert(!obj_new - || (NMP_OBJECT_IS_VALID(obj_new) && !NMP_OBJECT_IS_STACKINIT(obj_new) - && nmp_object_is_alive(obj_new))); - - switch (ops_type) { - case NMP_CACHE_OPS_UNCHANGED: - nm_assert(obj_old == obj_new); - break; - case NMP_CACHE_OPS_ADDED: - nm_assert(!obj_old && obj_new); - break; - case NMP_CACHE_OPS_UPDATED: - nm_assert(obj_old && obj_new && obj_old != obj_new); - break; - case NMP_CACHE_OPS_REMOVED: - nm_assert(obj_old && !obj_new); - break; - default: - nm_assert_not_reached(); - } - - nm_assert(obj_new == NULL || obj_old == NULL || nmp_object_id_equal(obj_new, obj_old)); - nm_assert(!obj_old || !obj_new - || NMP_OBJECT_GET_CLASS(obj_old) == NMP_OBJECT_GET_CLASS(obj_new)); - - nm_assert(obj_new == nmp_cache_lookup_obj(cache, obj_new ?: obj_old)); -#endif -} - -const NMDedupMultiHeadEntry * -nm_platform_lookup_all(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj); - -const NMDedupMultiEntry * -nm_platform_lookup_entry(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj); - -static inline const NMPObject * -nm_platform_lookup_obj(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj) -{ - return nm_dedup_multi_entry_get_obj(nm_platform_lookup_entry(platform, cache_id_type, obj)); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_obj_type(NMPlatform *platform, NMPObjectType obj_type) -{ - NMPLookup lookup; - - nmp_lookup_init_obj_type(&lookup, obj_type); - return nm_platform_lookup(platform, &lookup); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_link_by_ifname(NMPlatform *platform, const char *ifname) -{ - NMPLookup lookup; - - nmp_lookup_init_link_by_ifname(&lookup, ifname); - return nm_platform_lookup(platform, &lookup); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_object(NMPlatform *platform, NMPObjectType obj_type, int ifindex) -{ - NMPLookup lookup; - - nmp_lookup_init_object(&lookup, obj_type, ifindex); - return nm_platform_lookup(platform, &lookup); -} - -static inline GPtrArray * -nm_platform_lookup_object_clone(NMPlatform * platform, - NMPObjectType obj_type, - int ifindex, - NMPObjectPredicateFunc predicate, - gpointer user_data) -{ - NMPLookup lookup; - - nmp_lookup_init_object(&lookup, obj_type, ifindex); - return nm_platform_lookup_clone(platform, &lookup, predicate, user_data); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_route_default(NMPlatform *platform, NMPObjectType obj_type) -{ - NMPLookup lookup; - - nmp_lookup_init_route_default(&lookup, obj_type); - return nm_platform_lookup(platform, &lookup); -} - -static inline GPtrArray * -nm_platform_lookup_route_default_clone(NMPlatform * platform, - NMPObjectType obj_type, - NMPObjectPredicateFunc predicate, - gpointer user_data) -{ - NMPLookup lookup; - - nmp_lookup_init_route_default(&lookup, obj_type); - return nm_platform_lookup_clone(platform, &lookup, predicate, user_data); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_ip4_route_by_weak_id(NMPlatform *platform, - in_addr_t network, - guint plen, - guint32 metric, - guint8 tos) -{ - NMPLookup lookup; - - nmp_lookup_init_ip4_route_by_weak_id(&lookup, network, plen, metric, tos); - return nm_platform_lookup(platform, &lookup); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_ip6_route_by_weak_id(NMPlatform * platform, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen) -{ - NMPLookup lookup; - - nmp_lookup_init_ip6_route_by_weak_id(&lookup, network, plen, metric, src, src_plen); - return nm_platform_lookup(platform, &lookup); -} - -static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_object_by_addr_family(NMPlatform * platform, - NMPObjectType obj_type, - int addr_family) -{ - NMPLookup lookup; - - nmp_lookup_init_object_by_addr_family(&lookup, obj_type, addr_family); - return nm_platform_lookup(platform, &lookup); -} - -/*****************************************************************************/ - -static inline const char * -nmp_object_link_get_ifname(const NMPObject *obj) -{ - if (!obj) - return NULL; - return NMP_OBJECT_CAST_LINK(obj)->name; -} - -static inline gboolean -nmp_object_ip_route_is_best_defaut_route(const NMPObject *obj) -{ - const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE(obj); - - /* return whether @obj is considered a default-route. - * - * NMIP4Config/NMIP6Config tracks the (best) default-route explicitly, because - * at various places we act differently depending on whether there is a default-route - * configured. - * - * Note that this only considers the main routing table. */ - return r && NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) - && nm_platform_route_table_is_main(r->table_coerced) - && r->type_coerced == nm_platform_route_type_coerce(1 /* RTN_UNICAST */); -} - -static inline gboolean -nmp_object_ip6_address_is_not_link_local(const NMPObject *obj) -{ - return !IN6_IS_ADDR_LINKLOCAL(&NMP_OBJECT_CAST_IP6_ADDRESS(obj)->address); -} - -/*****************************************************************************/ - -static inline gboolean -nm_platform_dedup_multi_iter_next_obj(NMDedupMultiIter *ipconf_iter, - const NMPObject **out_obj, - NMPObjectType assert_obj_type) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next(ipconf_iter); - nm_assert(assert_obj_type == NMP_OBJECT_TYPE_UNKNOWN || !has_next - || NMP_OBJECT_GET_TYPE(ipconf_iter->current->obj) == assert_obj_type); - NM_SET_OUT(out_obj, has_next ? ipconf_iter->current->obj : NULL); - return has_next; -} - -#define _nm_platform_dedup_multi_iter_next(ipconf_iter, out_obj, field, ...) \ - ({ \ - NMDedupMultiIter *const _ipconf_iter = (ipconf_iter); \ - const typeof(((NMPObject *) NULL)->field) **const _out_obj = (out_obj); \ - gboolean _has_next; \ - \ - if (G_LIKELY(nm_dedup_multi_iter_next(_ipconf_iter))) { \ - if (_out_obj) { \ - *_out_obj = _NMP_OBJECT_CAST(_ipconf_iter->current->obj, field, __VA_ARGS__); \ - } else { \ - nm_assert( \ - NM_IN_SET(NMP_OBJECT_GET_TYPE(_ipconf_iter->current->obj), __VA_ARGS__)); \ - } \ - _has_next = TRUE; \ - } else { \ - if (_out_obj) \ - *_out_obj = NULL; \ - _has_next = FALSE; \ - } \ - _has_next; \ - }) - -#define nm_platform_dedup_multi_iter_next_ip_address(ipconf_iter, out_obj) \ - _nm_platform_dedup_multi_iter_next((ipconf_iter), \ - (out_obj), \ - ip_address, \ - NMP_OBJECT_TYPE_IP4_ADDRESS, \ - NMP_OBJECT_TYPE_IP6_ADDRESS) - -#define nm_platform_dedup_multi_iter_next_ip4_address(ipconf_iter, out_obj) \ - _nm_platform_dedup_multi_iter_next((ipconf_iter), \ - (out_obj), \ - ip4_address, \ - NMP_OBJECT_TYPE_IP4_ADDRESS) - -#define nm_platform_dedup_multi_iter_next_ip6_address(ipconf_iter, out_obj) \ - _nm_platform_dedup_multi_iter_next((ipconf_iter), \ - (out_obj), \ - ip6_address, \ - NMP_OBJECT_TYPE_IP6_ADDRESS) - -#define nm_platform_dedup_multi_iter_next_ip_route(ipconf_iter, out_obj) \ - _nm_platform_dedup_multi_iter_next((ipconf_iter), \ - (out_obj), \ - ip_route, \ - NMP_OBJECT_TYPE_IP4_ROUTE, \ - NMP_OBJECT_TYPE_IP6_ROUTE) - -#define nm_platform_dedup_multi_iter_next_ip4_route(ipconf_iter, out_obj) \ - _nm_platform_dedup_multi_iter_next((ipconf_iter), \ - (out_obj), \ - ip4_route, \ - NMP_OBJECT_TYPE_IP4_ROUTE) - -#define nm_platform_dedup_multi_iter_next_ip6_route(ipconf_iter, out_obj) \ - _nm_platform_dedup_multi_iter_next((ipconf_iter), \ - (out_obj), \ - ip6_route, \ - NMP_OBJECT_TYPE_IP6_ROUTE) - -#endif /* __NMP_OBJECT_H__ */ diff --git a/src/core/platform/nmp-rules-manager.c b/src/core/platform/nmp-rules-manager.c deleted file mode 100644 index 0c617b80..00000000 --- a/src/core/platform/nmp-rules-manager.c +++ /dev/null @@ -1,808 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "src/core/nm-default-daemon.h" - -#include "nmp-rules-manager.h" - -#include -#include - -#include "nm-std-aux/c-list-util.h" -#include "nmp-object.h" - -/*****************************************************************************/ - -struct _NMPRulesManager { - NMPlatform *platform; - GHashTable *by_obj; - GHashTable *by_user_tag; - GHashTable *by_data; - guint ref_count; -}; - -/*****************************************************************************/ - -static void _rules_init(NMPRulesManager *self); - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG_PREFIX_NAME "rules-manager" - -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ - _nm_log(__level, \ - _NMLOG_DOMAIN, \ - 0, \ - NULL, \ - NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static gboolean -NMP_IS_RULES_MANAGER(gpointer self) -{ - return self && ((NMPRulesManager *) self)->ref_count > 0 - && NM_IS_PLATFORM(((NMPRulesManager *) self)->platform); -} - -#define _USER_TAG_LOG(user_tag) nm_hash_obfuscate_ptr(1240261787u, (user_tag)) - -/*****************************************************************************/ - -typedef struct { - const NMPObject *obj; - gconstpointer user_tag; - CList obj_lst; - CList user_tag_lst; - - /* track_priority_val zero is special: those are weakly tracked rules. - * That means: NetworkManager will restore them only if it removed them earlier. - * But it will not remove or add them otherwise. - * - * Otherwise, the track_priority_val goes together with track_priority_present. - * In case of one rule being tracked multiple times (with different priorities), - * the one with higher priority wins. See _rules_obj_get_best_data(). - * Then, the winning present state either enforces that the rule is present - * or absent. - * - * If a rules is not tracked at all, it is ignored by NetworkManager. Assuming - * that it was added externally by the user. But unlike weakly tracked rules, - * NM will *not* restore such rules if NetworkManager themself removed them. */ - guint32 track_priority_val; - bool track_priority_present : 1; - - bool dirty : 1; -} RulesData; - -typedef enum { - CONFIG_STATE_NONE = 0, - CONFIG_STATE_ADDED_BY_US = 1, - CONFIG_STATE_REMOVED_BY_US = 2, - - /* ConfigState encodes whether the rule was touched by us at all (CONFIG_STATE_NONE). - * - * Maybe we would only need to track whether we touched the rule at all. But we - * track it more in detail what we did: did we add it (CONFIG_STATE_ADDED_BY_US) - * or did we remove it (CONFIG_STATE_REMOVED_BY_US)? - * Finally, we need CONFIG_STATE_OWNED_BY_US, which means that we didn't actively - * add/remove it, but whenever we are about to undo the add/remove, we need to do it. - * In that sense, CONFIG_STATE_OWNED_BY_US is really just a flag that we unconditionally - * force the state next time when necessary. */ - CONFIG_STATE_OWNED_BY_US = 3, -} ConfigState; - -typedef struct { - const NMPObject *obj; - CList obj_lst_head; - - /* indicates whether we configured/removed the rule (during sync()). We need that, so - * if the rule gets untracked, that we know to remove/restore it. - * - * This makes NMPRulesManager stateful (beyond the configuration that indicates - * which rules are tracked). - * After a restart, NetworkManager would no longer remember which rules were added - * by us. - * - * That is partially fixed by NetworkManager taking over the rules that it - * actively configures (see %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG). */ - ConfigState config_state; -} RulesObjData; - -typedef struct { - gconstpointer user_tag; - CList user_tag_lst_head; -} RulesUserTagData; - -/*****************************************************************************/ - -static void _rules_data_untrack(NMPRulesManager *self, - RulesData * rules_data, - gboolean remove_user_tag_data, - gboolean make_owned_by_us); - -/*****************************************************************************/ - -static void -_rules_data_assert(const RulesData *rules_data, gboolean linked) -{ - nm_assert(rules_data); - nm_assert(NMP_OBJECT_GET_TYPE(rules_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE); - nm_assert(nmp_object_is_visible(rules_data->obj)); - nm_assert(rules_data->user_tag); - nm_assert(!linked || !c_list_is_empty(&rules_data->obj_lst)); - nm_assert(!linked || !c_list_is_empty(&rules_data->user_tag_lst)); -} - -static guint -_rules_data_hash(gconstpointer data) -{ - const RulesData *rules_data = data; - NMHashState h; - - _rules_data_assert(rules_data, FALSE); - - nm_hash_init(&h, 269297543u); - nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(rules_data->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, - &h); - nm_hash_update_val(&h, rules_data->user_tag); - return nm_hash_complete(&h); -} - -static gboolean -_rules_data_equal(gconstpointer data_a, gconstpointer data_b) -{ - const RulesData *rules_data_a = data_a; - const RulesData *rules_data_b = data_b; - - _rules_data_assert(rules_data_a, FALSE); - _rules_data_assert(rules_data_b, FALSE); - - return rules_data_a->user_tag == rules_data_b->user_tag - && (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(rules_data_a->obj), - NMP_OBJECT_CAST_ROUTING_RULE(rules_data_b->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) - == 0); -} - -static void -_rules_data_destroy(gpointer data) -{ - RulesData *rules_data = data; - - _rules_data_assert(rules_data, FALSE); - - c_list_unlink_stale(&rules_data->obj_lst); - c_list_unlink_stale(&rules_data->user_tag_lst); - nmp_object_unref(rules_data->obj); - g_slice_free(RulesData, rules_data); -} - -static const RulesData * -_rules_obj_get_best_data(RulesObjData *obj_data) -{ - RulesData * rules_data; - const RulesData *rd_best = NULL; - - c_list_for_each_entry (rules_data, &obj_data->obj_lst_head, obj_lst) { - _rules_data_assert(rules_data, TRUE); - - if (rd_best) { - if (rd_best->track_priority_val > rules_data->track_priority_val) - continue; - if (rd_best->track_priority_val == rules_data->track_priority_val) { - if (rd_best->track_priority_present || !rules_data->track_priority_present) { - /* if the priorities are identical, then "present" wins over - * "!present" (absent). */ - continue; - } - } - } - - rd_best = rules_data; - } - - return rd_best; -} - -static guint -_rules_obj_hash(gconstpointer data) -{ - const RulesObjData *obj_data = data; - NMHashState h; - - nm_hash_init(&h, 432817559u); - nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, - &h); - return nm_hash_complete(&h); -} - -static gboolean -_rules_obj_equal(gconstpointer data_a, gconstpointer data_b) -{ - const RulesObjData *obj_data_a = data_a; - const RulesObjData *obj_data_b = data_b; - - return (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(obj_data_a->obj), - NMP_OBJECT_CAST_ROUTING_RULE(obj_data_b->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) - == 0); -} - -static void -_rules_obj_destroy(gpointer data) -{ - RulesObjData *obj_data = data; - - c_list_unlink_stale(&obj_data->obj_lst_head); - nmp_object_unref(obj_data->obj); - g_slice_free(RulesObjData, obj_data); -} - -static guint -_rules_user_tag_hash(gconstpointer data) -{ - const RulesUserTagData *user_tag_data = data; - - return nm_hash_val(644693447u, user_tag_data->user_tag); -} - -static gboolean -_rules_user_tag_equal(gconstpointer data_a, gconstpointer data_b) -{ - const RulesUserTagData *user_tag_data_a = data_a; - const RulesUserTagData *user_tag_data_b = data_b; - - return user_tag_data_a->user_tag == user_tag_data_b->user_tag; -} - -static void -_rules_user_tag_destroy(gpointer data) -{ - RulesUserTagData *user_tag_data = data; - - c_list_unlink_stale(&user_tag_data->user_tag_lst_head); - g_slice_free(RulesUserTagData, user_tag_data); -} - -static RulesData * -_rules_data_lookup(GHashTable *by_data, const NMPObject *obj, gconstpointer user_tag) -{ - RulesData rules_data_needle = { - .obj = obj, - .user_tag = user_tag, - }; - - return g_hash_table_lookup(by_data, &rules_data_needle); -} - -/** - * nmp_rules_manager_track: - * @self: the #NMPRulesManager instance - * @routing_rule: the #NMPlatformRoutingRule to track or untrack - * @track_priority: the priority for tracking the rule. Note that - * negative values indicate a forced absence of the rule. Priorities - * are compared with their absolute values (with higher absolute - * value being more important). For example, if you track the same - * rule twice, once with priority -5 and +10, then the rule is - * present (because the positive number is more important). - * The special value 0 indicates weakly-tracked rules. - * @user_tag: the tag associated with tracking this rule. The same tag - * must be used to untrack the rule later. - * @user_tag_untrack: if not %NULL, at the same time untrack this user-tag - * for the same rule. Note that this is different from a plain nmp_rules_manager_untrack(), - * because it enforces ownership of the now tracked rule. On the other hand, - * a plain nmp_rules_manager_untrack() merely forgets about the tracking. - * The purpose here is to set this to %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG. - */ -void -nmp_rules_manager_track(NMPRulesManager * self, - const NMPlatformRoutingRule *routing_rule, - gint32 track_priority, - gconstpointer user_tag, - gconstpointer user_tag_untrack) -{ - NMPObject obj_stack; - const NMPObject * p_obj_stack; - RulesData * rules_data; - RulesObjData * obj_data; - RulesUserTagData *user_tag_data; - gboolean changed = FALSE; - guint32 track_priority_val; - gboolean track_priority_present; - - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - g_return_if_fail(routing_rule); - g_return_if_fail(user_tag); - nm_assert(track_priority != G_MININT32); - - _rules_init(self); - - p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule); - - nm_assert(nmp_object_is_visible(p_obj_stack)); - - if (track_priority >= 0) { - track_priority_val = track_priority; - track_priority_present = TRUE; - } else { - track_priority_val = -track_priority; - track_priority_present = FALSE; - } - - rules_data = _rules_data_lookup(self->by_data, p_obj_stack, user_tag); - - if (!rules_data) { - rules_data = g_slice_new(RulesData); - *rules_data = (RulesData){ - .obj = nm_dedup_multi_index_obj_intern(nm_platform_get_multi_idx(self->platform), - p_obj_stack), - .user_tag = user_tag, - .track_priority_val = track_priority_val, - .track_priority_present = track_priority_present, - .dirty = FALSE, - }; - g_hash_table_add(self->by_data, rules_data); - - obj_data = g_hash_table_lookup(self->by_obj, &rules_data->obj); - if (!obj_data) { - obj_data = g_slice_new(RulesObjData); - *obj_data = (RulesObjData){ - .obj = nmp_object_ref(rules_data->obj), - .obj_lst_head = C_LIST_INIT(obj_data->obj_lst_head), - .config_state = CONFIG_STATE_NONE, - }; - g_hash_table_add(self->by_obj, obj_data); - } - c_list_link_tail(&obj_data->obj_lst_head, &rules_data->obj_lst); - - user_tag_data = g_hash_table_lookup(self->by_user_tag, &rules_data->user_tag); - if (!user_tag_data) { - user_tag_data = g_slice_new(RulesUserTagData); - *user_tag_data = (RulesUserTagData){ - .user_tag = user_tag, - .user_tag_lst_head = C_LIST_INIT(user_tag_data->user_tag_lst_head), - }; - g_hash_table_add(self->by_user_tag, user_tag_data); - } - c_list_link_tail(&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst); - changed = TRUE; - } else { - rules_data->dirty = FALSE; - if (rules_data->track_priority_val != track_priority_val - || rules_data->track_priority_present != track_priority_present) { - rules_data->track_priority_val = track_priority_val; - rules_data->track_priority_present = track_priority_present; - changed = TRUE; - } - } - - if (user_tag_untrack) { - if (user_tag != user_tag_untrack) { - RulesData *rules_data_untrack; - - rules_data_untrack = _rules_data_lookup(self->by_data, p_obj_stack, user_tag_untrack); - if (rules_data_untrack) - _rules_data_untrack(self, rules_data_untrack, FALSE, TRUE); - } else - nm_assert_not_reached(); - } - - _rules_data_assert(rules_data, TRUE); - - if (changed) { - _LOGD("routing-rule: track [" NM_HASH_OBFUSCATE_PTR_FMT ",%s%u] \"%s\")", - _USER_TAG_LOG(rules_data->user_tag), - (rules_data->track_priority_val == 0 - ? "" - : (rules_data->track_priority_present ? "+" : "-")), - (guint) rules_data->track_priority_val, - nmp_object_to_string(rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - } -} - -static void -_rules_data_untrack(NMPRulesManager *self, - RulesData * rules_data, - gboolean remove_user_tag_data, - gboolean make_owned_by_us) -{ - RulesObjData *obj_data; - - nm_assert(NMP_IS_RULES_MANAGER(self)); - _rules_data_assert(rules_data, TRUE); - nm_assert(self->by_data); - nm_assert(g_hash_table_lookup(self->by_data, rules_data) == rules_data); - - _LOGD("routing-rule: untrack [" NM_HASH_OBFUSCATE_PTR_FMT "] \"%s\"", - _USER_TAG_LOG(rules_data->user_tag), - nmp_object_to_string(rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - -#if NM_MORE_ASSERTS - { - RulesUserTagData *user_tag_data; - - user_tag_data = g_hash_table_lookup(self->by_user_tag, &rules_data->user_tag); - nm_assert(user_tag_data); - nm_assert(c_list_contains(&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst)); - } -#endif - - nm_assert(!c_list_is_empty(&rules_data->user_tag_lst)); - - obj_data = g_hash_table_lookup(self->by_obj, &rules_data->obj); - nm_assert(obj_data); - nm_assert(c_list_contains(&obj_data->obj_lst_head, &rules_data->obj_lst)); - nm_assert(obj_data == g_hash_table_lookup(self->by_obj, &rules_data->obj)); - - if (make_owned_by_us) { - if (obj_data->config_state == CONFIG_STATE_NONE) { - /* we need to mark this entry that it requires a touch on the next - * sync. */ - obj_data->config_state = CONFIG_STATE_OWNED_BY_US; - } - } else if (remove_user_tag_data && c_list_length_is(&rules_data->user_tag_lst, 1)) - g_hash_table_remove(self->by_user_tag, &rules_data->user_tag); - - /* if obj_data is marked to be "added_by_us" or "removed_by_us", we need to keep this entry - * around for the next sync -- so that we can undo what we did earlier. */ - if (obj_data->config_state == CONFIG_STATE_NONE && c_list_length_is(&rules_data->obj_lst, 1)) - g_hash_table_remove(self->by_obj, &rules_data->obj); - - g_hash_table_remove(self->by_data, rules_data); -} - -void -nmp_rules_manager_untrack(NMPRulesManager * self, - const NMPlatformRoutingRule *routing_rule, - gconstpointer user_tag) -{ - NMPObject obj_stack; - const NMPObject *p_obj_stack; - RulesData * rules_data; - - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - g_return_if_fail(routing_rule); - g_return_if_fail(user_tag); - - _rules_init(self); - - p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule); - - nm_assert(nmp_object_is_visible(p_obj_stack)); - - rules_data = _rules_data_lookup(self->by_data, p_obj_stack, user_tag); - if (rules_data) - _rules_data_untrack(self, rules_data, TRUE, FALSE); -} - -void -nmp_rules_manager_set_dirty(NMPRulesManager *self, gconstpointer user_tag) -{ - RulesData * rules_data; - RulesUserTagData *user_tag_data; - - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - g_return_if_fail(user_tag); - - if (!self->by_data) - return; - - user_tag_data = g_hash_table_lookup(self->by_user_tag, &user_tag); - if (!user_tag_data) - return; - - c_list_for_each_entry (rules_data, &user_tag_data->user_tag_lst_head, user_tag_lst) - rules_data->dirty = TRUE; -} - -void -nmp_rules_manager_untrack_all(NMPRulesManager *self, - gconstpointer user_tag, - gboolean all /* or only dirty */) -{ - RulesData * rules_data; - RulesData * rules_data_safe; - RulesUserTagData *user_tag_data; - - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - g_return_if_fail(user_tag); - - if (!self->by_data) - return; - - user_tag_data = g_hash_table_lookup(self->by_user_tag, &user_tag); - if (!user_tag_data) - return; - - c_list_for_each_entry_safe (rules_data, - rules_data_safe, - &user_tag_data->user_tag_lst_head, - user_tag_lst) { - if (all || rules_data->dirty) - _rules_data_untrack(self, rules_data, FALSE, FALSE); - } - if (c_list_is_empty(&user_tag_data->user_tag_lst_head)) - g_hash_table_remove(self->by_user_tag, user_tag_data); -} - -void -nmp_rules_manager_sync(NMPRulesManager *self, gboolean keep_deleted_rules) -{ - const NMDedupMultiHeadEntry *pl_head_entry; - NMDedupMultiIter pl_iter; - const NMPObject * plobj; - gs_unref_ptrarray GPtrArray *rules_to_delete = NULL; - RulesObjData * obj_data; - GHashTableIter h_iter; - guint i; - const RulesData * rd_best; - - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - - if (!self->by_data) - return; - - _LOGD("sync%s", keep_deleted_rules ? " (don't remove any rules)" : ""); - - pl_head_entry = nm_platform_lookup_obj_type(self->platform, NMP_OBJECT_TYPE_ROUTING_RULE); - if (pl_head_entry) { - nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) { - obj_data = g_hash_table_lookup(self->by_obj, &plobj); - - if (!obj_data) { - /* this rule is not tracked. It was externally added, hence we - * ignore it. */ - continue; - } - - rd_best = _rules_obj_get_best_data(obj_data); - if (rd_best) { - if (rd_best->track_priority_present) { - if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US) - obj_data->config_state = CONFIG_STATE_ADDED_BY_US; - continue; - } - if (rd_best->track_priority_val == 0) { - if (!NM_IN_SET(obj_data->config_state, - CONFIG_STATE_ADDED_BY_US, - CONFIG_STATE_OWNED_BY_US)) { - obj_data->config_state = CONFIG_STATE_NONE; - continue; - } - obj_data->config_state = CONFIG_STATE_NONE; - } - } - - if (keep_deleted_rules) { - _LOGD("forget/leak rule added by us: %s", - nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - continue; - } - - if (!rules_to_delete) - rules_to_delete = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); - - g_ptr_array_add(rules_to_delete, (gpointer) nmp_object_ref(plobj)); - - obj_data->config_state = CONFIG_STATE_REMOVED_BY_US; - } - } - - if (rules_to_delete) { - for (i = 0; i < rules_to_delete->len; i++) - nm_platform_object_delete(self->platform, rules_to_delete->pdata[i]); - } - - g_hash_table_iter_init(&h_iter, self->by_obj); - while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_data, NULL)) { - rd_best = _rules_obj_get_best_data(obj_data); - - if (!rd_best) { - g_hash_table_iter_remove(&h_iter); - continue; - } - - if (!rd_best->track_priority_present) { - if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US) - obj_data->config_state = CONFIG_STATE_REMOVED_BY_US; - continue; - } - if (rd_best->track_priority_val == 0) { - if (!NM_IN_SET(obj_data->config_state, - CONFIG_STATE_REMOVED_BY_US, - CONFIG_STATE_OWNED_BY_US)) { - obj_data->config_state = CONFIG_STATE_NONE; - continue; - } - obj_data->config_state = CONFIG_STATE_NONE; - } - - plobj = - nm_platform_lookup_obj(self->platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj_data->obj); - if (plobj) - continue; - - obj_data->config_state = CONFIG_STATE_ADDED_BY_US; - nm_platform_routing_rule_add(self->platform, - NMP_NLM_FLAG_ADD, - NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj)); - } -} - -void -nmp_rules_manager_track_from_platform(NMPRulesManager *self, - NMPlatform * platform, - int addr_family, - gint32 tracking_priority, - gconstpointer user_tag) -{ - NMPLookup lookup; - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - const NMPObject * o; - - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - - if (!platform) - platform = self->platform; - else - g_return_if_fail(NM_IS_PLATFORM(platform)); - - nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - head_entry = nm_platform_lookup(platform, &lookup); - nmp_cache_iter_for_each (&iter, head_entry, &o) { - const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE(o); - - if (addr_family != AF_UNSPEC && rr->addr_family != addr_family) - continue; - - nmp_rules_manager_track(self, rr, tracking_priority, user_tag, NULL); - } -} - -/*****************************************************************************/ - -void -nmp_rules_manager_track_default(NMPRulesManager *self, - int addr_family, - gint32 track_priority, - gconstpointer user_tag) -{ - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - - nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - /* track the default rules. See also `man ip-rule`. */ - - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) { - nmp_rules_manager_track(self, - &((NMPlatformRoutingRule){ - .addr_family = AF_INET, - .priority = 0, - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - nmp_rules_manager_track(self, - &((NMPlatformRoutingRule){ - .addr_family = AF_INET, - .priority = 32766, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - nmp_rules_manager_track(self, - &((NMPlatformRoutingRule){ - .addr_family = AF_INET, - .priority = 32767, - .table = RT_TABLE_DEFAULT, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - } - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) { - nmp_rules_manager_track(self, - &((NMPlatformRoutingRule){ - .addr_family = AF_INET6, - .priority = 0, - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - nmp_rules_manager_track(self, - &((NMPlatformRoutingRule){ - .addr_family = AF_INET6, - .priority = 32766, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - } -} - -static void -_rules_init(NMPRulesManager *self) -{ - if (self->by_data) - return; - - self->by_data = - g_hash_table_new_full(_rules_data_hash, _rules_data_equal, NULL, _rules_data_destroy); - self->by_obj = - g_hash_table_new_full(_rules_obj_hash, _rules_obj_equal, NULL, _rules_obj_destroy); - self->by_user_tag = g_hash_table_new_full(_rules_user_tag_hash, - _rules_user_tag_equal, - NULL, - _rules_user_tag_destroy); -} - -/*****************************************************************************/ - -NMPRulesManager * -nmp_rules_manager_new(NMPlatform *platform) -{ - NMPRulesManager *self; - - g_return_val_if_fail(NM_IS_PLATFORM(platform), NULL); - - self = g_slice_new(NMPRulesManager); - *self = (NMPRulesManager){ - .ref_count = 1, - .platform = g_object_ref(platform), - }; - return self; -} - -void -nmp_rules_manager_ref(NMPRulesManager *self) -{ - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - - self->ref_count++; -} - -void -nmp_rules_manager_unref(NMPRulesManager *self) -{ - g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - - if (--self->ref_count > 0) - return; - - if (self->by_data) { - g_hash_table_destroy(self->by_user_tag); - g_hash_table_destroy(self->by_obj); - g_hash_table_destroy(self->by_data); - } - g_object_unref(self->platform); - g_slice_free(NMPRulesManager, self); -} diff --git a/src/core/platform/nmp-rules-manager.h b/src/core/platform/nmp-rules-manager.h deleted file mode 100644 index 69cf9075..00000000 --- a/src/core/platform/nmp-rules-manager.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#ifndef __NMP_RULES_MANAGER_H__ -#define __NMP_RULES_MANAGER_H__ - -#include "nm-platform.h" - -/*****************************************************************************/ - -#define NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG ((const void *) nmp_rules_manager_new) - -typedef struct _NMPRulesManager NMPRulesManager; - -NMPRulesManager *nmp_rules_manager_new(NMPlatform *platform); - -void nmp_rules_manager_ref(NMPRulesManager *self); -void nmp_rules_manager_unref(NMPRulesManager *self); - -#define nm_auto_unref_rules_manager nm_auto(_nmp_rules_manager_unref) -NM_AUTO_DEFINE_FCN0(NMPRulesManager *, _nmp_rules_manager_unref, nmp_rules_manager_unref); - -void nmp_rules_manager_track(NMPRulesManager * self, - const NMPlatformRoutingRule *routing_rule, - gint32 track_priority, - gconstpointer user_tag, - gconstpointer user_tag_untrack); - -void nmp_rules_manager_track_default(NMPRulesManager *self, - int addr_family, - gint32 track_priority, - gconstpointer user_tag); - -void nmp_rules_manager_track_from_platform(NMPRulesManager *self, - NMPlatform * platform, - int addr_family, - gint32 tracking_priority, - gconstpointer user_tag); - -void nmp_rules_manager_untrack(NMPRulesManager * self, - const NMPlatformRoutingRule *routing_rule, - gconstpointer user_tag); - -void nmp_rules_manager_set_dirty(NMPRulesManager *self, gconstpointer user_tag); - -void nmp_rules_manager_untrack_all(NMPRulesManager *self, - gconstpointer user_tag, - gboolean all /* or only dirty */); - -void nmp_rules_manager_sync(NMPRulesManager *self, gboolean keep_deleted_rules); - -/*****************************************************************************/ - -#endif /* __NMP_RULES_MANAGER_H__ */ diff --git a/src/core/platform/tests/monitor.c b/src/core/platform/tests/monitor.c index abdf2cd5..ff6fae65 100644 --- a/src/core/platform/tests/monitor.c +++ b/src/core/platform/tests/monitor.c @@ -8,7 +8,7 @@ #include #include -#include "platform/nm-linux-platform.h" +#include "libnm-platform/nm-linux-platform.h" #include "nm-test-utils-core.h" diff --git a/src/core/platform/tests/test-address.c b/src/core/platform/tests/test-address.c index d4d67105..4e1d1d6e 100644 --- a/src/core/platform/tests/test-address.c +++ b/src/core/platform/tests/test-address.c @@ -235,7 +235,7 @@ test_ip4_address_general_2(void) /* Looks like addresses are not announced by kernel when the interface * is down. Link-local IPv6 address is automatically added. */ - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, DEVICE_IFINDEX, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, DEVICE_IFINDEX, IFF_UP, TRUE) >= 0); /* Add/delete notification */ nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); @@ -325,7 +325,7 @@ test_ip4_address_peer(void) g_assert(addr != addr_peer); - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, TRUE) >= 0); accept_signals(address_removed, 0, G_MAXINT); accept_signals(address_added, 0, G_MAXINT); @@ -397,7 +397,7 @@ test_ip4_address_peer_zero(void) peers[1] = addr_peer; peers[2] = 0; - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, TRUE) >= 0); nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers)); for (i = 0; i < G_N_ELEMENTS(peers); i++) { diff --git a/src/core/platform/tests/test-cleanup.c b/src/core/platform/tests/test-cleanup.c index b54eca34..e13bb8c8 100644 --- a/src/core/platform/tests/test-cleanup.c +++ b/src/core/platform/tests/test-cleanup.c @@ -44,9 +44,12 @@ test_cleanup_internal(void) g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL))); accept_signal(link_added); free_signal(link_added); - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, - nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME), - NULL)); + g_assert( + nm_platform_link_change_flags(NM_PLATFORM_GET, + nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME), + IFF_UP, + TRUE) + >= 0); ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); g_assert(ifindex > 0); diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 1b977145..2fc9e836 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -1413,6 +1413,48 @@ nmtstp_ip6_address_del(NMPlatform * platform, } \ G_STMT_END +/* Due to rounding errors with clock_t_to_jiffies()/jiffies_to_clock_t(), kernel cannot + * store all requested values. That means, when we try to configure a bridge with + * the @requested values, the actually configured settings are slightly off, as + * @kernel. + * + * This function takes @requested and returns it as @dst output. All fields + * that might be mangled by kernel (according to @kernel) are adjusted. The + * result is almost identical to @requested, but some fields might be adjusted + * to their @kernel value. */ +const NMPlatformLnkBridge * +nmtstp_link_bridge_normalize_jiffies_time(const NMPlatformLnkBridge *requested, + const NMPlatformLnkBridge *kernel, + NMPlatformLnkBridge * dst) +{ + g_assert(requested); + g_assert(dst); + g_assert(kernel); + + if (dst != requested) + *dst = *requested; + +#define _normalize_field(dst, kernel, field) \ + G_STMT_START \ + { \ + (dst)->field = nmtstp_normalize_jiffies_time((dst)->field, (kernel)->field); \ + } \ + G_STMT_END + + _normalize_field(dst, kernel, forward_delay); + _normalize_field(dst, kernel, hello_time); + _normalize_field(dst, kernel, max_age); + _normalize_field(dst, kernel, ageing_time); + _normalize_field(dst, kernel, mcast_last_member_interval); + _normalize_field(dst, kernel, mcast_membership_interval); + _normalize_field(dst, kernel, mcast_querier_interval); + _normalize_field(dst, kernel, mcast_query_interval); + _normalize_field(dst, kernel, mcast_query_response_interval); + _normalize_field(dst, kernel, mcast_startup_query_interval); + + return dst; +} + const NMPlatformLink * nmtstp_link_bridge_add(NMPlatform * platform, gboolean external_command, @@ -1421,7 +1463,8 @@ nmtstp_link_bridge_add(NMPlatform * platform, { const NMPlatformLink * pllink = NULL; const NMPlatformLnkBridge *ll = NULL; - int r = 0; + NMPlatformLnkBridge lnk_normalized; + int r = 0; g_assert(nm_utils_ifname_valid_kernel(name, NULL)); @@ -1542,10 +1585,9 @@ nmtstp_link_bridge_add(NMPlatform * platform, ll = NMP_OBJECT_CAST_LNK_BRIDGE(NMP_OBJECT_UP_CAST(pllink)->_link.netlink.lnk); - /* account for roundtrip rounding error with clock_t_to_jiffies()/jiffies_to_clock_t(). */ - g_assert_cmpint(lnk->forward_delay, >=, ll->forward_delay - 1); - g_assert_cmpint(lnk->forward_delay, <=, ll->forward_delay); + lnk = nmtstp_link_bridge_normalize_jiffies_time(lnk, ll, &lnk_normalized); + g_assert_cmpint(lnk->forward_delay, ==, ll->forward_delay); g_assert_cmpint(lnk->hello_time, ==, ll->hello_time); g_assert_cmpint(lnk->max_age, ==, ll->max_age); g_assert_cmpint(lnk->ageing_time, ==, ll->ageing_time); @@ -2246,9 +2288,9 @@ nmtstp_link_set_updown(NMPlatform *platform, gboolean external_command, int ifin nmtstp_run_command_check("ip link set %s %s", ifname, up ? "up" : "down"); } else { if (up) - g_assert(nm_platform_link_set_up(platform, ifindex, NULL)); + g_assert(nm_platform_link_change_flags(platform, ifindex, IFF_UP, TRUE) >= 0); else - g_assert(nm_platform_link_set_down(platform, ifindex)); + g_assert(nm_platform_link_change_flags(platform, ifindex, IFF_UP, FALSE) >= 0); } /* Let's wait until we get the result */ diff --git a/src/core/platform/tests/test-common.h b/src/core/platform/tests/test-common.h index 618645fe..1fb97d24 100644 --- a/src/core/platform/tests/test-common.h +++ b/src/core/platform/tests/test-common.h @@ -11,10 +11,10 @@ #include #include -#include "platform/nm-platform.h" -#include "platform/nmp-object.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" #include "platform/nm-fake-platform.h" -#include "platform/nm-linux-platform.h" +#include "libnm-platform/nm-linux-platform.h" #include "nm-test-utils-core.h" @@ -22,6 +22,24 @@ /*****************************************************************************/ +#define nmtstp_normalize_jiffies_time(requested_value, kernel_value) \ + ({ \ + typeof(kernel_value) _kernel_value = (kernel_value); \ + typeof(_kernel_value) _requested_value = (requested_value); \ + \ + /* kernel stores some values (like bridge's forward_delay) in jiffies. When converting + * back and forth (clock_t_to_jiffies()/jiffies_to_clock_t()), the value reported back + * to user space may have rounding errors (of +/- 1), depending on CONFIG_HZ setting. + * + * Normalize the requested_value to the kernel_value, if it look as if a rounding + * error happens. If the difference is larger than +/- 1, no normalization happens! */ \ + \ + ((_requested_value >= (NM_MAX(_kernel_value, 1) - 1)) \ + && (_requested_value <= (NM_MIN(_kernel_value, ~((typeof(_kernel_value)) 0) - 1) + 1))) \ + ? _kernel_value \ + : _requested_value; \ + }) + #define _NMLOG_PREFIX_NAME "platform-test" #define _NMLOG_DOMAIN LOGD_PLATFORM #define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, __VA_ARGS__) @@ -437,6 +455,11 @@ gboolean nmtstp_kernel_support_get(NMPlatformKernelSupportType type); void nmtstp_link_set_updown(NMPlatform *platform, gboolean external_command, int ifindex, gboolean up); +const NMPlatformLnkBridge * +nmtstp_link_bridge_normalize_jiffies_time(const NMPlatformLnkBridge *requested, + const NMPlatformLnkBridge *kernel, + NMPlatformLnkBridge * dst); + const NMPlatformLink *nmtstp_link_bridge_add(NMPlatform * platform, gboolean external_command, const char * name, @@ -519,7 +542,7 @@ _nmtstp_env1_wrapper_setup(const NmtstTestData *test_data) g_assert_cmpint(NMTSTP_ENV1_IFINDEX, ==, -1); if (GPOINTER_TO_INT(p_ifup)) - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, *p_ifindex, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, *p_ifindex, IFF_UP, TRUE) >= 0); nm_platform_process_events(NM_PLATFORM_GET); diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index 3aaa3759..f6c3841e 100644 --- a/src/core/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -11,11 +11,11 @@ #include #include -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-base/nm-ethtool-base.h" -#include "platform/nmp-object.h" -#include "nm-platform/nmp-netns.h" -#include "nm-platform/nm-platform-utils.h" +#include "libnm-glib-aux/nm-io-utils.h" +#include "libnm-base/nm-ethtool-base.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nmp-netns.h" +#include "libnm-platform/nm-platform-utils.h" #include "test-common.h" #include "nm-test-utils-core.h" @@ -48,13 +48,15 @@ test_bogus(void) g_assert(!nm_platform_link_get_type(NM_PLATFORM_GET, BOGUS_IFINDEX)); g_assert(!nm_platform_link_get_type_name(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert(!nm_platform_link_set_up(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); + g_assert(!(nm_platform_link_change_flags(NM_PLATFORM_GET, BOGUS_IFINDEX, IFF_UP, TRUE) >= 0)); - g_assert(!nm_platform_link_set_down(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!(nm_platform_link_change_flags(NM_PLATFORM_GET, BOGUS_IFINDEX, IFF_UP, FALSE) >= 0)); - g_assert(!nm_platform_link_set_arp(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert( + !(nm_platform_link_change_flags(NM_PLATFORM_GET, BOGUS_IFINDEX, IFF_NOARP, TRUE) >= 0)); - g_assert(!nm_platform_link_set_noarp(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert( + !(nm_platform_link_change_flags(NM_PLATFORM_GET, BOGUS_IFINDEX, IFF_NOARP, FALSE) >= 0)); g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, BOGUS_IFINDEX)); g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, BOGUS_IFINDEX)); @@ -147,7 +149,8 @@ software_add(NMLinkType link_type, const char *name) NM_PLATFORM_SIGNAL_CHANGED, link_callback, parent_ifindex); - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, parent_ifindex, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, parent_ifindex, IFF_UP, TRUE) + >= 0); if (was_up) { /* when NM is running in the background, it will mess with addrgenmode which might cause additional signals. */ accept_signals(parent_changed, 0, 1); @@ -233,7 +236,7 @@ test_slave(int master, int type, SignalData *master_changed) * See https://bugzilla.redhat.com/show_bug.cgi?id=910348 */ g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); - g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, FALSE) >= 0); g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); ensure_no_signal(link_changed); @@ -263,7 +266,7 @@ test_slave(int master, int type, SignalData *master_changed) &test_link_changed_signal_arg2); /* Set master up */ - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, master, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, master, IFF_UP, TRUE) >= 0); g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, master)); accept_signals(master_changed, 1, 3); @@ -284,7 +287,7 @@ test_slave(int master, int type, SignalData *master_changed) switch (nm_platform_link_get_type(NM_PLATFORM_GET, master)) { case NM_LINK_TYPE_BOND: case NM_LINK_TYPE_TEAM: - g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, FALSE) >= 0); accept_signal(link_changed); accept_signals(master_changed, 0, 3); break; @@ -317,7 +320,7 @@ test_slave(int master, int type, SignalData *master_changed) } /* Set slave up and see if master gets up too */ - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, TRUE) >= 0); g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, master)); accept_signals(link_changed, 1, 3); @@ -439,10 +442,10 @@ test_software(NMLinkType link_type, const char *link_typename) /* Set ARP/NOARP */ g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); - g_assert(nm_platform_link_set_noarp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_NOARP, TRUE) >= 0); g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); accept_signals(link_changed, 1, 2); - g_assert(nm_platform_link_set_arp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_NOARP, FALSE) >= 0); g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); accept_signal(link_changed); @@ -672,21 +675,21 @@ test_internal(void) /* Up/connected */ g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); - g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, TRUE) >= 0); g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); accept_signals(link_changed, 1, 2); - g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, FALSE) >= 0); g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); accept_signal(link_changed); /* arp/noarp */ g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); - g_assert(nm_platform_link_set_arp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_NOARP, FALSE) >= 0); g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); accept_signal(link_changed); - g_assert(nm_platform_link_set_noarp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_NOARP, TRUE) >= 0); g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); accept_signal(link_changed); @@ -1303,7 +1306,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gre0")) { /* Seems that the ip_gre module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; } if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) { @@ -1330,7 +1333,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gretap0")) { /* Seems that the ip_gre module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; } if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) { @@ -1350,7 +1353,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "tunl0")) { /* Seems that the ipip module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ipip", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ipip", NULL) != 0; } lnk_ipip.local = nmtst_inet4_from_string("1.2.3.4"); @@ -1376,7 +1379,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6tnl0")) { /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_tunnel", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_tunnel", NULL) != 0; } switch (test_data->test_mode) { @@ -1418,7 +1421,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) { /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; } lnk_ip6tnl.local = *nmtst_inet6_from_string("fd01::42"); @@ -1445,7 +1448,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) { /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; } lnk_ip6tnl.local = *nmtst_inet6_from_string("fe80::abcd"); @@ -1526,7 +1529,7 @@ test_software_detect(gconstpointer user_data) if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "sit0")) { /* Seems that the sit module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe(NULL, TRUE, "sit", NULL) != 0; + gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "sit", NULL) != 0; } if (!nmtstp_link_sit_add(NULL, ext, DEVICE_NAME, &lnk_sit)) { @@ -1679,17 +1682,25 @@ test_software_detect(gconstpointer user_data) case NM_LINK_TYPE_BRIDGE: { const NMPlatformLnkBridge *plnk = &lnk->lnk_bridge; + NMPlatformLnkBridge lnk_bridge_norm_stack; + const NMPlatformLnkBridge *lnk_bridge_norm; g_assert(plnk == nm_platform_link_get_lnk_bridge(NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint(nm_platform_lnk_bridge_cmp(&lnk_bridge, plnk), ==, 0); - g_assert_cmpint(plnk->forward_delay, ==, 1560); - g_assert_cmpint(plnk->hello_time, ==, 150); - g_assert_cmpint(plnk->max_age, ==, 2100); - g_assert_cmpint(plnk->ageing_time, ==, 2200); + + lnk_bridge_norm = nmtstp_link_bridge_normalize_jiffies_time(&lnk_bridge, + plnk, + &lnk_bridge_norm_stack); + + g_assert_cmpint(nm_platform_lnk_bridge_cmp(lnk_bridge_norm, plnk), ==, 0); + + g_assert_cmpint(plnk->forward_delay, ==, lnk_bridge_norm->forward_delay); + g_assert_cmpint(plnk->hello_time, ==, lnk_bridge_norm->hello_time); + g_assert_cmpint(plnk->max_age, ==, lnk_bridge_norm->max_age); + g_assert_cmpint(plnk->ageing_time, ==, lnk_bridge_norm->ageing_time); g_assert_cmpint(plnk->stp_state, ==, TRUE); g_assert_cmpint(plnk->priority, ==, 22); g_assert_cmpint(plnk->vlan_protocol, ==, 0x8100); - g_assert_cmpint(plnk->vlan_stats_enabled, ==, lnk_bridge.vlan_stats_enabled); + g_assert_cmpint(plnk->vlan_stats_enabled, ==, lnk_bridge_norm->vlan_stats_enabled); g_assert_cmpint(plnk->group_fwd_mask, ==, 8); g_assert_cmpint(plnk->mcast_snooping, ==, TRUE); g_assert_cmpint(plnk->mcast_router, ==, 1); @@ -1698,13 +1709,22 @@ test_software_detect(gconstpointer user_data) g_assert_cmpint(plnk->mcast_hash_max, ==, 1024); g_assert_cmpint(plnk->mcast_last_member_count, ==, 2); g_assert_cmpint(plnk->mcast_startup_query_count, ==, 3); - g_assert_cmpint(plnk->mcast_last_member_interval, ==, 5000); - g_assert_cmpint(plnk->mcast_membership_interval, ==, 25000); - g_assert_cmpint(plnk->mcast_querier_interval, ==, 26000); - g_assert_cmpint(plnk->mcast_query_interval, ==, 12000); - g_assert_cmpint(plnk->mcast_query_response_interval, ==, 5200); - g_assert_cmpint(plnk->mcast_startup_query_interval, ==, 3000); - g_assert_cmpint(nm_platform_lnk_bridge_cmp(&lnk_bridge, plnk), ==, 0); + g_assert_cmpint(plnk->mcast_last_member_interval, + ==, + lnk_bridge_norm->mcast_last_member_interval); + g_assert_cmpint(plnk->mcast_membership_interval, + ==, + lnk_bridge_norm->mcast_membership_interval); + g_assert_cmpint(plnk->mcast_querier_interval, + ==, + lnk_bridge_norm->mcast_querier_interval); + g_assert_cmpint(plnk->mcast_query_interval, ==, lnk_bridge_norm->mcast_query_interval); + g_assert_cmpint(plnk->mcast_query_response_interval, + ==, + lnk_bridge_norm->mcast_query_response_interval); + g_assert_cmpint(plnk->mcast_startup_query_interval, + ==, + lnk_bridge_norm->mcast_startup_query_interval); break; } case NM_LINK_TYPE_GRE: @@ -2049,7 +2069,7 @@ _assert_xgress_qos_mappings_impl(int ifindex, gboolean is_ingress_map, int n_ent _assert_xgress_qos_mappings(ifindex, FALSE, n_entries, __VA_ARGS__) static void -_assert_vlan_flags(int ifindex, NMVlanFlags flags) +_assert_vlan_flags(int ifindex, _NMVlanFlags flags) { const NMPlatformLnkVlan *plnk; @@ -2362,8 +2382,8 @@ test_vlan_set_xgress(void) g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, ifindex, - NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP, - NM_VLAN_FLAG_REORDER_HEADERS, + _NM_VLAN_FLAG_REORDER_HEADERS | _NM_VLAN_FLAG_GVRP, + _NM_VLAN_FLAG_REORDER_HEADERS, TRUE, ingress_map, G_N_ELEMENTS(ingress_map), @@ -2372,7 +2392,7 @@ test_vlan_set_xgress(void) G_N_ELEMENTS(egress_map))); _assert_ingress_qos_mappings(ifindex, 2, 4, 1, 6, 12); _assert_egress_qos_mappings(ifindex, 2, 1, 5, 3232, 7); - _assert_vlan_flags(ifindex, NM_VLAN_FLAG_REORDER_HEADERS); + _assert_vlan_flags(ifindex, _NM_VLAN_FLAG_REORDER_HEADERS); } { @@ -2393,8 +2413,8 @@ test_vlan_set_xgress(void) g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, ifindex, - NM_VLAN_FLAG_GVRP, - NM_VLAN_FLAG_GVRP, + _NM_VLAN_FLAG_GVRP, + _NM_VLAN_FLAG_GVRP, FALSE, ingress_map, G_N_ELEMENTS(ingress_map), @@ -2403,7 +2423,7 @@ test_vlan_set_xgress(void) G_N_ELEMENTS(egress_map))); _assert_ingress_qos_mappings(ifindex, 2, 4, 1, 6, 12); _assert_egress_qos_mappings(ifindex, 2, 1, 7, 64, 4); - _assert_vlan_flags(ifindex, NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP); + _assert_vlan_flags(ifindex, _NM_VLAN_FLAG_REORDER_HEADERS | _NM_VLAN_FLAG_GVRP); } nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE); diff --git a/src/core/platform/tests/test-nmp-object.c b/src/core/platform/tests/test-nmp-object.c index 310611ee..6d2236ec 100644 --- a/src/core/platform/tests/test-nmp-object.c +++ b/src/core/platform/tests/test-nmp-object.c @@ -8,8 +8,8 @@ #include #include -#include "platform/nmp-object.h" -#include "nm-udev-aux/nm-udev-utils.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-udev-aux/nm-udev-utils.h" #include "nm-test-utils-core.h" diff --git a/src/core/platform/tests/test-platform-general.c b/src/core/platform/tests/test-platform-general.c index b426cc65..05158228 100644 --- a/src/core/platform/tests/test-platform-general.c +++ b/src/core/platform/tests/test-platform-general.c @@ -7,8 +7,8 @@ #include -#include "nm-platform/nm-platform-utils.h" -#include "platform/nm-linux-platform.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-platform/nm-linux-platform.h" #include "nm-test-utils-core.h" @@ -584,7 +584,7 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) nmtst_stable_rand(710086081, rand_map, sizeof(rand_map[0]) * N_ADDRESSES); for (i = 0; i < N_ADDRESSES; i++) { - NMPlatformIPXAddress *a = (gpointer)(&addresses[i * ELM_SIZE]); + NMPlatformIPXAddress *a = (gpointer) (&addresses[i * ELM_SIZE]); guint64 r = rand_map[i]; struct in6_addr * a6; @@ -684,10 +684,10 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) (gpointer) test_data); for (i = 0; i < N_ADDRESSES; i++) { - const NMPlatformIPXAddress *a = (gconstpointer)(&addresses[i * ELM_SIZE]); + const NMPlatformIPXAddress *a = (gconstpointer) (&addresses[i * ELM_SIZE]); for (j = i + 1; j < N_ADDRESSES; j++) { - const NMPlatformIPXAddress *b = (gconstpointer)(&addresses[j * ELM_SIZE]); + const NMPlatformIPXAddress *b = (gconstpointer) (&addresses[j * ELM_SIZE]); int c1; int c2; diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index 645bb5b1..4b1db7fa 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -9,8 +9,8 @@ #include #include "nm-core-utils.h" -#include "nm-platform/nm-platform-utils.h" -#include "platform/nmp-rules-manager.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-platform/nmp-rules-manager.h" #include "test-common.h" @@ -332,30 +332,33 @@ test_ip4_route(void) /* Test route listing */ routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex); memset(rts, 0, sizeof(rts)); - rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); - rts[0].network = gateway; - rts[0].plen = 32; - rts[0].ifindex = ifindex; - rts[0].gateway = INADDR_ANY; - rts[0].metric = metric; - rts[0].mss = mss; - rts[0].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_LINK); - rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); - rts[1].network = network; - rts[1].plen = plen; - rts[1].ifindex = ifindex; - rts[1].gateway = gateway; - rts[1].metric = metric; - rts[1].mss = mss; - rts[1].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE); - rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); - rts[2].network = 0; - rts[2].plen = 0; - rts[2].ifindex = ifindex; - rts[2].gateway = gateway; - rts[2].metric = metric; - rts[2].mss = mss; - rts[2].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE); + rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[0].network = gateway; + rts[0].plen = 32; + rts[0].ifindex = ifindex; + rts[0].gateway = INADDR_ANY; + rts[0].metric = metric; + rts[0].mss = mss; + rts[0].is_external = TRUE; + rts[0].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_LINK); + rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[1].network = network; + rts[1].plen = plen; + rts[1].ifindex = ifindex; + rts[1].gateway = gateway; + rts[1].metric = metric; + rts[1].mss = mss; + rts[1].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE); + rts[1].is_external = TRUE; + rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[2].network = 0; + rts[2].plen = 0; + rts[2].ifindex = ifindex; + rts[2].gateway = gateway; + rts[2].metric = metric; + rts[2].mss = mss; + rts[2].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE); + rts[2].is_external = TRUE; g_assert_cmpint(routes->len, ==, 3); nmtst_platform_ip4_routes_equal_aptr((const NMPObject *const *) routes->pdata, rts, @@ -489,30 +492,33 @@ test_ip6_route(void) /* Test route listing */ routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex); memset(rts, 0, sizeof(rts)); - rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); - rts[0].network = gateway; - rts[0].plen = 128; - rts[0].ifindex = ifindex; - rts[0].gateway = in6addr_any; - rts[0].pref_src = in6addr_any; - rts[0].metric = metric; - rts[0].mss = mss; - rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); - rts[1].network = network; - rts[1].plen = plen; - rts[1].ifindex = ifindex; - rts[1].gateway = gateway; - rts[1].pref_src = pref_src; - rts[1].metric = metric; - rts[1].mss = mss; - rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); - rts[2].network = in6addr_any; - rts[2].plen = 0; - rts[2].ifindex = ifindex; - rts[2].gateway = gateway; - rts[2].pref_src = in6addr_any; - rts[2].metric = metric; - rts[2].mss = mss; + rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[0].network = gateway; + rts[0].plen = 128; + rts[0].ifindex = ifindex; + rts[0].gateway = in6addr_any; + rts[0].pref_src = in6addr_any; + rts[0].metric = metric; + rts[0].mss = mss; + rts[0].is_external = TRUE; + rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[1].network = network; + rts[1].plen = plen; + rts[1].ifindex = ifindex; + rts[1].gateway = gateway; + rts[1].pref_src = pref_src; + rts[1].metric = metric; + rts[1].mss = mss; + rts[1].is_external = TRUE; + rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[2].network = in6addr_any; + rts[2].plen = 0; + rts[2].ifindex = ifindex; + rts[2].gateway = gateway; + rts[2].pref_src = in6addr_any; + rts[2].metric = metric; + rts[2].mss = mss; + rts[2].is_external = TRUE; g_assert_cmpint(routes->len, ==, 3); nmtst_platform_ip6_routes_equal_aptr((const NMPObject *const *) routes->pdata, rts, @@ -709,6 +715,7 @@ test_ip4_route_options(gconstpointer test_data) for (i = 0; i < rts_n; i++) { rts_cmp[i] = rts_add[i]; nm_platform_ip_route_normalize(AF_INET, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i])); + rts_cmp[i].is_external = TRUE; } routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, IFINDEX); @@ -880,6 +887,7 @@ test_ip6_route_options(gconstpointer test_data) for (i = 0; i < rts_n; i++) { rts_cmp[i] = rts_add[i]; nm_platform_ip_route_normalize(AF_INET6, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i])); + rts_cmp[i].is_external = TRUE; } routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, IFINDEX); diff --git a/src/core/platform/tests/test-tc.c b/src/core/platform/tests/test-tc.c index d15c3d76..cd9536cc 100644 --- a/src/core/platform/tests/test-tc.c +++ b/src/core/platform/tests/test-tc.c @@ -5,9 +5,9 @@ #include #include "nm-test-utils-core.h" -#include "platform/nmp-object.h" -#include "nm-platform/nmp-netns.h" -#include "nm-platform/nm-platform-utils.h" +#include "libnm-platform/nmp-object.h" +#include "libnm-platform/nmp-netns.h" +#include "libnm-platform/nm-platform-utils.h" #include "test-common.h" static NMPObject * diff --git a/src/core/platform/wifi/nm-wifi-utils-nl80211.c b/src/core/platform/wifi/nm-wifi-utils-nl80211.c deleted file mode 100644 index ad067248..00000000 --- a/src/core/platform/wifi/nm-wifi-utils-nl80211.c +++ /dev/null @@ -1,909 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2005 - 2018 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - * Copyright (C) 2011 Intel Corporation. All rights reserved. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-wifi-utils-nl80211.h" - -#include -#include -#include -#include -#include - -#include "nm-platform/nm-netlink.h" -#include "nm-wifi-utils-private.h" -#include "platform/nm-platform.h" -#include "nm-platform/nm-platform-utils.h" -#include "nm-utils.h" - -#define _NMLOG_PREFIX_NAME "wifi-nl80211" -#define _NMLOG_DOMAIN LOGD_PLATFORM | LOGD_WIFI -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - char _ifname_buf[IFNAMSIZ]; \ - const char *_ifname = \ - self ? nmp_utils_if_indextoname(self->parent.ifindex, _ifname_buf) : NULL; \ - \ - nm_log((level), \ - _NMLOG_DOMAIN, \ - _ifname ?: NULL, \ - NULL, \ - "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - NM_PRINT_FMT_QUOTED(_ifname, " (", _ifname, ")", "") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -typedef struct { - NMWifiUtils parent; - struct nl_sock *nl_sock; - guint32 * freqs; - int id; - int num_freqs; - int phy; - bool can_wowlan : 1; -} NMWifiUtilsNl80211; - -typedef struct { - NMWifiUtilsClass parent; -} NMWifiUtilsNl80211Class; - -G_DEFINE_TYPE(NMWifiUtilsNl80211, nm_wifi_utils_nl80211, NM_TYPE_WIFI_UTILS) - -static int -ack_handler(struct nl_msg *msg, void *arg) -{ - int *done = arg; - *done = 1; - return NL_STOP; -} - -static int -finish_handler(struct nl_msg *msg, void *arg) -{ - int *done = arg; - *done = 1; - return NL_SKIP; -} - -static int -error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) -{ - int *done = arg; - *done = err->error; - return NL_SKIP; -} - -static struct nl_msg * -_nl80211_alloc_msg(int id, int ifindex, int phy, guint32 cmd, guint32 flags) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nlmsg_alloc(); - genlmsg_put(msg, 0, 0, id, 0, flags, cmd, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - if (phy != -1) - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, phy); - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static struct nl_msg * -nl80211_alloc_msg(NMWifiUtilsNl80211 *self, guint32 cmd, guint32 flags) -{ - return _nl80211_alloc_msg(self->id, self->parent.ifindex, self->phy, cmd, flags); -} - -static int -nl80211_send_and_recv(NMWifiUtilsNl80211 *self, - struct nl_msg * msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - int err; - int done = 0; - const struct nl_cb cb = { - .err_cb = error_handler, - .err_arg = &done, - .finish_cb = finish_handler, - .finish_arg = &done, - .ack_cb = ack_handler, - .ack_arg = &done, - .valid_cb = valid_handler, - .valid_arg = valid_data, - }; - - g_return_val_if_fail(msg != NULL, -ENOMEM); - - err = nl_send_auto(self->nl_sock, msg); - if (err < 0) - return err; - - /* Loop until one of our NL callbacks says we're done; on success - * done will be 1, on error it will be < 0. - */ - while (!done) { - err = nl_recvmsgs(self->nl_sock, &cb); - if (err < 0 && err != -EAGAIN) { - /* Kernel scan list can change while we are dumping it, as new scan - * results from H/W can arrive. BSS info is assured to be consistent - * and we don't need consistent view of whole scan list. Hence do - * not warn on DUMP_INTR error for get scan command. - */ - if (err == -NME_NL_DUMP_INTR - && genlmsg_hdr(nlmsg_hdr(msg))->cmd == NL80211_CMD_GET_SCAN) - break; - - _LOGW("nl_recvmsgs() error: (%d) %s", err, nm_strerror(err)); - break; - } - } - - if (err >= 0 && done < 0) - err = done; - return err; -} - -static void -dispose(GObject *object) -{ - NMWifiUtilsNl80211 *self = NM_WIFI_UTILS_NL80211(object); - - nm_clear_g_free(&self->freqs); -} - -struct nl80211_iface_info { - NM80211Mode mode; - uint32_t freq; -}; - -static int -nl80211_iface_info_handler(struct nl_msg *msg, void *arg) -{ - struct nl80211_iface_info *info = arg; - struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr * tb[NL80211_ATTR_MAX + 1]; - - if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) - return NL_SKIP; - - if (!tb[NL80211_ATTR_IFTYPE]) - return NL_SKIP; - - switch (nla_get_u32(tb[NL80211_ATTR_IFTYPE])) { - case NL80211_IFTYPE_ADHOC: - info->mode = NM_802_11_MODE_ADHOC; - break; - case NL80211_IFTYPE_AP: - info->mode = NM_802_11_MODE_AP; - break; - case NL80211_IFTYPE_STATION: - info->mode = NM_802_11_MODE_INFRA; - break; - case NL80211_IFTYPE_MESH_POINT: - info->mode = NM_802_11_MODE_MESH; - break; - } - - if (tb[NL80211_ATTR_WIPHY_FREQ] != NULL) - info->freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); - - return NL_SKIP; -} - -static NM80211Mode -wifi_nl80211_get_mode(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - struct nl80211_iface_info iface_info = { - .mode = NM_802_11_MODE_UNKNOWN, - }; - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_INTERFACE, 0); - - if (nl80211_send_and_recv(self, msg, nl80211_iface_info_handler, &iface_info) < 0) - return NM_802_11_MODE_UNKNOWN; - - return iface_info.mode; -} - -static gboolean -wifi_nl80211_set_mode(NMWifiUtils *data, const NM80211Mode mode) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg(self, NL80211_CMD_SET_INTERFACE, 0); - - switch (mode) { - case NM_802_11_MODE_INFRA: - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_STATION); - break; - case NM_802_11_MODE_ADHOC: - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_ADHOC); - break; - case NM_802_11_MODE_AP: - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP); - break; - case NM_802_11_MODE_MESH: - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MESH_POINT); - break; - default: - g_assert_not_reached(); - } - - err = nl80211_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -wifi_nl80211_set_powersave(NMWifiUtils *data, guint32 powersave) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg(self, NL80211_CMD_SET_POWER_SAVE, 0); - NLA_PUT_U32(msg, - NL80211_ATTR_PS_STATE, - powersave == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED); - err = nl80211_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static int -nl80211_get_wake_on_wlan_handler(struct nl_msg *msg, void *arg) -{ - NMSettingWirelessWakeOnWLan *wowl = arg; - struct nlattr * attrs[NL80211_ATTR_MAX + 1]; - struct nlattr * trig[NUM_NL80211_WOWLAN_TRIG]; - struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - - nla_parse_arr(attrs, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); - - if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) - return NL_SKIP; - - nla_parse_arr(trig, - nla_data(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), - nla_len(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), - NULL); - - *wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE; - if (trig[NL80211_WOWLAN_TRIG_ANY]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY; - if (trig[NL80211_WOWLAN_TRIG_DISCONNECT]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT; - if (trig[NL80211_WOWLAN_TRIG_MAGIC_PKT]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC; - if (trig[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE; - if (trig[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST; - if (trig[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE; - if (trig[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE; - if (trig[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP; - - return NL_SKIP; -} - -static NMSettingWirelessWakeOnWLan -wifi_nl80211_get_wake_on_wlan(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - NMSettingWirelessWakeOnWLan wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WOWLAN, 0); - - nl80211_send_and_recv(self, msg, nl80211_get_wake_on_wlan_handler, &wowl); - - return wowl; -} - -static gboolean -wifi_nl80211_set_wake_on_wlan(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr * triggers; - int err; - - if (wowl == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) - return TRUE; - - msg = nl80211_alloc_msg(self, NL80211_CMD_SET_WOWLAN, 0); - - triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); - if (!triggers) - goto nla_put_failure; - - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); - if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE)) - NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); - - nla_nest_end(msg, triggers); - - err = nl80211_send_and_recv(self, msg, NULL, NULL); - - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static guint32 -wifi_nl80211_get_freq(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - struct nl80211_iface_info iface_info = {}; - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_INTERFACE, 0); - - if (nl80211_send_and_recv(self, msg, nl80211_iface_info_handler, &iface_info) < 0) - return 0; - - return iface_info.freq; -} - -static guint32 -wifi_nl80211_find_freq(NMWifiUtils *data, const guint32 *freqs) -{ - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - int i; - - for (i = 0; i < self->num_freqs; i++) { - while (*freqs) { - if (self->freqs[i] == *freqs) - return *freqs; - freqs++; - } - } - return 0; -} - -/* @divisor: pass what value @xbm should be divided by to get dBm */ -static guint32 -nl80211_xbm_to_percent(gint32 xbm, guint32 divisor) -{ -#define NOISE_FLOOR_DBM -90 -#define SIGNAL_MAX_DBM -20 - - xbm /= divisor; - xbm = CLAMP(xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM); - - return 100 - - 70 - * (((float) SIGNAL_MAX_DBM - (float) xbm) - / ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM)); -} - -struct nl80211_station_info { - gboolean valid; - guint8 bssid[ETH_ALEN]; - guint32 txrate; - gboolean txrate_valid; - guint8 signal; - gboolean signal_valid; -}; - -static int -nl80211_station_dump_handler(struct nl_msg *msg, void *arg) -{ - static const struct nla_policy stats_policy[] = { - [NL80211_STA_INFO_INACTIVE_TIME] = {.type = NLA_U32}, - [NL80211_STA_INFO_RX_BYTES] = {.type = NLA_U32}, - [NL80211_STA_INFO_TX_BYTES] = {.type = NLA_U32}, - [NL80211_STA_INFO_RX_PACKETS] = {.type = NLA_U32}, - [NL80211_STA_INFO_TX_PACKETS] = {.type = NLA_U32}, - [NL80211_STA_INFO_SIGNAL] = {.type = NLA_U8}, - [NL80211_STA_INFO_TX_BITRATE] = {.type = NLA_NESTED}, - [NL80211_STA_INFO_LLID] = {.type = NLA_U16}, - [NL80211_STA_INFO_PLID] = {.type = NLA_U16}, - [NL80211_STA_INFO_PLINK_STATE] = {.type = NLA_U8}, - [NL80211_STA_INFO_STA_FLAGS] = {.minlen = sizeof(struct nl80211_sta_flag_update)}, - [NL80211_STA_INFO_BEACON_SIGNAL_AVG] = {.type = NLA_U8}, - }; - static const struct nla_policy rate_policy[] = { - [NL80211_RATE_INFO_BITRATE] = {.type = NLA_U16}, - [NL80211_RATE_INFO_MCS] = {.type = NLA_U8}, - [NL80211_RATE_INFO_40_MHZ_WIDTH] = {.type = NLA_FLAG}, - [NL80211_RATE_INFO_SHORT_GI] = {.type = NLA_FLAG}, - }; - struct nlattr * rinfo[G_N_ELEMENTS(rate_policy)]; - struct nlattr * sinfo[G_N_ELEMENTS(stats_policy)]; - struct nl80211_station_info *info = arg; - struct nlattr * tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - - if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) - return NL_SKIP; - - if (tb[NL80211_ATTR_MAC] == NULL) - return NL_SKIP; - - if (tb[NL80211_ATTR_STA_INFO] == NULL) - return NL_SKIP; - - if (nla_parse_nested_arr(sinfo, tb[NL80211_ATTR_STA_INFO], stats_policy)) - return NL_SKIP; - - if (sinfo[NL80211_STA_INFO_STA_FLAGS] != NULL) { - const struct nl80211_sta_flag_update *flags = nla_data(sinfo[NL80211_STA_INFO_STA_FLAGS]); - - if (flags->mask & ~flags->set & (1 << NL80211_STA_FLAG_ASSOCIATED)) - return NL_SKIP; - } - - memcpy(info->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN); - info->valid = TRUE; - - if (sinfo[NL80211_STA_INFO_TX_BITRATE] != NULL - && !nla_parse_nested_arr(rinfo, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy) - && rinfo[NL80211_RATE_INFO_BITRATE] != NULL) { - /* convert from nl80211's units of 100kbps to NM's kbps */ - info->txrate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100; - info->txrate_valid = TRUE; - } - - if (sinfo[NL80211_STA_INFO_SIGNAL] != NULL) { - info->signal = - nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]), 1); - info->signal_valid = TRUE; - } else if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG] != NULL) { - /* Fall back to beacon signal strength */ - info->signal = - nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]), - 1); - info->signal_valid = TRUE; - } - - return NL_SKIP; -} - -static gboolean -wifi_nl80211_get_station(NMWifiUtils *data, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nl80211_station_info sta_info = {}; - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, NLM_F_DUMP); - - nl80211_send_and_recv(self, msg, nl80211_station_dump_handler, &sta_info); - - if (!sta_info.valid || (out_quality && !sta_info.signal_valid) - || (out_rate && !sta_info.txrate_valid)) - return FALSE; - - if (out_bssid) - memcpy(out_bssid, sta_info.bssid, ETH_ALEN); - - if (out_quality) - *out_quality = sta_info.signal; - - if (out_rate) - *out_rate = sta_info.txrate; - - return TRUE; -} - -static gboolean -wifi_nl80211_indicate_addressing_running(NMWifiUtils *data, gboolean running) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg(self, - running ? 98 /* NL80211_CMD_CRIT_PROTOCOL_START */ - : 99 /* NL80211_CMD_CRIT_PROTOCOL_STOP */, - 0); - /* Despite the DHCP name, we're using this for any type of IP addressing, - * DHCPv4, DHCPv6, and IPv6 SLAAC. - */ - NLA_PUT_U16(msg, 179 /* NL80211_ATTR_CRIT_PROT_ID */, 1 /* NL80211_CRIT_PROTO_DHCP */); - if (running) { - /* Give DHCP 5 seconds to complete */ - NLA_PUT_U16(msg, 180 /* NL80211_ATTR_MAX_CRIT_PROT_DURATION */, 5000); - } - - err = nl80211_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -struct nl80211_device_info { - NMWifiUtilsNl80211 *self; - int phy; - guint32 * freqs; - int num_freqs; - guint32 freq; - guint32 caps; - gboolean can_scan; - gboolean can_scan_ssid; - gboolean supported; - gboolean success; - gboolean can_wowlan; -}; - -#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 -#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 -#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 -#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 -#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 -#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 -#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 -#define WLAN_CIPHER_SUITE_SMS4 0x00147201 - -static int -nl80211_wiphy_info_handler(struct nl_msg *msg, void *arg) -{ - static const struct nla_policy freq_policy[] = { - [NL80211_FREQUENCY_ATTR_FREQ] = {.type = NLA_U32}, - [NL80211_FREQUENCY_ATTR_DISABLED] = {.type = NLA_FLAG}, -#ifdef NL80211_FREQUENCY_ATTR_NO_IR - [NL80211_FREQUENCY_ATTR_NO_IR] = {.type = NLA_FLAG}, -#else - [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = {.type = NLA_FLAG}, - [NL80211_FREQUENCY_ATTR_NO_IBSS] = {.type = NLA_FLAG}, -#endif - [NL80211_FREQUENCY_ATTR_RADAR] = {.type = NLA_FLAG}, - [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = {.type = NLA_U32}, - }; - struct nlattr * tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nl80211_device_info *info = arg; - NMWifiUtilsNl80211 * self = info->self; - struct nlattr * tb_band[NL80211_BAND_ATTR_MAX + 1]; - struct nlattr * tb_freq[G_N_ELEMENTS(freq_policy)]; - struct nlattr * nl_band; - struct nlattr * nl_freq; - int rem_freq; - int rem_band; - int freq_idx; - -#ifdef NL80211_FREQUENCY_ATTR_NO_IR - G_STATIC_ASSERT_EXPR(NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR - && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR); -#else - G_STATIC_ASSERT_EXPR(NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS); -#endif - - if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) - return NL_SKIP; - - if (tb[NL80211_ATTR_WIPHY] == NULL || tb[NL80211_ATTR_WIPHY_BANDS] == NULL) - return NL_SKIP; - - info->phy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); - - if (tb[NL80211_ATTR_WIPHY_FREQ]) - info->freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); - else - info->freq = 0; - - if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) { - info->can_scan_ssid = nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) > 0; - } else { - /* old kernel that only had mac80211, so assume it can */ - info->can_scan_ssid = TRUE; - } - - if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { - struct nlattr *nl_cmd; - int i; - - nla_for_each_nested (nl_cmd, tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { - switch (nla_get_u32(nl_cmd)) { - case NL80211_CMD_TRIGGER_SCAN: - info->can_scan = TRUE; - break; - case NL80211_CMD_CONNECT: - case NL80211_CMD_AUTHENTICATE: - /* Only devices that support CONNECT or AUTH actually support - * 802.11, unlike say ipw2x00 (up to at least kernel 3.4) which - * has minimal info support, but no actual command support. - * This check mirrors what wpa_supplicant does to determine - * whether or not to use the nl80211 driver. - */ - info->supported = TRUE; - break; - default: - break; - } - } - } - - /* Find number of supported frequencies */ - info->num_freqs = 0; - - nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { - if (nla_parse_nested_arr(tb_band, nl_band, NULL) < 0) - return NL_SKIP; - - nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - if (nla_parse_nested_arr(tb_freq, nl_freq, freq_policy) < 0) - continue; - - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - info->num_freqs++; - } - } - - /* Read supported frequencies */ - info->freqs = g_malloc0(sizeof(guint32) * info->num_freqs); - - freq_idx = 0; - nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { - if (nla_parse_nested_arr(tb_band, nl_band, NULL) < 0) - return NL_SKIP; - - nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - if (nla_parse_nested_arr(tb_freq, nl_freq, freq_policy) < 0) - continue; - - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - info->freqs[freq_idx] = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - - info->caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID; - - if (info->freqs[freq_idx] > 2400 && info->freqs[freq_idx] < 2500) - info->caps |= NM_WIFI_DEVICE_CAP_FREQ_2GHZ; - if (info->freqs[freq_idx] > 4900 && info->freqs[freq_idx] < 6000) - info->caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; - - freq_idx++; - } - } - - /* Read security/encryption support */ - if (tb[NL80211_ATTR_CIPHER_SUITES]) { - guint32 *ciphers = nla_data(tb[NL80211_ATTR_CIPHER_SUITES]); - guint i, num; - - num = nla_len(tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof(guint32); - for (i = 0; i < num; i++) { - switch (ciphers[i]) { - case WLAN_CIPHER_SUITE_WEP40: - info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40; - break; - case WLAN_CIPHER_SUITE_WEP104: - info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP104; - break; - case WLAN_CIPHER_SUITE_TKIP: - info->caps |= (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_WPA); - break; - case WLAN_CIPHER_SUITE_CCMP: - info->caps |= (NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN); - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - case WLAN_CIPHER_SUITE_GCMP: - case WLAN_CIPHER_SUITE_SMS4: - break; - default: - _LOGD("don't know the meaning of NL80211_ATTR_CIPHER_SUITE %#8.8x.", ciphers[i]); - break; - } - } - } - - if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { - struct nlattr *nl_mode; - int i; - - nla_for_each_nested (nl_mode, tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { - switch (nla_type(nl_mode)) { - case NL80211_IFTYPE_AP: - info->caps |= NM_WIFI_DEVICE_CAP_AP; - break; - case NL80211_IFTYPE_ADHOC: - info->caps |= NM_WIFI_DEVICE_CAP_ADHOC; - break; - case NL80211_IFTYPE_MESH_POINT: - info->caps |= NM_WIFI_DEVICE_CAP_MESH; - break; - } - } - } - - if (tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]) - info->can_wowlan = TRUE; - - if (tb[NL80211_ATTR_SUPPORT_IBSS_RSN]) - info->caps |= NM_WIFI_DEVICE_CAP_IBSS_RSN; - - info->success = TRUE; - - return NL_SKIP; -} - -static guint32 -wifi_nl80211_get_mesh_channel(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nl80211_device_info device_info = {.self = self}; - int i; - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WIPHY, 0); - - if (nl80211_send_and_recv(self, msg, nl80211_wiphy_info_handler, &device_info) < 0) { - _LOGW("NL80211_CMD_GET_WIPHY request failed"); - return 0; - } - - for (i = 0; i < self->num_freqs; i++) { - if (device_info.freq == self->freqs[i]) - return i + 1; - } - return 0; -} - -static gboolean -wifi_nl80211_set_mesh_channel(NMWifiUtils *data, guint32 channel) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - if (channel > self->num_freqs) - return FALSE; - - msg = nl80211_alloc_msg(self, NL80211_CMD_SET_WIPHY, 0); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, self->freqs[channel - 1]); - err = nl80211_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -wifi_nl80211_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg(self, NL80211_CMD_SET_INTERFACE, 0); - NLA_PUT(msg, NL80211_ATTR_MESH_ID, len, ssid); - err = nl80211_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static void -nm_wifi_utils_nl80211_init(NMWifiUtilsNl80211 *self) -{} - -static void -nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMWifiUtilsClass *wifi_utils_class = NM_WIFI_UTILS_CLASS(klass); - - object_class->dispose = dispose; - - wifi_utils_class->get_mode = wifi_nl80211_get_mode; - wifi_utils_class->set_mode = wifi_nl80211_set_mode; - wifi_utils_class->set_powersave = wifi_nl80211_set_powersave; - wifi_utils_class->get_wake_on_wlan = wifi_nl80211_get_wake_on_wlan, - wifi_utils_class->set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan, - wifi_utils_class->get_freq = wifi_nl80211_get_freq; - wifi_utils_class->find_freq = wifi_nl80211_find_freq; - wifi_utils_class->get_station = wifi_nl80211_get_station; - wifi_utils_class->indicate_addressing_running = wifi_nl80211_indicate_addressing_running; - wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; - wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; - wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid; -} - -NMWifiUtils * -nm_wifi_utils_nl80211_new(int ifindex, struct nl_sock *genl) -{ - gs_unref_object NMWifiUtilsNl80211 *self = NULL; - nm_auto_nlmsg struct nl_msg * msg = NULL; - struct nl80211_device_info device_info = {}; - - if (!genl) - return NULL; - - self = g_object_new(NM_TYPE_WIFI_UTILS_NL80211, NULL); - - self->parent.ifindex = ifindex; - self->nl_sock = genl; - - self->id = genl_ctrl_resolve(self->nl_sock, "nl80211"); - if (self->id < 0) { - _LOGD("genl_ctrl_resolve: failed to resolve \"nl80211\""); - return NULL; - } - - self->phy = -1; - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WIPHY, 0); - - device_info.self = self; - if (nl80211_send_and_recv(self, msg, nl80211_wiphy_info_handler, &device_info) < 0) { - _LOGD("NL80211_CMD_GET_WIPHY request failed"); - return NULL; - } - - if (!device_info.success) { - _LOGD("NL80211_CMD_GET_WIPHY request indicated failure"); - return NULL; - } - - if (!device_info.supported) { - _LOGD("driver does not fully support nl80211, falling back to WEXT"); - return NULL; - } - - if (!device_info.can_scan_ssid) { - _LOGE("driver does not support SSID scans"); - return NULL; - } - - if (device_info.num_freqs == 0 || device_info.freqs == NULL) { - _LOGE("driver reports no supported frequencies"); - return NULL; - } - - if (device_info.caps == 0) { - _LOGE("driver doesn't report support of any encryption"); - return NULL; - } - - self->phy = device_info.phy; - self->freqs = device_info.freqs; - self->num_freqs = device_info.num_freqs; - self->parent.caps = device_info.caps; - self->can_wowlan = device_info.can_wowlan; - - _LOGD("using nl80211 for Wi-Fi device control"); - return (NMWifiUtils *) g_steal_pointer(&self); -} diff --git a/src/core/platform/wifi/nm-wifi-utils-nl80211.h b/src/core/platform/wifi/nm-wifi-utils-nl80211.h deleted file mode 100644 index 37c32ed7..00000000 --- a/src/core/platform/wifi/nm-wifi-utils-nl80211.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2011 Intel Corporation. All rights reserved. - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef __WIFI_UTILS_NL80211_H__ -#define __WIFI_UTILS_NL80211_H__ - -#include "nm-wifi-utils.h" -#include "nm-platform/nm-netlink.h" - -#define NM_TYPE_WIFI_UTILS_NL80211 (nm_wifi_utils_nl80211_get_type()) -#define NM_WIFI_UTILS_NL80211(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211)) -#define NM_WIFI_UTILS_NL80211_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211Class)) -#define NM_IS_WIFI_UTILS_NL80211(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WIFI_UTILS_NL80211)) -#define NM_IS_WIFI_UTILS_NL80211_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_UTILS_NL80211)) -#define NM_WIFI_UTILS_NL80211_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211Class)) - -GType nm_wifi_utils_nl80211_get_type(void); - -NMWifiUtils *nm_wifi_utils_nl80211_new(int ifindex, struct nl_sock *genl); - -#endif /* __WIFI_UTILS_NL80211_H__ */ diff --git a/src/core/platform/wifi/nm-wifi-utils-private.h b/src/core/platform/wifi/nm-wifi-utils-private.h deleted file mode 100644 index 9ed57453..00000000 --- a/src/core/platform/wifi/nm-wifi-utils-private.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2011 - 2018 Red Hat, Inc. - */ - -#ifndef __WIFI_UTILS_PRIVATE_H__ -#define __WIFI_UTILS_PRIVATE_H__ - -#include "nm-dbus-interface.h" -#include "nm-wifi-utils.h" - -typedef struct { - GObjectClass parent; - - NM80211Mode (*get_mode)(NMWifiUtils *data); - - gboolean (*set_mode)(NMWifiUtils *data, const NM80211Mode mode); - - /* Set power saving mode on an interface */ - gboolean (*set_powersave)(NMWifiUtils *data, guint32 powersave); - - /* Get WakeOnWLAN configuration on an interface */ - NMSettingWirelessWakeOnWLan (*get_wake_on_wlan)(NMWifiUtils *data); - - /* Set WakeOnWLAN mode on an interface */ - gboolean (*set_wake_on_wlan)(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl); - - /* Return current frequency in MHz (really associated BSS frequency) */ - guint32 (*get_freq)(NMWifiUtils *data); - - /* Return first supported frequency in the zero-terminated list */ - guint32 (*find_freq)(NMWifiUtils *data, const guint32 *freqs); - - /* - * @out_bssid: must be NULL or an ETH_ALEN-byte buffer - * @out_quality: receives signal strength percentage 0 - 100% for the current BSSID, if not NULL - * @out_rate: receives current bitrate in Kbps if not NULL - * - * Returns %TRUE on succcess, %FALSE on errors or if not associated. - */ - gboolean (*get_station)(NMWifiUtils *data, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate); - - /* OLPC Mesh-only functions */ - - guint32 (*get_mesh_channel)(NMWifiUtils *data); - - /* channel == 0 means "auto channel" */ - gboolean (*set_mesh_channel)(NMWifiUtils *data, guint32 channel); - - /* ssid == NULL means "auto SSID" */ - gboolean (*set_mesh_ssid)(NMWifiUtils *data, const guint8 *ssid, gsize len); - - gboolean (*indicate_addressing_running)(NMWifiUtils *data, gboolean running); -} NMWifiUtilsClass; - -struct NMWifiUtils { - GObject parent; - - int ifindex; - NMDeviceWifiCapabilities caps; -}; - -#endif /* __WIFI_UTILS_PRIVATE_H__ */ diff --git a/src/core/platform/wifi/nm-wifi-utils-wext.c b/src/core/platform/wifi/nm-wifi-utils-wext.c deleted file mode 100644 index a44fcf62..00000000 --- a/src/core/platform/wifi/nm-wifi-utils-wext.c +++ /dev/null @@ -1,836 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2005 - 2018 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-wifi-utils-wext.h" - -#include -#include -#include - -/* Hacks necessary to #include wireless.h; yay for WEXT */ -#ifndef __user - #define __user -#endif -#include -#include -#include -#include - -#include "nm-wifi-utils-private.h" -#include "nm-utils.h" -#include "nm-platform/nm-platform-utils.h" -#include "nm-core-internal.h" -#include "nm-core-utils.h" - -typedef struct { - NMWifiUtils parent; - int fd; - struct iw_quality max_qual; - gint8 num_freqs; - guint32 freqs[IW_MAX_FREQUENCIES]; -} NMWifiUtilsWext; - -typedef struct { - NMWifiUtilsClass parent; -} NMWifiUtilsWextClass; - -G_DEFINE_TYPE(NMWifiUtilsWext, nm_wifi_utils_wext, NM_TYPE_WIFI_UTILS) - -/* Until a new wireless-tools comes out that has the defs and the structure, - * need to copy them here. - */ -/* Scan capability flags - in (struct iw_range *)->scan_capa */ -#define NM_IW_SCAN_CAPA_NONE 0x00 -#define NM_IW_SCAN_CAPA_ESSID 0x01 - -struct iw_range_with_scan_capa { - guint32 throughput; - guint32 min_nwid; - guint32 max_nwid; - guint16 old_num_channels; - guint8 old_num_frequency; - - guint8 scan_capa; - /* don't need the rest... */ -}; - -#define _NMLOG_PREFIX_NAME "wifi-wext" -#define _NMLOG(level, domain, ...) \ - G_STMT_START \ - { \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -static guint32 -iw_freq_to_uint32(const struct iw_freq *freq) -{ - if (freq->e == 0) { - /* Some drivers report channel not frequency. Convert to a - * frequency; but this assumes that the device is in b/g mode. - */ - if ((freq->m >= 1) && (freq->m <= 13)) - return 2407 + (5 * freq->m); - else if (freq->m == 14) - return 2484; - } - return (guint32)((((double) freq->m) * nm_utils_exp10(freq->e)) / 1000000.0); -} - -static void -dispose(GObject *object) -{ - NMWifiUtilsWext *wext = NM_WIFI_UTILS_WEXT(object); - - wext->fd = nm_close(wext->fd); -} - -static gboolean -get_ifname(int ifindex, char *buffer, const char *op) -{ - int errsv; - - if (!nmp_utils_if_indextoname(ifindex, buffer)) { - errsv = errno; - _LOGW(LOGD_PLATFORM | LOGD_WIFI, - "error getting interface name for ifindex %d, operation '%s': %s (%d)", - ifindex, - op, - nm_strerror_native(errsv), - errsv); - return FALSE; - } - - return TRUE; -} - -static NM80211Mode -wifi_wext_get_mode_ifname(NMWifiUtils *data, const char *ifname) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - int errsv; - - memset(&wrq, 0, sizeof(struct iwreq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - - if (ioctl(wext->fd, SIOCGIWMODE, &wrq) < 0) { - errsv = errno; - if (errsv != ENODEV) { - _LOGW(LOGD_PLATFORM | LOGD_WIFI, "(%s): error %d getting card mode", ifname, errsv); - } - return NM_802_11_MODE_UNKNOWN; - } - - switch (wrq.u.mode) { - case IW_MODE_ADHOC: - return NM_802_11_MODE_ADHOC; - case IW_MODE_MASTER: - return NM_802_11_MODE_AP; - case IW_MODE_INFRA: - case IW_MODE_AUTO: /* hack for WEXT devices reporting IW_MODE_AUTO */ - return NM_802_11_MODE_INFRA; - default: - break; - } - return NM_802_11_MODE_UNKNOWN; -} - -static NM80211Mode -wifi_wext_get_mode(NMWifiUtils *data) -{ - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "get-mode")) - return FALSE; - - return wifi_wext_get_mode_ifname(data, ifname); -} - -static gboolean -wifi_wext_set_mode(NMWifiUtils *data, const NM80211Mode mode) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "set-mode")) - return FALSE; - - if (wifi_wext_get_mode_ifname(data, ifname) == mode) - return TRUE; - - memset(&wrq, 0, sizeof(struct iwreq)); - switch (mode) { - case NM_802_11_MODE_ADHOC: - wrq.u.mode = IW_MODE_ADHOC; - break; - case NM_802_11_MODE_AP: - wrq.u.mode = IW_MODE_MASTER; - break; - case NM_802_11_MODE_INFRA: - wrq.u.mode = IW_MODE_INFRA; - break; - default: - g_warn_if_reached(); - return FALSE; - } - - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - if (ioctl(wext->fd, SIOCSIWMODE, &wrq) < 0) { - if (errno != ENODEV) { - _LOGE(LOGD_PLATFORM | LOGD_WIFI, "(%s): error setting mode %d", ifname, mode); - } - return FALSE; - } - - return TRUE; -} - -static gboolean -wifi_wext_set_powersave(NMWifiUtils *data, guint32 powersave) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "set-powersave")) - return FALSE; - - memset(&wrq, 0, sizeof(struct iwreq)); - if (powersave == 1) { - wrq.u.power.flags = IW_POWER_ALL_R; - } else - wrq.u.power.disabled = 1; - - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - if (ioctl(wext->fd, SIOCSIWPOWER, &wrq) < 0) { - if (errno != ENODEV) { - _LOGE(LOGD_PLATFORM | LOGD_WIFI, - "(%s): error setting powersave %" G_GUINT32_FORMAT, - ifname, - powersave); - } - return FALSE; - } - - return TRUE; -} - -static guint32 -wifi_wext_get_freq(NMWifiUtils *data) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "get-freq")) - return FALSE; - - memset(&wrq, 0, sizeof(struct iwreq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - if (ioctl(wext->fd, SIOCGIWFREQ, &wrq) < 0) { - _LOGW(LOGD_PLATFORM | LOGD_WIFI, - "(%s): error getting frequency: %s", - ifname, - nm_strerror_native(errno)); - return 0; - } - - return iw_freq_to_uint32(&wrq.u.freq); -} - -static guint32 -wifi_wext_find_freq(NMWifiUtils *data, const guint32 *freqs) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - int i; - - for (i = 0; i < wext->num_freqs; i++) { - while (*freqs) { - if (wext->freqs[i] == *freqs) - return *freqs; - freqs++; - } - } - return 0; -} - -static gboolean -wifi_wext_get_bssid(NMWifiUtils *data, NMEtherAddr *out_bssid) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "get-bssid")) - return FALSE; - - memset(&wrq, 0, sizeof(wrq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - if (ioctl(wext->fd, SIOCGIWAP, &wrq) < 0) { - _LOGW(LOGD_PLATFORM | LOGD_WIFI, - "(%s): error getting associated BSSID: %s", - ifname, - nm_strerror_native(errno)); - return FALSE; - } - memcpy(out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN); - return TRUE; -} - -static guint32 -wifi_wext_get_rate(NMWifiUtils *data) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - int err; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "get-rate")) - return FALSE; - - memset(&wrq, 0, sizeof(wrq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - err = ioctl(wext->fd, SIOCGIWRATE, &wrq); - return ((err == 0) ? wrq.u.bitrate.value / 1000 : 0); -} - -static int -wext_qual_to_percent(const struct iw_quality *qual, const struct iw_quality *max_qual) -{ - int percent = -1; - int level_percent = -1; - - g_return_val_if_fail(qual != NULL, -1); - g_return_val_if_fail(max_qual != NULL, -1); - - /* Magically convert the many different WEXT quality representations to a percentage */ - - _LOGD(LOGD_WIFI, - "QL: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X ** MAX: qual " - "%d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X", - (__s8) qual->qual, - qual->qual, - qual->qual, - (__s8) qual->level, - qual->level, - qual->level, - (__s8) qual->noise, - qual->noise, - qual->noise, - qual->updated, - (__s8) max_qual->qual, - max_qual->qual, - max_qual->qual, - (__s8) max_qual->level, - max_qual->level, - max_qual->level, - (__s8) max_qual->noise, - max_qual->noise, - max_qual->noise, - max_qual->updated); - - /* Try using the card's idea of the signal quality first as long as it tells us what the max quality is. - * Drivers that fill in quality values MUST treat them as percentages, ie the "Link Quality" MUST be - * bounded by 0 and max_qual->qual, and MUST change in a linear fashion. Within those bounds, drivers - * are free to use whatever they want to calculate "Link Quality". - */ - if ((max_qual->qual != 0) && !(max_qual->updated & IW_QUAL_QUAL_INVALID) - && !(qual->updated & IW_QUAL_QUAL_INVALID)) - percent = (int) (100 * ((double) qual->qual / (double) max_qual->qual)); - - /* If the driver doesn't specify a complete and valid quality, we have two options: - * - * 1) dBm: driver must specify max_qual->level = 0, and have valid values for - * qual->level and (qual->noise OR max_qual->noise) - * 2) raw RSSI: driver must specify max_qual->level > 0, and have valid values for - * qual->level and max_qual->level - * - * This is the WEXT spec. If this interpretation is wrong, I'll fix it. Otherwise, - * If drivers don't conform to it, they are wrong and need to be fixed. - */ - - if ((max_qual->level == 0) - && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ - && (((max_qual->noise > 0) - && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ - || ((qual->noise > 0) - && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ - ) { -/* Absolute power values (dBm) */ - -/* Reasonable fallbacks for dumb drivers that don't specify either level. */ -#define FALLBACK_NOISE_FLOOR_DBM -90 -#define FALLBACK_SIGNAL_MAX_DBM -20 - int max_level = FALLBACK_SIGNAL_MAX_DBM; - int noise = FALLBACK_NOISE_FLOOR_DBM; - int level = qual->level - 0x100; - - level = CLAMP(level, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); - - if ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID)) - noise = qual->noise - 0x100; - else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) - noise = max_qual->noise - 0x100; - noise = CLAMP(noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM - 1); - - /* A sort of signal-to-noise ratio calculation */ - level_percent = (int) (100 - - 70 - * (((double) max_level - (double) level) - / ((double) max_level - (double) noise))); - _LOGD(LOGD_WIFI, - "QL1: level_percent is %d. max_level %d, level %d, noise_floor %d.", - level_percent, - max_level, - level, - noise); - } else if ((max_qual->level != 0) - && !(max_qual->updated - & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID)) { - /* Relative power values (RSSI) */ - - int level = qual->level; - - /* Signal level is relavtive (0 -> max_qual->level) */ - level = CLAMP(level, 0, max_qual->level); - level_percent = (int) (100 * ((double) level / (double) max_qual->level)); - _LOGD(LOGD_WIFI, - "QL2: level_percent is %d. max_level %d, level %d.", - level_percent, - max_qual->level, - level); - } else if (percent == -1) { - _LOGD(LOGD_WIFI, - "QL: Could not get quality %% value from driver. Driver is probably buggy."); - } - - /* If the quality percent was 0 or doesn't exist, then try to use signal levels instead */ - if ((percent < 1) && (level_percent >= 0)) - percent = level_percent; - - _LOGD(LOGD_WIFI, "QL: Final quality percent is %d (%d).", percent, CLAMP(percent, 0, 100)); - return (CLAMP(percent, 0, 100)); -} - -static int -wifi_wext_get_qual(NMWifiUtils *data) -{ - NMWifiUtilsWext * wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - struct iw_statistics stats; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "get-qual")) - return FALSE; - - memset(&stats, 0, sizeof(stats)); - wrq.u.data.pointer = &stats; - wrq.u.data.length = sizeof(stats); - wrq.u.data.flags = 1; /* Clear updated flag */ - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - - if (ioctl(wext->fd, SIOCGIWSTATS, &wrq) < 0) { - _LOGW(LOGD_PLATFORM | LOGD_WIFI, - "(%s): error getting signal strength: %s", - ifname, - nm_strerror_native(errno)); - return -1; - } - - return wext_qual_to_percent(&stats.qual, &wext->max_qual); -} - -static gboolean -wifi_wext_get_station(NMWifiUtils *data, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate) -{ - NMEtherAddr local_addr; - - if (!out_bssid && !out_quality && !out_rate) { - /* hm, the caller requested no parameter at all? - * Don't simply return TRUE, but at least check that - * we can successfully fetch the bssid. */ - out_bssid = &local_addr; - } - - if (out_bssid) { - if (!wifi_wext_get_bssid(data, out_bssid)) - return FALSE; - } - if (out_quality) { - *out_quality = wifi_wext_get_qual(data); - if (*out_quality < 0) - return FALSE; - } - if (out_rate) { - *out_rate = wifi_wext_get_rate(data); - if (*out_rate == 0) - return FALSE; - } - return TRUE; -} - -/*****************************************************************************/ -/* OLPC Mesh-only functions */ - -static guint32 -wifi_wext_get_mesh_channel(NMWifiUtils *data) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - guint32 freq; - int i; - - freq = nm_wifi_utils_get_freq(data); - for (i = 0; i < wext->num_freqs; i++) { - if (freq == wext->freqs[i]) - return i + 1; - } - return 0; -} - -static gboolean -wifi_wext_set_mesh_channel(NMWifiUtils *data, guint32 channel) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname(data->ifindex, ifname, "set-mesh-channel")) - return FALSE; - - memset(&wrq, 0, sizeof(struct iwreq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - - if (channel > 0) { - wrq.u.freq.flags = IW_FREQ_FIXED; - wrq.u.freq.e = 0; - wrq.u.freq.m = channel; - } - - if (ioctl(wext->fd, SIOCSIWFREQ, &wrq) < 0) { - _LOGE(LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, - "(%s): error setting channel to %d: %s", - ifname, - channel, - nm_strerror_native(errno)); - return FALSE; - } - - return TRUE; -} - -static gboolean -wifi_wext_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) -{ - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char buf[IW_ESSID_MAX_SIZE + 1]; - char ifname[IFNAMSIZ]; - int errsv; - - if (!get_ifname(data->ifindex, ifname, "set-mesh-ssid")) - return FALSE; - - memset(buf, 0, sizeof(buf)); - memcpy(buf, ssid, MIN(sizeof(buf) - 1, len)); - - wrq.u.essid.pointer = (caddr_t) buf; - wrq.u.essid.length = len; - wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ - - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - if (ioctl(wext->fd, SIOCSIWESSID, &wrq) == 0) - return TRUE; - - errsv = errno; - if (errsv != ENODEV) { - gs_free char *ssid_str = NULL; - - _LOGE(LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, - "(%s): error setting SSID to %s: %s", - ifname, - (ssid_str = _nm_utils_ssid_to_string_arr(ssid, len)), - nm_strerror_native(errsv)); - } - - return FALSE; -} - -/*****************************************************************************/ - -static gboolean -wext_can_scan_ifname(NMWifiUtilsWext *wext, const char *ifname) -{ - struct iwreq wrq; - - memset(&wrq, 0, sizeof(struct iwreq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - if (ioctl(wext->fd, SIOCSIWSCAN, &wrq) < 0) { - if (errno == EOPNOTSUPP) - return FALSE; - } - return TRUE; -} - -static gboolean -wext_get_range_ifname(NMWifiUtilsWext *wext, - const char * ifname, - struct iw_range *range, - guint32 * response_len) -{ - int i = 26; - gboolean success = FALSE; - struct iwreq wrq; - int errsv; - - memset(&wrq, 0, sizeof(struct iwreq)); - nm_utils_ifname_cpy(wrq.ifr_name, ifname); - wrq.u.data.pointer = (caddr_t) range; - wrq.u.data.length = sizeof(struct iw_range); - - /* Need to give some drivers time to recover after suspend/resume - * (ex ipw3945 takes a few seconds to talk to its regulatory daemon; - * see rh bz#362421) - */ - while (i-- > 0) { - if (ioctl(wext->fd, SIOCGIWRANGE, &wrq) == 0) { - if (response_len) - *response_len = wrq.u.data.length; - success = TRUE; - break; - } else { - errsv = errno; - if (errsv != EAGAIN) { - _LOGE(LOGD_PLATFORM | LOGD_WIFI, - "(%s): couldn't get driver range information (%d).", - ifname, - errsv); - break; - } - } - - g_usleep(G_USEC_PER_SEC / 4); - } - - if (i <= 0) { - _LOGW(LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver took too long to respond to IWRANGE query.", - ifname); - } - - return success; -} - -#define WPA_CAPS \ - (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_WPA \ - | NM_WIFI_DEVICE_CAP_RSN) - -static guint32 -wext_get_caps(NMWifiUtilsWext *wext, const char *ifname, struct iw_range *range) -{ - guint32 caps = NM_WIFI_DEVICE_CAP_NONE; - - g_return_val_if_fail(wext != NULL, NM_WIFI_DEVICE_CAP_NONE); - g_return_val_if_fail(range != NULL, NM_WIFI_DEVICE_CAP_NONE); - - /* All drivers should support WEP by default */ - caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104; - - if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) - caps |= NM_WIFI_DEVICE_CAP_CIPHER_TKIP; - - if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) - caps |= NM_WIFI_DEVICE_CAP_CIPHER_CCMP; - - if (range->enc_capa & IW_ENC_CAPA_WPA) - caps |= NM_WIFI_DEVICE_CAP_WPA; - - if (range->enc_capa & IW_ENC_CAPA_WPA2) - caps |= NM_WIFI_DEVICE_CAP_RSN; - - /* Check for cipher support but not WPA support */ - if ((caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - && !(caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))) { - _LOGW(LOGD_WIFI, - "%s: device supports WPA ciphers but not WPA protocol; WPA unavailable.", - ifname); - caps &= ~WPA_CAPS; - } - - /* Check for WPA support but not cipher support */ - if ((caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN)) - && !(caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))) { - _LOGW(LOGD_WIFI, - "%s: device supports WPA protocol but not WPA ciphers; WPA unavailable.", - ifname); - caps &= ~WPA_CAPS; - } - - /* There's no way to detect Ad-Hoc/AP mode support with WEXT - * (other than actually trying to do it), so just assume that - * Ad-Hoc is supported and AP isn't. - */ - caps |= NM_WIFI_DEVICE_CAP_ADHOC; - - return caps; -} - -/*****************************************************************************/ - -static void -nm_wifi_utils_wext_init(NMWifiUtilsWext *self) -{} - -static void -nm_wifi_utils_wext_class_init(NMWifiUtilsWextClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMWifiUtilsClass *wifi_utils_class = NM_WIFI_UTILS_CLASS(klass); - - object_class->dispose = dispose; - - wifi_utils_class->get_mode = wifi_wext_get_mode; - wifi_utils_class->set_mode = wifi_wext_set_mode; - wifi_utils_class->set_powersave = wifi_wext_set_powersave; - wifi_utils_class->get_freq = wifi_wext_get_freq; - wifi_utils_class->find_freq = wifi_wext_find_freq; - wifi_utils_class->get_station = wifi_wext_get_station; - wifi_utils_class->get_mesh_channel = wifi_wext_get_mesh_channel; - wifi_utils_class->set_mesh_channel = wifi_wext_set_mesh_channel; - wifi_utils_class->set_mesh_ssid = wifi_wext_set_mesh_ssid; -} - -NMWifiUtils * -nm_wifi_utils_wext_new(int ifindex, gboolean check_scan) -{ - NMWifiUtilsWext * wext; - struct iw_range range; - guint32 response_len = 0; - struct iw_range_with_scan_capa *scan_capa_range; - int i; - gboolean freq_valid = FALSE, has_5ghz = FALSE, has_2ghz = FALSE; - char ifname[IFNAMSIZ]; - - if (!nmp_utils_if_indextoname(ifindex, ifname)) { - _LOGW(LOGD_PLATFORM | LOGD_WIFI, "can't determine interface name for ifindex %d", ifindex); - return NULL; - } - - wext = g_object_new(NM_TYPE_WIFI_UTILS_WEXT, NULL); - - wext->parent.ifindex = ifindex; - wext->fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (wext->fd < 0) - goto error; - - memset(&range, 0, sizeof(struct iw_range)); - if (wext_get_range_ifname(wext, ifname, &range, &response_len) == FALSE) { - _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): driver WEXT range request failed", ifname); - goto error; - } - - if ((response_len < 300) || (range.we_version_compiled < 21)) { - _LOGI(LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver WEXT version too old (got %d, expected >= 21)", - ifname, - range.we_version_compiled); - goto error; - } - - wext->max_qual.qual = range.max_qual.qual; - wext->max_qual.level = range.max_qual.level; - wext->max_qual.noise = range.max_qual.noise; - wext->max_qual.updated = range.max_qual.updated; - - wext->num_freqs = MIN(range.num_frequency, IW_MAX_FREQUENCIES); - for (i = 0; i < wext->num_freqs; i++) { - wext->freqs[i] = iw_freq_to_uint32(&range.freq[i]); - freq_valid = TRUE; - if (wext->freqs[i] > 2400 && wext->freqs[i] < 2500) - has_2ghz = TRUE; - else if (wext->freqs[i] > 4900 && wext->freqs[i] < 6000) - has_5ghz = TRUE; - } - - /* Check for scanning capability; cards that can't scan are not supported */ - if (check_scan && (wext_can_scan_ifname(wext, ifname) == FALSE)) { - _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): drivers that cannot scan are unsupported", ifname); - goto error; - } - - /* Check for the ability to scan specific SSIDs. Until the scan_capa - * field gets added to wireless-tools, need to work around that by casting - * to the custom structure. - */ - scan_capa_range = (struct iw_range_with_scan_capa *) ⦥ - if (scan_capa_range->scan_capa & NM_IW_SCAN_CAPA_ESSID) { - _LOGI(LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver supports SSID scans (scan_capa 0x%02X).", - ifname, - scan_capa_range->scan_capa); - } else { - _LOGI(LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver does not support SSID scans (scan_capa 0x%02X).", - ifname, - scan_capa_range->scan_capa); - } - - wext->parent.caps = wext_get_caps(wext, ifname, &range); - if (freq_valid) - wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID; - if (has_2ghz) - wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_2GHZ; - if (has_5ghz) - wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; - - _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): using WEXT for Wi-Fi device control", ifname); - - return (NMWifiUtils *) wext; - -error: - g_object_unref(wext); - return NULL; -} - -gboolean -nm_wifi_utils_wext_is_wifi(const char *iface) -{ - int fd; - struct iwreq iwr; - gboolean is_wifi = FALSE; - - /* performing an ioctl on a non-existing name may cause the automatic - * loading of kernel modules, which should be avoided. - * - * Usually, we should thus make sure that an interface with this name - * exists. - * - * Note that wifi_wext_is_wifi() has only one caller which just verified - * that an interface with this name exists. - */ - - fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (fd >= 0) { - nm_utils_ifname_cpy(iwr.ifr_ifrn.ifrn_name, iface); - if (ioctl(fd, SIOCGIWNAME, &iwr) == 0) - is_wifi = TRUE; - nm_close(fd); - } - return is_wifi; -} diff --git a/src/core/platform/wifi/nm-wifi-utils-wext.h b/src/core/platform/wifi/nm-wifi-utils-wext.h deleted file mode 100644 index d6f3453c..00000000 --- a/src/core/platform/wifi/nm-wifi-utils-wext.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2011 - 2018 Red Hat, Inc. - */ - -#ifndef __WIFI_UTILS_WEXT_H__ -#define __WIFI_UTILS_WEXT_H__ - -#include "nm-wifi-utils.h" - -#define NM_TYPE_WIFI_UTILS_WEXT (nm_wifi_utils_wext_get_type()) -#define NM_WIFI_UTILS_WEXT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWext)) -#define NM_WIFI_UTILS_WEXT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWextClass)) -#define NM_IS_WIFI_UTILS_WEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WIFI_UTILS_WEXT)) -#define NM_IS_WIFI_UTILS_WEXT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_UTILS_WEXT)) -#define NM_WIFI_UTILS_WEXT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWextClass)) - -GType nm_wifi_utils_wext_get_type(void); - -NMWifiUtils *nm_wifi_utils_wext_new(int ifindex, gboolean check_scan); - -gboolean nm_wifi_utils_wext_is_wifi(const char *iface); - -#endif /* __WIFI_UTILS_WEXT_H__ */ diff --git a/src/core/platform/wifi/nm-wifi-utils.c b/src/core/platform/wifi/nm-wifi-utils.c deleted file mode 100644 index 49ae1811..00000000 --- a/src/core/platform/wifi/nm-wifi-utils.c +++ /dev/null @@ -1,211 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2005 - 2018 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-wifi-utils.h" - -#include -#include -#include - -#include "nm-wifi-utils-private.h" -#include "nm-wifi-utils-nl80211.h" -#if HAVE_WEXT - #include "nm-wifi-utils-wext.h" -#endif -#include "nm-core-utils.h" - -#include "nm-platform/nm-platform-utils.h" - -G_DEFINE_ABSTRACT_TYPE(NMWifiUtils, nm_wifi_utils, G_TYPE_OBJECT) - -/*****************************************************************************/ - -static void -nm_wifi_utils_init(NMWifiUtils *self) -{} - -static void -nm_wifi_utils_class_init(NMWifiUtilsClass *klass) -{} - -NMWifiUtils * -nm_wifi_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan) -{ - NMWifiUtils *ret; - - g_return_val_if_fail(ifindex > 0, NULL); - - ret = nm_wifi_utils_nl80211_new(ifindex, genl); - -#if HAVE_WEXT - if (ret == NULL) - ret = nm_wifi_utils_wext_new(ifindex, check_scan); -#endif - - return ret; -} - -NMDeviceWifiCapabilities -nm_wifi_utils_get_caps(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, NM_WIFI_DEVICE_CAP_NONE); - - return data->caps; -} - -NM80211Mode -nm_wifi_utils_get_mode(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, NM_802_11_MODE_UNKNOWN); - return NM_WIFI_UTILS_GET_CLASS(data)->get_mode(data); -} - -gboolean -nm_wifi_utils_set_mode(NMWifiUtils *data, const NM80211Mode mode) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - g_return_val_if_fail((mode == NM_802_11_MODE_INFRA) || (mode == NM_802_11_MODE_AP) - || (mode == NM_802_11_MODE_ADHOC) || (mode == NM_802_11_MODE_MESH), - FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - - /* nl80211 probably doesn't need this */ - return klass->set_mode ? klass->set_mode(data, mode) : TRUE; -} - -gboolean -nm_wifi_utils_set_powersave(NMWifiUtils *data, guint32 powersave) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - return klass->set_powersave ? klass->set_powersave(data, powersave) : TRUE; -} - -NMSettingWirelessWakeOnWLan -nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - - return klass->get_wake_on_wlan ? klass->get_wake_on_wlan(data) - : NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; -} - -gboolean -nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - return klass->set_wake_on_wlan ? klass->set_wake_on_wlan(data, wowl) : FALSE; -} - -guint32 -nm_wifi_utils_get_freq(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS(data)->get_freq(data); -} - -guint32 -nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs) -{ - g_return_val_if_fail(data != NULL, 0); - g_return_val_if_fail(freqs != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS(data)->find_freq(data, freqs); -} - -gboolean -nm_wifi_utils_get_station(NMWifiUtils *data, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate) -{ - g_return_val_if_fail(data != NULL, FALSE); - - return NM_WIFI_UTILS_GET_CLASS(data)->get_station(data, out_bssid, out_quality, out_rate); -} - -gboolean -nm_wifi_utils_is_wifi(int dirfd, const char *ifname) -{ - g_return_val_if_fail(dirfd >= 0, FALSE); - - if (faccessat(dirfd, "phy80211", F_OK, 0) == 0) - return TRUE; -#if HAVE_WEXT - if (nm_wifi_utils_wext_is_wifi(ifname)) - return TRUE; -#endif - return FALSE; -} - -/* OLPC Mesh-only functions */ - -guint32 -nm_wifi_utils_get_mesh_channel(NMWifiUtils *data) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - g_return_val_if_fail(klass->get_mesh_channel != NULL, FALSE); - - return klass->get_mesh_channel(data); -} - -gboolean -nm_wifi_utils_set_mesh_channel(NMWifiUtils *data, guint32 channel) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - g_return_val_if_fail(channel <= 13, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - g_return_val_if_fail(klass->set_mesh_channel != NULL, FALSE); - - return klass->set_mesh_channel(data, channel); -} - -gboolean -nm_wifi_utils_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - g_return_val_if_fail(klass->set_mesh_ssid != NULL, FALSE); - - return klass->set_mesh_ssid(data, ssid, len); -} - -gboolean -nm_wifi_utils_indicate_addressing_running(NMWifiUtils *data, gboolean running) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - return klass->indicate_addressing_running ? klass->indicate_addressing_running(data, running) - : FALSE; -} diff --git a/src/core/platform/wifi/nm-wifi-utils.h b/src/core/platform/wifi/nm-wifi-utils.h deleted file mode 100644 index a252e43e..00000000 --- a/src/core/platform/wifi/nm-wifi-utils.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2005 - 2018 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef __WIFI_UTILS_H__ -#define __WIFI_UTILS_H__ - -#include - -#include "nm-dbus-interface.h" -#include "nm-setting-wireless.h" -#include "nm-platform/nm-netlink.h" - -typedef struct NMWifiUtils NMWifiUtils; - -#define NM_TYPE_WIFI_UTILS (nm_wifi_utils_get_type()) -#define NM_WIFI_UTILS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_UTILS, NMWifiUtils)) -#define NM_WIFI_UTILS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WIFI_UTILS, NMWifiUtilsClass)) -#define NM_IS_WIFI_UTILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WIFI_UTILS)) -#define NM_IS_WIFI_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_UTILS)) -#define NM_WIFI_UTILS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_UTILS, NMWifiUtilsClass)) - -GType nm_wifi_utils_get_type(void); - -gboolean nm_wifi_utils_is_wifi(int dirfd, const char *ifname); - -NMWifiUtils *nm_wifi_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan); - -NMDeviceWifiCapabilities nm_wifi_utils_get_caps(NMWifiUtils *data); - -NM80211Mode nm_wifi_utils_get_mode(NMWifiUtils *data); - -gboolean nm_wifi_utils_set_mode(NMWifiUtils *data, const NM80211Mode mode); - -/* Returns frequency in MHz */ -guint32 nm_wifi_utils_get_freq(NMWifiUtils *data); - -/* Return the first supported frequency in the zero-terminated list. - * Frequencies are specified in MHz. */ -guint32 nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs); - -/* - * @out_bssid: must be NULL or an ETH_ALEN-byte buffer - * @out_quality: receives signal quality in 0 - 100% range if not NULL - * @out_rate: receives current bitrate in Kbps if not NULL - * - * Returns %TRUE on succcess. - */ -gboolean nm_wifi_utils_get_station(NMWifiUtils *data, - NMEtherAddr *out_bssid, - int * out_quality, - guint32 * out_rate); - -/* Tells the driver DHCP or SLAAC is running */ -gboolean nm_wifi_utils_indicate_addressing_running(NMWifiUtils *data, gboolean running); - -gboolean nm_wifi_utils_set_powersave(NMWifiUtils *data, guint32 powersave); - -NMSettingWirelessWakeOnWLan nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data); - -gboolean nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl); - -/* OLPC Mesh-only functions */ -guint32 nm_wifi_utils_get_mesh_channel(NMWifiUtils *data); - -gboolean nm_wifi_utils_set_mesh_channel(NMWifiUtils *data, guint32 channel); - -gboolean nm_wifi_utils_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len); - -#endif /* __WIFI_UTILS_H__ */ diff --git a/src/core/platform/wpan/nm-wpan-utils.c b/src/core/platform/wpan/nm-wpan-utils.c deleted file mode 100644 index efb19979..00000000 --- a/src/core/platform/wpan/nm-wpan-utils.c +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-wpan-utils.h" - -#include - -#include "nm-platform/nm-netlink.h" -#include "platform/linux/nl802154.h" -#include "nm-platform/nm-platform-utils.h" - -#define _NMLOG_PREFIX_NAME "wpan-nl802154" -#define _NMLOG(level, domain, ...) \ - G_STMT_START \ - { \ - char _ifname_buf[IFNAMSIZ]; \ - const char *_ifname = self ? nmp_utils_if_indextoname(self->ifindex, _ifname_buf) : NULL; \ - \ - nm_log((level), \ - (domain), \ - _ifname ?: NULL, \ - NULL, \ - "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - NM_PRINT_FMT_QUOTED(_ifname, " (", _ifname, ")", "") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -struct NMWpanUtils { - GObject parent; - int ifindex; - struct nl_sock *nl_sock; - int id; -}; - -typedef struct { - GObjectClass parent; -} NMWpanUtilsClass; - -G_DEFINE_TYPE(NMWpanUtils, nm_wpan_utils, G_TYPE_OBJECT) - -/*****************************************************************************/ - -static int -ack_handler(struct nl_msg *msg, void *arg) -{ - int *done = arg; - *done = 1; - return NL_STOP; -} - -static int -finish_handler(struct nl_msg *msg, void *arg) -{ - int *done = arg; - *done = 1; - return NL_SKIP; -} - -static int -error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) -{ - int *done = arg; - *done = err->error; - return NL_SKIP; -} - -static struct nl_msg * -_nl802154_alloc_msg(int id, int ifindex, guint32 cmd, guint32 flags) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nlmsg_alloc(); - genlmsg_put(msg, 0, 0, id, 0, flags, cmd, 0); - NLA_PUT_U32(msg, NL802154_ATTR_IFINDEX, ifindex); - return g_steal_pointer(&msg); - -nla_put_failure: - g_return_val_if_reached(NULL); -} - -static struct nl_msg * -nl802154_alloc_msg(NMWpanUtils *self, guint32 cmd, guint32 flags) -{ - return _nl802154_alloc_msg(self->id, self->ifindex, cmd, flags); -} - -static int -nl802154_send_and_recv(NMWpanUtils * self, - struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - int err; - int done = 0; - const struct nl_cb cb = { - .err_cb = error_handler, - .err_arg = &done, - .finish_cb = finish_handler, - .finish_arg = &done, - .ack_cb = ack_handler, - .ack_arg = &done, - .valid_cb = valid_handler, - .valid_arg = valid_data, - }; - - g_return_val_if_fail(msg != NULL, -ENOMEM); - - err = nl_send_auto(self->nl_sock, msg); - if (err < 0) - return err; - - /* Loop until one of our NL callbacks says we're done; on success - * done will be 1, on error it will be < 0. - */ - while (!done) { - err = nl_recvmsgs(self->nl_sock, &cb); - if (err < 0 && err != -EAGAIN) { - _LOGW(LOGD_PLATFORM, "nl_recvmsgs() error: (%d) %s", err, nm_strerror(err)); - break; - } - } - - if (err >= 0 && done < 0) - err = done; - return err; -} - -struct nl802154_interface { - guint16 pan_id; - guint16 short_addr; - - gboolean valid; -}; - -static int -nl802154_get_interface_handler(struct nl_msg *msg, void *arg) -{ - static const struct nla_policy nl802154_policy[] = { - [NL802154_ATTR_PAN_ID] = {.type = NLA_U16}, - [NL802154_ATTR_SHORT_ADDR] = {.type = NLA_U16}, - }; - struct nlattr * tb[G_N_ELEMENTS(nl802154_policy)]; - struct nl802154_interface *info = arg; - struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - - if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nl802154_policy) < 0) - return NL_SKIP; - - if (tb[NL802154_ATTR_PAN_ID]) - info->pan_id = le16toh(nla_get_u16(tb[NL802154_ATTR_PAN_ID])); - - if (tb[NL802154_ATTR_SHORT_ADDR]) - info->short_addr = le16toh(nla_get_u16(tb[NL802154_ATTR_SHORT_ADDR])); - - info->valid = TRUE; - - return NL_SKIP; -} - -static void -nl802154_get_interface(NMWpanUtils *self, struct nl802154_interface *interface) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - - memset(interface, 0, sizeof(*interface)); - - msg = nl802154_alloc_msg(self, NL802154_CMD_GET_INTERFACE, 0); - - nl802154_send_and_recv(self, msg, nl802154_get_interface_handler, interface); -} - -/*****************************************************************************/ - -guint16 -nm_wpan_utils_get_pan_id(NMWpanUtils *self) -{ - struct nl802154_interface interface; - - nl802154_get_interface(self, &interface); - - return interface.pan_id; -} - -gboolean -nm_wpan_utils_set_pan_id(NMWpanUtils *self, guint16 pan_id) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - g_return_val_if_fail(self != NULL, FALSE); - - msg = nl802154_alloc_msg(self, NL802154_CMD_SET_PAN_ID, 0); - NLA_PUT_U16(msg, NL802154_ATTR_PAN_ID, htole16(pan_id)); - err = nl802154_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -guint16 -nm_wpan_utils_get_short_addr(NMWpanUtils *self) -{ - struct nl802154_interface interface; - - nl802154_get_interface(self, &interface); - - return interface.short_addr; -} - -gboolean -nm_wpan_utils_set_short_addr(NMWpanUtils *self, guint16 short_addr) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - g_return_val_if_fail(self != NULL, FALSE); - - msg = nl802154_alloc_msg(self, NL802154_CMD_SET_SHORT_ADDR, 0); - NLA_PUT_U16(msg, NL802154_ATTR_SHORT_ADDR, htole16(short_addr)); - err = nl802154_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -gboolean -nm_wpan_utils_set_channel(NMWpanUtils *self, guint8 page, guint8 channel) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - g_return_val_if_fail(self != NULL, FALSE); - - msg = nl802154_alloc_msg(self, NL802154_CMD_SET_CHANNEL, 0); - NLA_PUT_U8(msg, NL802154_ATTR_PAGE, page); - NLA_PUT_U8(msg, NL802154_ATTR_CHANNEL, channel); - err = nl802154_send_and_recv(self, msg, NULL, NULL); - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -/*****************************************************************************/ - -static void -nm_wpan_utils_init(NMWpanUtils *self) -{} - -static void -nm_wpan_utils_class_init(NMWpanUtilsClass *klass) -{} - -NMWpanUtils * -nm_wpan_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan) -{ - NMWpanUtils *self; - - g_return_val_if_fail(ifindex > 0, NULL); - - if (!genl) - return NULL; - - self = g_object_new(NM_TYPE_WPAN_UTILS, NULL); - self->ifindex = ifindex; - self->nl_sock = genl; - self->id = genl_ctrl_resolve(genl, "nl802154"); - - if (self->id < 0) { - _LOGD(LOGD_PLATFORM, "genl_ctrl_resolve: failed to resolve \"nl802154\""); - g_object_unref(self); - return NULL; - } - - return self; -} diff --git a/src/core/platform/wpan/nm-wpan-utils.h b/src/core/platform/wpan/nm-wpan-utils.h deleted file mode 100644 index 940c2c9d..00000000 --- a/src/core/platform/wpan/nm-wpan-utils.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef __WPAN_UTILS_H__ -#define __WPAN_UTILS_H__ - -#include - -#include "nm-dbus-interface.h" -#include "nm-platform/nm-netlink.h" - -typedef struct NMWpanUtils NMWpanUtils; - -#define NM_TYPE_WPAN_UTILS (nm_wpan_utils_get_type()) -#define NM_WPAN_UTILS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WPAN_UTILS, NMWpanUtils)) -#define NM_WPAN_UTILS_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WPAN_UTILS, NMWpanUtilsClass)) -#define NM_IS_WPAN_UTILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WPAN_UTILS)) -#define NM_IS_WPAN_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WPAN_UTILS)) -#define NM_WPAN_UTILS_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WPAN_UTILS, NMWpanUtilsClass)) - -GType nm_wpan_utils_get_type(void); - -NMWpanUtils *nm_wpan_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan); - -guint16 nm_wpan_utils_get_pan_id(NMWpanUtils *self); -gboolean nm_wpan_utils_set_pan_id(NMWpanUtils *self, guint16 pan_id); - -guint16 nm_wpan_utils_get_short_addr(NMWpanUtils *self); -gboolean nm_wpan_utils_set_short_addr(NMWpanUtils *self, guint16 short_addr); - -gboolean nm_wpan_utils_set_channel(NMWpanUtils *self, guint8 page, guint8 channel); - -#endif /* __WPAN_UTILS_H__ */ diff --git a/src/core/ppp/meson.build b/src/core/ppp/meson.build index 607b4718..9ee46113 100644 --- a/src/core/ppp/meson.build +++ b/src/core/ppp/meson.build @@ -4,9 +4,20 @@ nm_pppd_plugin = shared_module( 'nm-pppd-plugin', name_prefix: '', sources: 'nm-pppd-plugin.c', - dependencies: libnm_core_nm_default_dep, - c_args: [ - '-DG_LOG_DOMAIN="nm-pppd-plugin"', + include_directories: [ + src_inc, + top_inc, + ], + dependencies: [ + libnm_core_public_dep, + glib_dep, + ], + link_with: [ + libnm_core_impl, + libnm_log_null, + libnm_glib_aux, + libnm_std_aux, + libc_siphash, ], install: true, install_dir: pppd_plugin_dir, @@ -20,7 +31,6 @@ core_plugins += shared_module( 'nm-ppp-manager.c', ], dependencies: core_plugin_dep, - c_args: daemon_c_flags, link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, install: true, diff --git a/src/core/ppp/nm-ppp-manager-call.c b/src/core/ppp/nm-ppp-manager-call.c index f791e8b0..5e84f596 100644 --- a/src/core/ppp/nm-ppp-manager-call.c +++ b/src/core/ppp/nm-ppp-manager-call.c @@ -18,17 +18,21 @@ /*****************************************************************************/ -static NMPPPOps *ppp_ops = NULL; +static const NMPPPOps *_ppp_ops = NULL; + +#define ppp_ops_get() ((const NMPPPOps *) g_atomic_pointer_get(&_ppp_ops)) NMPPPManager * nm_ppp_manager_create(const char *iface, GError **error) { - NMPPPManager *ret; - GModule * plugin; - GError * error_local = NULL; - NMPPPOps * ops; - struct stat st; - + NMPPPManager * ret; + GModule * plugin; + GError * error_local = NULL; + struct stat st; + const NMPPPOps *ppp_ops; + +again: + ppp_ops = ppp_ops_get(); if (G_UNLIKELY(!ppp_ops)) { if (stat(PPP_PLUGIN_PATH, &st) != 0) { g_set_error_literal(error, @@ -58,7 +62,7 @@ nm_ppp_manager_create(const char *iface, GError **error) return NULL; } - if (!g_module_symbol(plugin, "ppp_ops", (gpointer) &ops)) { + if (!g_module_symbol(plugin, "ppp_ops", (gpointer *) &ppp_ops)) { g_set_error(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_MISSING_PLUGIN, @@ -67,18 +71,21 @@ nm_ppp_manager_create(const char *iface, GError **error) return NULL; } + nm_assert(ppp_ops); + nm_assert(ppp_ops->create); + nm_assert(ppp_ops->start); + nm_assert(ppp_ops->stop); + nm_assert(ppp_ops->stop_cancel); + + if (!g_atomic_pointer_compare_and_exchange(&_ppp_ops, NULL, ppp_ops)) { + g_module_close(plugin); + goto again; + } + /* after loading glib types from the plugin, we cannot unload the library anymore. * Make it resident. */ g_module_make_resident(plugin); - nm_assert(ops); - nm_assert(ops->create); - nm_assert(ops->start); - nm_assert(ops->stop); - nm_assert(ops->stop_cancel); - - ppp_ops = ops; - nm_log_info(LOGD_CORE | LOGD_PPP, "loaded PPP plugin " PPP_PLUGIN_PATH); } @@ -94,6 +101,8 @@ nm_ppp_manager_set_route_parameters(NMPPPManager *self, guint32 ip6_route_table, guint32 ip6_route_metric) { + const NMPPPOps *ppp_ops = ppp_ops_get(); + g_return_if_fail(ppp_ops); ppp_ops->set_route_parameters(self, @@ -111,6 +120,8 @@ nm_ppp_manager_start(NMPPPManager *self, guint baud_override, GError ** err) { + const NMPPPOps *ppp_ops = ppp_ops_get(); + g_return_val_if_fail(ppp_ops, FALSE); return ppp_ops->start(self, req, ppp_name, timeout_secs, baud_override, err); @@ -122,6 +133,8 @@ nm_ppp_manager_stop(NMPPPManager * self, NMPPPManagerStopCallback callback, gpointer user_data) { + const NMPPPOps *ppp_ops = ppp_ops_get(); + g_return_val_if_fail(ppp_ops, NULL); return ppp_ops->stop(self, cancellable, callback, user_data); @@ -130,6 +143,8 @@ nm_ppp_manager_stop(NMPPPManager * self, void nm_ppp_manager_stop_cancel(NMPPPManagerStopHandle *handle) { + const NMPPPOps *ppp_ops = ppp_ops_get(); + g_return_if_fail(ppp_ops); g_return_if_fail(handle); diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index 396a49ae..fefc5d61 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -28,8 +28,9 @@ #include #include "NetworkManagerUtils.h" -#include "platform/nm-platform.h" -#include "nm-core-internal.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nm-platform-utils.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-act-request.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -998,7 +999,7 @@ _ppp_manager_start(NMPPPManager *self, /* Make sure /dev/ppp exists (bgo #533064) */ if (stat("/dev/ppp", &st) || !S_ISCHR(st.st_mode)) - nm_utils_modprobe(NULL, FALSE, "ppp_generic", NULL); + nmp_utils_modprobe(NULL, FALSE, "ppp_generic", NULL); connection = nm_act_request_get_applied_connection(req); g_return_val_if_fail(connection, FALSE); @@ -1445,11 +1446,11 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class) NULL, G_TYPE_NONE, 2, - G_TYPE_UINT /*guint32 in_bytes*/, - G_TYPE_UINT /*guint32 out_bytes*/); + G_TYPE_UINT, /* guint32 in_bytes */ + G_TYPE_UINT); /* guint32 out_bytes */ } -NMPPPOps ppp_ops = { +const NMPPPOps ppp_ops = { .create = _ppp_manager_new, .set_route_parameters = _ppp_manager_set_route_parameters, .start = _ppp_manager_start, diff --git a/src/core/ppp/nm-pppd-plugin.c b/src/core/ppp/nm-pppd-plugin.c index c9016dac..5ffa7d17 100644 --- a/src/core/ppp/nm-pppd-plugin.c +++ b/src/core/ppp/nm-pppd-plugin.c @@ -20,7 +20,7 @@ #include #include -#include "nm-glib-aux/nm-default-glib.h" +#include "libnm-glib-aux/nm-default-glib.h" #include "nm-dbus-interface.h" @@ -226,11 +226,10 @@ nm_ip_up(void *data, int arg) if (opts.dnsaddr[1]) dns[len++] = opts.dnsaddr[1]; - g_variant_builder_add( - &builder, - "{sv}", - NM_PPP_IP4_CONFIG_DNS, - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, dns, len, sizeof(guint32))); + g_variant_builder_add(&builder, + "{sv}", + NM_PPP_IP4_CONFIG_DNS, + nm_g_variant_new_au(dns, len)); } if (opts.winsaddr[0] || opts.winsaddr[1]) { @@ -242,11 +241,10 @@ nm_ip_up(void *data, int arg) if (opts.winsaddr[1]) wins[len++] = opts.winsaddr[1]; - g_variant_builder_add( - &builder, - "{sv}", - NM_PPP_IP4_CONFIG_WINS, - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, wins, len, sizeof(guint32))); + g_variant_builder_add(&builder, + "{sv}", + NM_PPP_IP4_CONFIG_WINS, + nm_g_variant_new_au(wins, len)); } g_message("nm-ppp-plugin: sending IPv4 config to NetworkManager..."); diff --git a/src/core/settings/nm-agent-manager.c b/src/core/settings/nm-agent-manager.c index 7e617909..a1c2eb9c 100644 --- a/src/core/settings/nm-agent-manager.c +++ b/src/core/settings/nm-agent-manager.c @@ -9,7 +9,7 @@ #include -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-dbus-interface.h" #include "nm-secret-agent.h" #include "nm-auth-utils.h" @@ -19,7 +19,7 @@ #include "nm-session-monitor.h" #include "nm-simple-connection.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "c-list/src/c-list.h" /*****************************************************************************/ diff --git a/src/core/settings/nm-secret-agent.c b/src/core/settings/nm-secret-agent.c index 7e7c5d7d..45152c27 100644 --- a/src/core/settings/nm-secret-agent.c +++ b/src/core/settings/nm-secret-agent.c @@ -10,11 +10,11 @@ #include #include -#include "nm-glib-aux/nm-c-list.h" -#include "nm-glib-aux/nm-dbus-aux.h" +#include "libnm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-dbus-aux.h" #include "nm-dbus-interface.h" -#include "nm-core-internal.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-simple-connection.h" #include "NetworkManagerUtils.h" #include "c-list/src/c-list.h" @@ -583,7 +583,7 @@ nm_secret_agent_delete_secrets(NMSecretAgent * self, priv = NM_SECRET_AGENT_GET_PRIVATE(self); /* No secrets sent; agents must be smart enough to track secrets using the UUID or something */ - dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); + dict = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_WITH_NON_SECRET); call_id = _call_id_new(self, METHOD_DELETE_SECRETS, path, NULL, callback, callback_data); diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c index 0ff07189..b423bf5b 100644 --- a/src/core/settings/nm-settings-connection.c +++ b/src/core/settings/nm-settings-connection.c @@ -10,8 +10,9 @@ #include "c-list/src/c-list.h" -#include "nm-glib-aux/nm-keyfile-aux.h" -#include "nm-libnm-core-intern/nm-common-macros.h" +#include "libnm-glib-aux/nm-keyfile-aux.h" +#include "libnm-glib-aux/nm-c-list.h" +#include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-config.h" #include "nm-config-data.h" #include "nm-dbus-interface.h" @@ -20,7 +21,7 @@ #include "nm-auth-utils.h" #include "nm-agent-manager.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-audit-manager.h" #include "nm-settings.h" #include "nm-dbus-manager.h" @@ -30,10 +31,13 @@ #define AUTOCONNECT_RETRIES_FOREVER -1 #define AUTOCONNECT_RESET_RETRIES_TIMER 300 -#define _NM_SETTINGS_UPDATE2_FLAG_ALL_PERSIST_MODES \ - ((NMSettingsUpdate2Flags)( \ - NM_SETTINGS_UPDATE2_FLAG_TO_DISK | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY \ - | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY)) +#define SEEN_BSSIDS_MAX 30 + +#define _NM_SETTINGS_UPDATE2_FLAG_ALL_PERSIST_MODES \ + ((NMSettingsUpdate2Flags) (NM_SETTINGS_UPDATE2_FLAG_TO_DISK \ + | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY \ + | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED \ + | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY)) /*****************************************************************************/ @@ -58,6 +62,56 @@ nm_settings_connections_array_to_connections(NMSettingsConnection *const *connec /*****************************************************************************/ +typedef struct { + char bssid[sizeof(NMEtherAddr) * 3]; + CList seen_bssids_lst; +} SeenBssidEntry; + +static inline SeenBssidEntry * +_seen_bssid_entry_init_stale(SeenBssidEntry *entry, const NMEtherAddr *bssid_bin) +{ + _nm_utils_hwaddr_ntoa(bssid_bin, sizeof(NMEtherAddr), TRUE, entry->bssid, sizeof(entry->bssid)); + return entry; +} + +static inline SeenBssidEntry * +_seen_bssid_entry_new_stale_bin(const NMEtherAddr *bssid_bin) +{ + return _seen_bssid_entry_init_stale(g_slice_new(SeenBssidEntry), bssid_bin); +} + +static inline SeenBssidEntry * +_seen_bssid_entry_new_stale_copy(const SeenBssidEntry *src) +{ + SeenBssidEntry *entry; + + entry = g_slice_new(SeenBssidEntry); + memcpy(entry->bssid, src->bssid, sizeof(entry->bssid)); + return entry; +} + +static void +_seen_bssid_entry_free(gpointer data) +{ + SeenBssidEntry *entry = data; + + c_list_unlink_stale(&entry->seen_bssids_lst); + nm_g_slice_free(entry); +} + +/*****************************************************************************/ + +static GHashTable * +_seen_bssids_hash_new(void) +{ + return g_hash_table_new_full(nm_str_hash, + g_str_equal, + (GDestroyNotify) _seen_bssid_entry_free, + NULL); +} + +/*****************************************************************************/ + NM_GOBJECT_PROPERTIES_DEFINE(NMSettingsConnection, PROP_UNSAVED, PROP_FLAGS, PROP_FILENAME, ); enum { UPDATED_INTERNAL, FLAGS_CHANGED, LAST_SIGNAL }; @@ -79,19 +133,17 @@ typedef struct _NMSettingsConnectionPrivate { NMConnection *connection; + struct { + NMConnectionSerializationOptions options; + GVariant * variant; + } getsettings_cached; + NMSettingsStorage *storage; char *filename; NMDevice *default_wired_device; - /* Caches secrets from on-disk connections; were they not cached any - * call to nm_connection_clear_secrets() wipes them out and we'd have - * to re-read them from disk which defeats the purpose of having the - * connection in-memory at all. - */ - GVariant *system_secrets; - /* Caches secrets from agents during the activation process; if new system * secrets are returned from an agent, they get written out to disk, * triggering a re-read of the connection, which reads only system @@ -100,7 +152,8 @@ typedef struct _NMSettingsConnectionPrivate { */ GVariant *agent_secrets; - GHashTable *seen_bssids; /* Up-to-date BSSIDs that's been seen for the connection */ + CList seen_bssids_lst_head; + GHashTable *seen_bssids_hash; guint64 timestamp; /* Up-to-date timestamp of connection use */ @@ -168,8 +221,9 @@ static const GDBusSignalInfo signal_info_updated; static const GDBusSignalInfo signal_info_removed; static const NMDBusInterfaceInfoExtended interface_info_settings_connection; -static void update_system_secrets_cache(NMSettingsConnection *self, NMConnection *new); -static void update_agent_secrets_cache(NMSettingsConnection *self, NMConnection *new); +static void update_agent_secrets_cache(NMSettingsConnection *self, NMConnection *new); +static guint _get_seen_bssids(NMSettingsConnection *self, + const char * strv_buf[static(SEEN_BSSIDS_MAX + 1)]); /*****************************************************************************/ @@ -248,10 +302,53 @@ nm_settings_connection_still_valid(NMSettingsConnection *self) /*****************************************************************************/ -static GHashTable * -_seen_bssids_hash_new(void) +static void +_getsettings_cached_clear(NMSettingsConnectionPrivate *priv) { - return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, NULL); + if (nm_clear_pointer(&priv->getsettings_cached.variant, g_variant_unref)) { + priv->getsettings_cached.options.timestamp.has = FALSE; + priv->getsettings_cached.options.timestamp.val = 0; + nm_clear_g_free((gpointer *) &priv->getsettings_cached.options.seen_bssids); + } +} + +static GVariant * +_getsettings_cached_get(NMSettingsConnection *self, const NMConnectionSerializationOptions *options) +{ + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); + GVariant * variant; + + if (priv->getsettings_cached.variant) { + if (nm_connection_serialization_options_equal(&priv->getsettings_cached.options, options)) { +#if NM_MORE_ASSERTS > 10 + gs_unref_variant GVariant *variant2 = NULL; + + variant = nm_connection_to_dbus_full(priv->connection, + NM_CONNECTION_SERIALIZE_WITH_NON_SECRET, + options); + nm_assert(variant); + variant2 = g_variant_new("(@a{sa{sv}})", variant); + nm_assert(g_variant_equal(priv->getsettings_cached.variant, variant2)); +#endif + return priv->getsettings_cached.variant; + } + _getsettings_cached_clear(priv); + } + + nm_assert(!priv->getsettings_cached.options.seen_bssids); + + variant = nm_connection_to_dbus_full(priv->connection, + NM_CONNECTION_SERIALIZE_WITH_NON_SECRET, + options); + nm_assert(variant); + + priv->getsettings_cached.variant = g_variant_ref_sink(g_variant_new("(@a{sa{sv}})", variant)); + + priv->getsettings_cached.options = *options; + priv->getsettings_cached.options.seen_bssids = + nm_utils_strv_dup_packed(priv->getsettings_cached.options.seen_bssids, -1); + + return priv->getsettings_cached.variant; } /*****************************************************************************/ @@ -287,6 +384,9 @@ _nm_settings_connection_set_connection(NMSettingsConnection * self, priv->connection = g_object_ref(new_connection); nmtst_connection_assert_unchanging(priv->connection); + _getsettings_cached_clear(priv); + _nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(priv->settings); + /* note that we only return @connection_old if the new connection actually differs from * before. * @@ -298,11 +398,6 @@ _nm_settings_connection_set_connection(NMSettingsConnection * self, NM_SET_OUT(out_connection_old, g_steal_pointer(&connection_old)); } - if (NM_FLAGS_HAS(update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_SYSTEM_SECRETS)) - update_system_secrets_cache(self, NULL); - else if (NM_FLAGS_HAS(update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS)) - update_system_secrets_cache(self, priv->connection); - if (NM_FLAGS_HAS(update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS)) update_agent_secrets_cache(self, NULL); else if (NM_FLAGS_HAS(update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS)) @@ -433,64 +528,21 @@ nm_settings_connection_check_permission(NMSettingsConnection *self, const char * /*****************************************************************************/ -static void -update_system_secrets_cache(NMSettingsConnection *self, NMConnection *new) -{ - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); - gs_unref_object NMConnection *connection_cloned = NULL; - gs_unref_variant GVariant *old_secrets = NULL; - - old_secrets = g_steal_pointer(&priv->system_secrets); - - if (!new) - goto out; - - /* FIXME: improve NMConnection API so we can avoid the overhead of cloning the connection, - * in particular if there are no secrets to begin with. */ - - connection_cloned = nm_simple_connection_new_clone(new); - - /* Clear out non-system-owned and not-saved secrets */ - _nm_connection_clear_secrets_by_secret_flags(connection_cloned, NM_SETTING_SECRET_FLAG_NONE); - - priv->system_secrets = nm_g_variant_ref_sink( - nm_connection_to_dbus(connection_cloned, NM_CONNECTION_SERIALIZE_ONLY_SECRETS)); - -out: - if (_LOGT_ENABLED()) { - if ((!!old_secrets) != (!!priv->system_secrets)) { - _LOGT("update system secrets: secrets %s", old_secrets ? "cleared" : "set"); - } else if (priv->system_secrets && !g_variant_equal(old_secrets, priv->system_secrets)) - _LOGT("update system secrets: secrets updated"); - } -} - static void update_agent_secrets_cache(NMSettingsConnection *self, NMConnection *new) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); - gs_unref_object NMConnection *connection_cloned = NULL; - gs_unref_variant GVariant *old_secrets = NULL; + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); + gs_unref_variant GVariant *old_secrets = NULL; old_secrets = g_steal_pointer(&priv->agent_secrets); - if (!new) - goto out; - - /* FIXME: improve NMConnection API so we can avoid the overhead of cloning the connection, - * in particular if there are no secrets to begin with. */ - - connection_cloned = nm_simple_connection_new_clone(new); - - /* Clear out non-system-owned secrets */ - _nm_connection_clear_secrets_by_secret_flags(connection_cloned, - NM_SETTING_SECRET_FLAG_NOT_SAVED - | NM_SETTING_SECRET_FLAG_AGENT_OWNED); - - priv->agent_secrets = nm_g_variant_ref_sink( - nm_connection_to_dbus(connection_cloned, NM_CONNECTION_SERIALIZE_ONLY_SECRETS)); + if (new) { + priv->agent_secrets = nm_g_variant_ref_sink( + nm_connection_to_dbus(new, + NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED + | NM_CONNECTION_SERIALIZE_WITH_SECRETS_NOT_SAVED)); + } -out: if (_LOGT_ENABLED()) { if ((!!old_secrets) != (!!priv->agent_secrets)) { _LOGT("update agent secrets: secrets %s", old_secrets ? "cleared" : "set"); @@ -499,39 +551,6 @@ out: } } -void -nm_settings_connection_clear_secrets(NMSettingsConnection *self, - gboolean clear_cached_system_secrets, - gboolean persist) -{ - gs_unref_object NMConnection *connection_cloned = NULL; - - if (!nm_settings_connection_still_valid(self)) - return; - - /* FIXME: add API to NMConnection so that we can clone a profile without secrets. */ - - connection_cloned = nm_simple_connection_new_clone(nm_settings_connection_get_connection(self)); - - nm_connection_clear_secrets(connection_cloned); - - if (!nm_settings_connection_update( - self, - connection_cloned, - persist ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP - : NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST, - NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_UPDATE_REASON_IGNORE_PERSIST_FAILURE - | (clear_cached_system_secrets - ? NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_SYSTEM_SECRETS - : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE) - | NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS, - "clear-secrets", - NULL)) - nm_assert_not_reached(); -} - static gboolean _secrets_update(NMConnection * connection, const char * setting_name, @@ -829,6 +848,18 @@ nm_settings_connection_new_secrets(NMSettingsConnection *self, return TRUE; } +static gboolean +match_secret_by_setting_name_and_flags_cb(NMSetting * setting, + const char * secret, + NMSettingSecretFlags flags, + gpointer user_data) +{ + const char *get_secrets_setting_name = user_data; + + return nm_streq(nm_setting_get_name(setting), get_secrets_setting_name) + && NM_FLAGS_HAS(flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED); +} + static void get_secrets_done_cb(NMAgentManager * manager, NMAgentManagerCallId call_id_a, @@ -846,7 +877,6 @@ get_secrets_done_cb(NMAgentManager * manager, NMSettingsConnectionPrivate *priv; NMConnection * applied_connection; gs_free_error GError *local = NULL; - gs_unref_variant GVariant *system_secrets = NULL; gs_unref_object NMConnection *new_connection = NULL; gboolean agent_had_system = FALSE; ForEachSecretFlags cmp_flags = {NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_SECRET_FLAG_NONE}; @@ -917,18 +947,12 @@ get_secrets_done_cb(NMAgentManager * manager, _LOGD("(%s:%p) secrets request completed", setting_name, call_id); - system_secrets = nm_g_variant_ref(priv->system_secrets); - new_connection = nm_simple_connection_new_clone(nm_settings_connection_get_connection(self)); - nm_connection_clear_secrets(new_connection); - - if (!_secrets_update(new_connection, setting_name, system_secrets, NULL, &local)) { - _LOGD("(%s:%p) failed to update with existing secrets: %s", - setting_name, - call_id, - local->message); - } + /* Remove old agent-owned secrets in the requested setting */ + nm_connection_clear_secrets_with_flags(new_connection, + match_secret_by_setting_name_and_flags_cb, + (gpointer) setting_name); /* Update the connection with the agent's secrets; by this point if any * system-owned secrets exist in 'secrets' the agent that provided them @@ -962,7 +986,8 @@ get_secrets_done_cb(NMAgentManager * manager, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, NM_SETTINGS_CONNECTION_UPDATE_REASON_IGNORE_PERSIST_FAILURE - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS + | (agent_had_system ? NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS + : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE) | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS, "get-new-secrets", NULL)) @@ -970,6 +995,8 @@ get_secrets_done_cb(NMAgentManager * manager, applied_connection = call_id->applied_connection; if (applied_connection) { + gs_unref_variant GVariant *filtered_secrets2 = NULL; + get_cmp_flags(self, call_id, applied_connection, @@ -981,18 +1008,12 @@ get_secrets_done_cb(NMAgentManager * manager, &agent_had_system, &cmp_flags); - nm_connection_clear_secrets(applied_connection); - - if (!system_secrets - || nm_connection_update_secrets(applied_connection, - setting_name, - system_secrets, - NULL)) { - gs_unref_variant GVariant *filtered_secrets2 = NULL; + nm_connection_clear_secrets_with_flags(applied_connection, + match_secret_by_setting_name_and_flags_cb, + (gpointer) setting_name); - filtered_secrets2 = validate_secret_flags(applied_connection, secrets, &cmp_flags); - nm_connection_update_secrets(applied_connection, setting_name, filtered_secrets2, NULL); - } + filtered_secrets2 = validate_secret_flags(applied_connection, secrets, &cmp_flags); + nm_connection_update_secrets(applied_connection, setting_name, filtered_secrets2, NULL); } _get_secrets_info_callback(call_id, agent_username, setting_name, local); @@ -1060,7 +1081,8 @@ nm_settings_connection_get_secrets(NMSettingsConnection * self, NMAgentManagerCallId call_id_a; gs_free char * joined_hints = NULL; NMSettingsConnectionCallId * call_id; - GError * local = NULL; + GError * local = NULL; + gs_unref_variant GVariant *system_secrets = NULL; g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(self), NULL); g_return_val_if_fail( @@ -1111,14 +1133,15 @@ nm_settings_connection_get_secrets(NMSettingsConnection * self, * Then we know that the this request probably did not yet include the latest secret-agent. */ priv->last_secret_agent_version_id = nm_agent_manager_get_agent_version_id(priv->agent_mgr); - /* Use priv->system_secrets to work around the fact that nm_connection_clear_secrets() - * will clear secrets on this object's settings. - */ + system_secrets = nm_g_variant_ref_sink( + nm_connection_to_dbus(nm_settings_connection_get_connection(self), + NM_CONNECTION_SERIALIZE_WITH_SECRETS_SYSTEM_OWNED)); + call_id_a = nm_agent_manager_get_secrets(priv->agent_mgr, nm_dbus_object_get_path(NM_DBUS_OBJECT(self)), nm_settings_connection_get_connection(self), subject, - priv->system_secrets, + system_secrets, setting_name, flags, hints, @@ -1325,9 +1348,8 @@ get_settings_auth_cb(NMSettingsConnection * self, GError * error, gpointer data) { - gs_free const char ** seen_bssids = NULL; - NMConnectionSerializationOptions options = {}; - GVariant * settings; + const char * seen_bssids_strv[SEEN_BSSIDS_MAX + 1]; + NMConnectionSerializationOptions options = {}; if (error) { g_dbus_method_invocation_return_gerror(context, error); @@ -1347,17 +1369,15 @@ get_settings_auth_cb(NMSettingsConnection * self, * from the same reason as timestamp. Thus we put it here to GetSettings() * return settings too. */ - seen_bssids = nm_settings_connection_get_seen_bssids(self); - options.seen_bssids = seen_bssids; + _get_seen_bssids(self, seen_bssids_strv); + options.seen_bssids = seen_bssids_strv; /* Secrets should *never* be returned by the GetSettings method, they * get returned by the GetSecrets method which can be better * protected against leakage of secrets to unprivileged callers. */ - settings = nm_connection_to_dbus_full(nm_settings_connection_get_connection(self), - NM_CONNECTION_SERIALIZE_NO_SECRETS, - &options); - g_dbus_method_invocation_return_value(context, g_variant_new("(@a{sa{sv}})", settings)); + + g_dbus_method_invocation_return_value(context, _getsettings_cached_get(self, &options)); } static void @@ -1488,14 +1508,21 @@ update_auth_cb(NMSettingsConnection * self, if (!_nm_connection_aggregate(info->new_settings, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)) { + gs_unref_variant GVariant *secrets = NULL; + /* If the new connection has no secrets, we do not want to remove all * secrets, rather we keep all the existing ones. Do that by merging * them in to the new connection. */ + secrets = nm_g_variant_ref_sink( + nm_connection_to_dbus(nm_settings_connection_get_connection(self), + NM_CONNECTION_SERIALIZE_WITH_SECRETS)); + + if (secrets) + nm_connection_update_secrets(info->new_settings, NULL, secrets, NULL); + if (priv->agent_secrets) nm_connection_update_secrets(info->new_settings, NULL, priv->agent_secrets, NULL); - if (priv->system_secrets) - nm_connection_update_secrets(info->new_settings, NULL, priv->system_secrets, NULL); } else { /* Cache the new secrets from the agent, as stuff like inotify-triggered * changes to connection's backing config files will blow them away if @@ -1558,6 +1585,7 @@ update_auth_cb(NMSettingsConnection * self, : NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL) | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET | (NM_FLAGS_HAS(info->flags, NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT) ? NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE), @@ -1568,7 +1596,7 @@ update_auth_cb(NMSettingsConnection * self, gs_unref_object NMConnection *for_agent = NULL; /* Dupe the connection so we can clear out non-agent-owned secrets, - * as agent-owned secrets are the only ones we send back be saved. + * as agent-owned secrets are the only ones we send back to be saved. * Only send secrets to agents of the same UID that called update too. */ for_agent = nm_simple_connection_new_clone(nm_settings_connection_get_connection(self)); @@ -1754,10 +1782,10 @@ impl_settings_connection_update2(NMDBusObject * obj, g_variant_get(parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args); if (NM_FLAGS_ANY(flags_u, - ~((guint32)(_NM_SETTINGS_UPDATE2_FLAG_ALL_PERSIST_MODES - | NM_SETTINGS_UPDATE2_FLAG_VOLATILE - | NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT - | NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY)))) { + ~((guint32) (_NM_SETTINGS_UPDATE2_FLAG_ALL_PERSIST_MODES + | NM_SETTINGS_UPDATE2_FLAG_VOLATILE + | NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT + | NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY)))) { error = g_error_new_literal(NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_ARGUMENTS, "Unknown flags"); @@ -1888,9 +1916,9 @@ dbus_get_agent_secrets_cb(NMSettingsConnection * self, * by the time we get here. */ dict = nm_connection_to_dbus(nm_settings_connection_get_connection(self), - NM_CONNECTION_SERIALIZE_ONLY_SECRETS); + NM_CONNECTION_SERIALIZE_WITH_SECRETS); if (!dict) - dict = g_variant_new_array(G_VARIANT_TYPE("{sa{sv}}"), NULL, 0); + dict = nm_g_variant_singleton_aLsaLsvII(); g_dbus_method_invocation_return_value(context, g_variant_new("(@a{sa{sv}})", dict)); } } @@ -1959,8 +1987,9 @@ dbus_clear_secrets_auth_cb(NMSettingsConnection * self, GError * error, gpointer user_data) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); - gs_free_error GError *local = NULL; + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); + gs_free_error GError *local = NULL; + gs_unref_object NMConnection *connection_cloned = NULL; if (error) { g_dbus_method_invocation_return_gerror(context, error); @@ -1973,7 +2002,24 @@ dbus_clear_secrets_auth_cb(NMSettingsConnection * self, return; } - nm_settings_connection_clear_secrets(self, TRUE, TRUE); + /* FIXME: add API to NMConnection so that we can clone a profile without secrets. */ + + connection_cloned = nm_simple_connection_new_clone(nm_settings_connection_get_connection(self)); + + nm_connection_clear_secrets(connection_cloned); + + if (!nm_settings_connection_update( + self, + connection_cloned, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, + NM_SETTINGS_CONNECTION_UPDATE_REASON_IGNORE_PERSIST_FAILURE + | NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_SYSTEM_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS, + "clear-secrets", + NULL)) + nm_assert_not_reached(); /* Tell agents to remove secrets for this connection */ nm_agent_manager_delete_secrets(priv->agent_mgr, @@ -2142,7 +2188,9 @@ _cmp_last_resort(NMSettingsConnection *a, NMSettingsConnection *b) /* hm, same UUID. Use their pointer value to give them a stable * order. */ - return (a > b) ? -1 : 1; + NM_CMP_DIRECT_PTR(a, b); + + return nm_assert_unreachable_val(0); } /* sorting for "best" connections. @@ -2183,6 +2231,15 @@ nm_settings_connection_cmp_autoconnect_priority(NMSettingsConnection *a, NMSetti return _cmp_last_resort(a, b); } +int +nm_settings_connection_cmp_autoconnect_priority_with_data(gconstpointer pa, + gconstpointer pb, + gpointer user_data) +{ + return nm_settings_connection_cmp_autoconnect_priority((NMSettingsConnection *) pa, + (NMSettingsConnection *) pb); +} + int nm_settings_connection_cmp_autoconnect_priority_p_with_data(gconstpointer pa, gconstpointer pb, @@ -2243,6 +2300,8 @@ nm_settings_connection_update_timestamp(NMSettingsConnection *self, guint64 time _LOGT("timestamp: set timestamp %" G_GUINT64_FORMAT, timestamp); + _nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(priv->settings); + if (!priv->kf_db_timestamps) return; @@ -2293,68 +2352,66 @@ _nm_settings_connection_register_kf_dbs(NMSettingsConnection *self, if (priv->kf_db_seen_bssids != kf_db_seen_bssids) { gs_strfreev char **tmp_strv = NULL; - gsize i, len; + gsize len; + gsize i; + guint result_len; nm_key_file_db_unref(priv->kf_db_seen_bssids); priv->kf_db_seen_bssids = nm_key_file_db_ref(kf_db_seen_bssids); tmp_strv = nm_key_file_db_get_string_list(priv->kf_db_seen_bssids, connection_uuid, &len); - nm_clear_pointer(&priv->seen_bssids, g_hash_table_unref); + if (priv->seen_bssids_hash) + g_hash_table_remove_all(priv->seen_bssids_hash); - if (len > 0) { - _LOGT("read %zu seen-bssids from keyfile database \"%s\"", - len, - nm_key_file_db_get_filename(priv->kf_db_seen_bssids)); - priv->seen_bssids = _seen_bssids_hash_new(); - for (i = len; i > 0;) - g_hash_table_add(priv->seen_bssids, g_steal_pointer(&tmp_strv[--i])); - nm_clear_g_free(&tmp_strv); - } else { - NMSettingWireless *s_wifi; + for (result_len = 0, i = 0; i < len; i++) { + NMEtherAddr addr_bin; + SeenBssidEntry *entry; - _LOGT("no seen-bssids from keyfile database \"%s\"", - nm_key_file_db_get_filename(priv->kf_db_seen_bssids)); + nm_assert(result_len == nm_g_hash_table_size(priv->seen_bssids_hash)); + if (result_len >= SEEN_BSSIDS_MAX) + break; - /* If this connection didn't have an entry in the seen-bssids database, - * maybe this is the first time we've read it in, so populate the - * seen-bssids list from the deprecated seen-bssids property of the - * wifi setting. - */ - s_wifi = - nm_connection_get_setting_wireless(nm_settings_connection_get_connection(self)); - if (s_wifi) { - len = nm_setting_wireless_get_num_seen_bssids(s_wifi); - if (len > 0) { - priv->seen_bssids = _seen_bssids_hash_new(); - for (i = 0; i < len; i++) { - const char *bssid = nm_setting_wireless_get_seen_bssid(s_wifi, i); - - g_hash_table_add(priv->seen_bssids, g_strdup(bssid)); - } - } + if (!_nm_utils_hwaddr_aton_exact(tmp_strv[i], &addr_bin, sizeof(addr_bin))) + continue; + + if (!priv->seen_bssids_hash) + priv->seen_bssids_hash = _seen_bssids_hash_new(); + + entry = _seen_bssid_entry_new_stale_bin(&addr_bin); + c_list_link_tail(&priv->seen_bssids_lst_head, &entry->seen_bssids_lst); + if (!g_hash_table_insert(priv->seen_bssids_hash, entry, entry)) { + /* duplicate detected! The @entry key was freed by g_hash_table_insert(). */ + continue; } + result_len++; } + if (result_len > 0) { + _LOGT("read %u seen-bssids from keyfile database \"%s\"", + result_len, + nm_key_file_db_get_filename(priv->kf_db_seen_bssids)); + } else + nm_clear_pointer(&priv->seen_bssids_hash, g_hash_table_destroy); + + nm_assert(nm_g_hash_table_size(priv->seen_bssids_hash) == result_len); + nm_assert(result_len <= SEEN_BSSIDS_MAX); } } -/** - * nm_settings_connection_get_seen_bssids: - * @self: the #NMSettingsConnection - * - * Returns current list of seen BSSIDs for the connection. - * - * Returns: (transfer container) list of seen BSSIDs (in the standard hex-digits-and-colons notation). - * The caller is responsible for freeing the list, but not the content. - **/ -const char ** -nm_settings_connection_get_seen_bssids(NMSettingsConnection *self) +static guint +_get_seen_bssids(NMSettingsConnection *self, const char *strv_buf[static(SEEN_BSSIDS_MAX + 1)]) { - g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(self), NULL); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); + SeenBssidEntry * entry; + guint i; - return nm_utils_strdict_get_keys(NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->seen_bssids, - TRUE, - NULL); + i = 0; + c_list_for_each_entry (entry, &priv->seen_bssids_lst_head, seen_bssids_lst) { + nm_assert(i <= SEEN_BSSIDS_MAX); + strv_buf[i++] = entry->bssid; + } + strv_buf[i] = NULL; + return i; } /** @@ -2368,14 +2425,17 @@ gboolean nm_settings_connection_has_seen_bssid(NMSettingsConnection *self, const char *bssid) { NMSettingsConnectionPrivate *priv; + NMEtherAddr addr_bin; g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(self), FALSE); g_return_val_if_fail(bssid, FALSE); + nm_assert(_nm_utils_hwaddr_aton_exact(bssid, &addr_bin, sizeof(addr_bin))); priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); - return priv->seen_bssids - && g_hash_table_contains(NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->seen_bssids, bssid); + return priv->seen_bssids_hash + && g_hash_table_contains(NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->seen_bssids_hash, + bssid); } /** @@ -2390,15 +2450,47 @@ void nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *seen_bssid) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); - gs_free const char ** strv = NULL; + const char * seen_bssids_strv[SEEN_BSSIDS_MAX + 1]; + NMEtherAddr addr_bin; const char * connection_uuid; + SeenBssidEntry entry_stack; + SeenBssidEntry * entry; + guint i; - g_return_if_fail(seen_bssid != NULL); + g_return_if_fail(seen_bssid); - if (!priv->seen_bssids) - priv->seen_bssids = _seen_bssids_hash_new(); + if (!_nm_utils_hwaddr_aton_exact(seen_bssid, &addr_bin, sizeof(addr_bin))) + g_return_if_reached(); - g_hash_table_add(priv->seen_bssids, g_strdup(seen_bssid)); + _seen_bssid_entry_init_stale(&entry_stack, &addr_bin); + + if (!priv->seen_bssids_hash) { + priv->seen_bssids_hash = _seen_bssids_hash_new(); + entry = NULL; + } else + entry = g_hash_table_lookup(priv->seen_bssids_hash, &entry_stack); + + if (entry) { + if (!nm_c_list_move_front(&priv->seen_bssids_lst_head, &entry->seen_bssids_lst)) { + /* no change. */ + return; + } + } else { + entry = _seen_bssid_entry_new_stale_copy(&entry_stack); + c_list_link_front(&priv->seen_bssids_lst_head, &entry->seen_bssids_lst); + if (!g_hash_table_add(priv->seen_bssids_hash, entry)) + nm_assert_not_reached(); + + if (g_hash_table_size(priv->seen_bssids_hash) > SEEN_BSSIDS_MAX) { + g_hash_table_remove( + priv->seen_bssids_hash, + c_list_last_entry(&priv->seen_bssids_lst_head, SeenBssidEntry, seen_bssids_lst)); + } + } + + nm_assert(g_hash_table_size(priv->seen_bssids_hash) <= SEEN_BSSIDS_MAX); + nm_assert(g_hash_table_size(priv->seen_bssids_hash) + == c_list_length(&priv->seen_bssids_lst_head)); if (!priv->kf_db_seen_bssids) return; @@ -2407,12 +2499,8 @@ nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *se if (!connection_uuid) return; - strv = nm_utils_strdict_get_keys(priv->seen_bssids, TRUE, NULL); - - nm_key_file_db_set_string_list(priv->kf_db_seen_bssids, - connection_uuid, - strv ?: NM_PTRARRAY_EMPTY(const char *), - -1); + i = _get_seen_bssids(self, seen_bssids_strv); + nm_key_file_db_set_string_list(priv->kf_db_seen_bssids, connection_uuid, seen_bssids_strv, i); } /*****************************************************************************/ @@ -2623,7 +2711,7 @@ nm_settings_connection_init(NMSettingsConnection *self) self->_priv = priv; c_list_init(&self->_connections_lst); - + c_list_init(&priv->seen_bssids_lst_head); c_list_init(&priv->call_ids_lst_head); c_list_init(&priv->auth_lst_head); @@ -2659,15 +2747,16 @@ dispose(GObject *object) _get_secrets_cancel(self, call_id, TRUE); } - nm_clear_pointer(&priv->system_secrets, g_variant_unref); nm_clear_pointer(&priv->agent_secrets, g_variant_unref); - nm_clear_pointer(&priv->seen_bssids, g_hash_table_destroy); + nm_clear_pointer(&priv->seen_bssids_hash, g_hash_table_destroy); g_clear_object(&priv->agent_mgr); g_clear_object(&priv->connection); + _getsettings_cached_clear(priv); + nm_clear_pointer(&priv->kf_db_timestamps, nm_key_file_db_unref); nm_clear_pointer(&priv->kf_db_seen_bssids, nm_key_file_db_unref); @@ -2732,20 +2821,17 @@ static const NMDBusInterfaceInfoExtended interface_info_settings_connection = { .out_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("result", "a{sv}"), ), ), .handle = impl_settings_connection_update2, ), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_updated, - &signal_info_removed, ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_updated, &signal_info_removed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Unsaved", - "b", - NM_SETTINGS_CONNECTION_UNSAVED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Unsaved", + "b", + NM_SETTINGS_CONNECTION_UNSAVED), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Flags", "u", NM_SETTINGS_CONNECTION_FLAGS), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Filename", "s", NM_SETTINGS_CONNECTION_FILENAME), ), ), - .legacy_property_changed = TRUE, }; static void diff --git a/src/core/settings/nm-settings-connection.h b/src/core/settings/nm-settings-connection.h index 7c61dbeb..fa3dbcfb 100644 --- a/src/core/settings/nm-settings-connection.h +++ b/src/core/settings/nm-settings-connection.h @@ -63,6 +63,9 @@ typedef enum { NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT = (1u << 8), + /* Is anything other than secrets changing */ + NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET = (1u << 9), + } NMSettingsConnectionUpdateReason; typedef enum { @@ -274,10 +277,6 @@ nm_settings_connection_get_secrets(NMSettingsConnection * self, void nm_settings_connection_cancel_secrets(NMSettingsConnection * self, NMSettingsConnectionCallId *call_id); -void nm_settings_connection_clear_secrets(NMSettingsConnection *self, - gboolean clear_cached_system_secrets, - gboolean persist); - gboolean nm_settings_connection_check_visibility(NMSettingsConnection *self, NMSessionMonitor * session_monitor); @@ -324,6 +323,9 @@ int nm_settings_connection_cmp_timestamp_p_with_data(gconstpointer pa, gpointer user_data); int nm_settings_connection_cmp_autoconnect_priority(NMSettingsConnection *a, NMSettingsConnection *b); +int nm_settings_connection_cmp_autoconnect_priority_with_data(gconstpointer pa, + gconstpointer pb, + gpointer user_data); int nm_settings_connection_cmp_autoconnect_priority_p_with_data(gconstpointer pa, gconstpointer pb, gpointer user_data); @@ -338,8 +340,6 @@ gboolean nm_settings_connection_get_timestamp(NMSettingsConnection *self, guint6 void nm_settings_connection_update_timestamp(NMSettingsConnection *self, guint64 timestamp); -const char **nm_settings_connection_get_seen_bssids(NMSettingsConnection *self); - gboolean nm_settings_connection_has_seen_bssid(NMSettingsConnection *self, const char *bssid); void nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *seen_bssid); diff --git a/src/core/settings/nm-settings-plugin.c b/src/core/settings/nm-settings-plugin.c index 9e81caab..66cc19b6 100644 --- a/src/core/settings/nm-settings-plugin.c +++ b/src/core/settings/nm-settings-plugin.c @@ -9,7 +9,7 @@ #include "nm-settings-plugin.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-settings-connection.h" diff --git a/src/core/settings/nm-settings-storage.c b/src/core/settings/nm-settings-storage.c index c56ba075..e284b822 100644 --- a/src/core/settings/nm-settings-storage.c +++ b/src/core/settings/nm-settings-storage.c @@ -7,6 +7,7 @@ #include "nm-settings-storage.h" +#include "libnm-glib-aux/nm-uuid.h" #include "nm-utils.h" #include "nm-settings-plugin.h" @@ -72,7 +73,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps case PROP_UUID: /* construct-only */ self->_uuid = g_value_dup_string(value); - nm_assert(!self->_uuid || nm_utils_is_uuid(self->_uuid)); + nm_assert(!self->_uuid || nm_uuid_is_normalized(self->_uuid)); break; case PROP_FILENAME: /* construct-only */ @@ -97,7 +98,7 @@ NMSettingsStorage * nm_settings_storage_new(NMSettingsPlugin *plugin, const char *uuid, const char *filename) { nm_assert(NM_IS_SETTINGS_PLUGIN(plugin)); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); return g_object_new(NM_TYPE_SETTINGS_STORAGE, NM_SETTINGS_STORAGE_PLUGIN, diff --git a/src/core/settings/nm-settings-storage.h b/src/core/settings/nm-settings-storage.h index 970cfd77..2e5e1c55 100644 --- a/src/core/settings/nm-settings-storage.h +++ b/src/core/settings/nm-settings-storage.h @@ -48,36 +48,35 @@ GType nm_settings_storage_get_type(void); NMSettingsStorage * nm_settings_storage_new(struct _NMSettingsPlugin *plugin, const char *uuid, const char *filename); +/* forward declare so we don't have to include "nm-settings-plugin.h" here. */ +GType nm_settings_plugin_get_type(void); + static inline struct _NMSettingsPlugin * nm_settings_storage_get_plugin(const NMSettingsStorage *self) { - GType nm_settings_plugin_get_type(void); - g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL); nm_assert(G_TYPE_CHECK_INSTANCE_TYPE(self->_plugin, nm_settings_plugin_get_type())); return self->_plugin; } +gboolean nm_uuid_is_normalized_full(const char *str); + static inline const char * nm_settings_storage_get_uuid(const NMSettingsStorage *self) { - gboolean nm_utils_is_uuid(const char *str); - g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL); - nm_assert(nm_utils_is_uuid(self->_uuid)); + nm_assert(nm_uuid_is_normalized_full(self->_uuid)); return self->_uuid; } static inline const char * nm_settings_storage_get_uuid_opt(const NMSettingsStorage *self) { - gboolean nm_utils_is_uuid(const char *str); - g_return_val_if_fail(NM_IS_SETTINGS_STORAGE(self), NULL); - nm_assert(!self->_uuid || nm_utils_is_uuid(self->_uuid)); + nm_assert(!self->_uuid || nm_uuid_is_normalized_full(self->_uuid)); return self->_uuid; } diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c index 3d31fb8b..f9f98de7 100644 --- a/src/core/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -20,9 +20,10 @@ #include #endif -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-glib-aux/nm-keyfile-aux.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-keyfile-aux.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-setting-8021x.h" @@ -44,17 +45,17 @@ #include "nm-setting-proxy.h" #include "nm-setting-bond.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" -#include "nm-std-aux/c-list-util.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-std-aux/c-list-util.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-dbus-object.h" #include "devices/nm-device-ethernet.h" #include "nm-settings-connection.h" #include "nm-settings-plugin.h" #include "nm-dbus-manager.h" #include "nm-auth-utils.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-session-monitor.h" #include "plugins/keyfile/nms-keyfile-plugin.h" #include "plugins/keyfile/nms-keyfile-storage.h" @@ -139,7 +140,7 @@ nm_assert_storage_data_lst(CList *head) u = nm_settings_storage_get_uuid(sd->storage); if (!uuid) { uuid = u; - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); } else nm_assert(nm_streq0(uuid, u)); } @@ -182,7 +183,7 @@ _sett_conn_entry_new(const char *uuid) SettConnEntry *sett_conn_entry; gsize l_p_1; - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); l_p_1 = strlen(uuid) + 1; @@ -370,6 +371,7 @@ typedef struct { CList connections_lst_head; NMSettingsConnection **connections_cached_list; + NMSettingsConnection **connections_cached_list_sorted_by_autoconnect_priority; GSList *unmanaged_specs; GSList *unrecognized_specs; @@ -386,8 +388,17 @@ typedef struct { guint kf_db_flush_idle_id_timestamps; guint kf_db_flush_idle_id_seen_bssids; + bool kf_db_pruned_timestamps; + bool kf_db_pruned_seen_bssid; + bool started : 1; + /* Whether NMSettingsConnections changed in a way that affects the comparison + * with nm_settings_connection_cmp_autoconnect_priority_with_data(). In that case, + * we may need to re-sort the connections_cached_list_sorted_by_autoconnect_priority + * list. */ + bool sorted_by_autoconnect_priority_maybe_changed : 1; + } NMSettingsPrivate; struct _NMSettings { @@ -487,6 +498,8 @@ _startup_complete_check_is_ready(NMSettings * self, conn = nm_settings_connection_get_connection(sett_conn); nm_manager_for_each_device (priv->manager, device, tmp_lst) { + gs_free_error GError *error = NULL; + if (!nm_device_is_real(device)) continue; @@ -497,7 +510,13 @@ _startup_complete_check_is_ready(NMSettings * self, continue; } - if (!nm_device_check_connection_compatible(device, conn, NULL)) + /* Check that device is compatible with the device. We are also happy + * with a device compatible but for which the connection is disallowed + * by NM configuration. */ + if (!nm_device_check_connection_compatible(device, conn, &error) + && !g_error_matches(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_DISALLOWED)) continue; return TRUE; @@ -1433,7 +1452,8 @@ _plugin_connections_reload(NMSettings *self) NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, TRUE, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS); + | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET); for (iter = priv->plugins; iter; iter = iter->next) nm_settings_plugin_load_connections_done(iter->data); @@ -1460,7 +1480,7 @@ _add_connection_to_first_plugin(NMSettings * self, uuid = nm_connection_get_uuid(new_connection); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); for (iter = priv->plugins; iter; iter = iter->next) { NMSettingsPlugin *plugin = NM_SETTINGS_PLUGIN(iter->data); @@ -1541,9 +1561,7 @@ _add_connection_to_first_plugin(NMSettings * self, } agent_owned_secrets = - nm_connection_to_dbus(new_connection, - NM_CONNECTION_SERIALIZE_ONLY_SECRETS - | NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); + nm_connection_to_dbus(new_connection, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); connection_to_add_real = _connection_changed_normalize_connection(storage, connection_to_add, @@ -1912,7 +1930,8 @@ again_delete_tombstone: _NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK, FALSE, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET | (NM_FLAGS_HAS(add_reason, NM_SETTINGS_CONNECTION_ADD_REASON_BLOCK_AUTOCONNECT) ? NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE)); @@ -2218,9 +2237,7 @@ nm_settings_update_connection(NMSettings * self, nm_assert(nm_streq(uuid, nm_settings_storage_get_uuid(new_storage))); agent_owned_secrets = - nm_connection_to_dbus(connection, - NM_CONNECTION_SERIALIZE_ONLY_SECRETS - | NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); + nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); new_connection_real = _connection_changed_normalize_connection(new_storage, new_connection, agent_owned_secrets, @@ -2297,7 +2314,7 @@ nm_settings_delete_connection(NMSettings * self, nm_assert(NM_IS_SETTINGS_STORAGE(cur_storage)); uuid = nm_settings_storage_get_uuid(cur_storage); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); sett_conn_entry = _sett_conn_entries_get(self, uuid); @@ -2691,9 +2708,9 @@ impl_settings_add_connection2(NMDBusObject * obj, g_variant_get(parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args); if (NM_FLAGS_ANY(flags_u, - ~((guint32)(NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK - | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY - | NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)))) { + ~((guint32) (NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK + | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY + | NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)))) { g_dbus_method_invocation_take_error(invocation, g_error_new_literal(NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_ARGUMENTS, @@ -2814,7 +2831,8 @@ impl_settings_load_connections(NMDBusObject * obj, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, TRUE, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS); + | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET); for (iter = priv->plugins; iter; iter = iter->next) nm_settings_plugin_load_connections_done(iter->data); @@ -2832,7 +2850,7 @@ impl_settings_load_connections(NMDBusObject * obj, g_dbus_method_invocation_return_value(invocation, g_variant_new("(b^as)", - (gboolean)(!failures), + (gboolean) (!failures), failures ? (const char **) failures->pdata : NM_PTRARRAY_EMPTY(const char *))); @@ -2870,25 +2888,48 @@ impl_settings_reload_connections(NMDBusObject * obj, /*****************************************************************************/ +void +_nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(NMSettings *self) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self); + + priv->sorted_by_autoconnect_priority_maybe_changed = TRUE; +} + static void _clear_connections_cached_list(NMSettingsPrivate *priv) { - if (!priv->connections_cached_list) - return; + if (priv->connections_cached_list) { + nm_assert(priv->connections_len == NM_PTRARRAY_LEN(priv->connections_cached_list)); + +#if NM_MORE_ASSERTS + /* set the pointer to a bogus value. This makes it more apparent + * if somebody has a reference to the cached list and still uses + * it. That is a bug, this code just tries to make it blow up + * more eagerly. */ + memset(priv->connections_cached_list, + 0x43, + sizeof(NMSettingsConnection *) * (priv->connections_len + 1)); +#endif - nm_assert(priv->connections_len == NM_PTRARRAY_LEN(priv->connections_cached_list)); + nm_clear_g_free(&priv->connections_cached_list); + } + if (priv->connections_cached_list_sorted_by_autoconnect_priority) { + nm_assert(priv->connections_len + == NM_PTRARRAY_LEN(priv->connections_cached_list_sorted_by_autoconnect_priority)); #if NM_MORE_ASSERTS - /* set the pointer to a bogus value. This makes it more apparent - * if somebody has a reference to the cached list and still uses - * it. That is a bug, this code just tries to make it blow up - * more eagerly. */ - memset(priv->connections_cached_list, - 0x43, - sizeof(NMSettingsConnection *) * (priv->connections_len + 1)); + /* set the pointer to a bogus value. This makes it more apparent + * if somebody has a reference to the cached list and still uses + * it. That is a bug, this code just tries to make it blow up + * more eagerly. */ + memset(priv->connections_cached_list_sorted_by_autoconnect_priority, + 0x42, + sizeof(NMSettingsConnection *) * (priv->connections_len + 1)); #endif - nm_clear_g_free(&priv->connections_cached_list); + nm_clear_g_free(&priv->connections_cached_list_sorted_by_autoconnect_priority); + } } static void @@ -3027,6 +3068,65 @@ nm_settings_get_connections(NMSettings *self, guint *out_len) return priv->connections_cached_list; } +NMSettingsConnection *const * +nm_settings_get_connections_sorted_by_autoconnect_priority(NMSettings *self, guint *out_len) +{ + NMSettingsPrivate *priv; + gboolean needs_sort = FALSE; + + g_return_val_if_fail(NM_IS_SETTINGS(self), NULL); + + priv = NM_SETTINGS_GET_PRIVATE(self); + + nm_assert(priv->connections_len == c_list_length(&priv->connections_lst_head)); + nm_assert( + !priv->connections_cached_list_sorted_by_autoconnect_priority + || (priv->connections_len + == NM_PTRARRAY_LEN(priv->connections_cached_list_sorted_by_autoconnect_priority))); + + if (!priv->connections_cached_list_sorted_by_autoconnect_priority) { + NMSettingsConnection *const *list_cached; + guint len; + + list_cached = nm_settings_get_connections(self, &len); + priv->connections_cached_list_sorted_by_autoconnect_priority = + nm_memdup(list_cached, sizeof(NMSettingsConnection *) * (len + 1)); + needs_sort = (len > 1); + } else if (priv->sorted_by_autoconnect_priority_maybe_changed) { + if (!nm_utils_ptrarray_is_sorted( + (gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority, + priv->connections_len, + FALSE, + nm_settings_connection_cmp_autoconnect_priority_with_data, + NULL)) { + /* We cache the sorted list, but we don't monitor all entries whether they + * get modified to invalidate the sort order. So every time we have to check + * whether the sort order is still correct. The vast majority of the time it + * is, and this check is faster than sorting anew. */ + needs_sort = TRUE; + } + } else { + nm_assert(nm_utils_ptrarray_is_sorted( + (gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority, + priv->connections_len, + TRUE, + nm_settings_connection_cmp_autoconnect_priority_with_data, + NULL)); + } + + priv->sorted_by_autoconnect_priority_maybe_changed = FALSE; + if (needs_sort) { + g_qsort_with_data(priv->connections_cached_list_sorted_by_autoconnect_priority, + priv->connections_len, + sizeof(NMSettingsConnection *), + nm_settings_connection_cmp_autoconnect_priority_p_with_data, + NULL); + } + + NM_SET_OUT(out_len, priv->connections_len); + return priv->connections_cached_list_sorted_by_autoconnect_priority; +} + /** * nm_settings_get_connections_clone: * @self: the #NMSetting @@ -3058,9 +3158,13 @@ nm_settings_get_connections_clone(NMSettings * self, g_return_val_if_fail(NM_IS_SETTINGS(self), NULL); - list_cached = nm_settings_get_connections(self, &len); + if (sort_compare_func == nm_settings_connection_cmp_autoconnect_priority_p_with_data) { + list_cached = nm_settings_get_connections_sorted_by_autoconnect_priority(self, &len); + sort_compare_func = NULL; + } else + list_cached = nm_settings_get_connections(self, &len); -#if NM_MORE_ASSERTS +#if NM_MORE_ASSERTS > 10 nm_assert(list_cached); for (i = 0; i < len; i++) nm_assert(NM_IS_SETTINGS_CONNECTION(list_cached[i])); @@ -3204,7 +3308,7 @@ add_plugin_load_file(NMSettings *self, const char *pname, GError **error) /* errors after this point are fatal, because we loaded the shared library already. */ - if (!g_module_symbol(module, "nm_settings_plugin_factory", (gpointer)(&factory_func))) { + if (!g_module_symbol(module, "nm_settings_plugin_factory", (gpointer) (&factory_func))) { g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -3591,6 +3695,41 @@ again: /*****************************************************************************/ +static gboolean +_kf_db_prune_predicate(const char *uuid, gpointer user_data) +{ + return !!nm_settings_get_connection_by_uuid(user_data, uuid); +} + +static void +_kf_db_to_file(NMSettings *self, gboolean is_timestamps, gboolean force_write) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self); + NMKeyFileDB * kf_db; + bool * p_kf_db_pruned; + + if (is_timestamps) { + kf_db = priv->kf_db_timestamps; + p_kf_db_pruned = &priv->kf_db_pruned_timestamps; + } else { + kf_db = priv->kf_db_seen_bssids; + p_kf_db_pruned = &priv->kf_db_pruned_seen_bssid; + } + + if (!*p_kf_db_pruned) { + /* we only prune the DB once, because afterwards every + * add/remove of an connection will lead to a direct update. */ + *p_kf_db_pruned = TRUE; + nm_key_file_db_prune(kf_db, _kf_db_prune_predicate, self); + + /* once we also go over the directory, and see whether we + * have any left over temporary files to delete. */ + nm_key_file_db_prune_tmp_files(kf_db); + } + + nm_key_file_db_to_file(kf_db, force_write); +} + G_GNUC_PRINTF(4, 5) static void _kf_db_log_fcn(NMKeyFileDB *kf_db, int syslog_level, gpointer user_data, const char *fmt, ...) @@ -3639,7 +3778,7 @@ _kf_db_got_dirty_flush(NMSettings *self, gboolean is_timestamps) } if (nm_key_file_db_is_dirty(kf_db)) - nm_key_file_db_to_file(kf_db, FALSE); + _kf_db_to_file(self, is_timestamps, FALSE); else { _LOGT("[%s-keyfile]: skip saving changes to \"%s\"", prefix, @@ -3692,15 +3831,10 @@ _kf_db_got_dirty_fcn(NMKeyFileDB *kf_db, gpointer user_data) void nm_settings_kf_db_write(NMSettings *self) { - NMSettingsPrivate *priv; - g_return_if_fail(NM_IS_SETTINGS(self)); - priv = NM_SETTINGS_GET_PRIVATE(self); - if (priv->kf_db_timestamps) - nm_key_file_db_to_file(priv->kf_db_timestamps, TRUE); - if (priv->kf_db_seen_bssids) - nm_key_file_db_to_file(priv->kf_db_seen_bssids, TRUE); + _kf_db_to_file(self, TRUE, TRUE); + _kf_db_to_file(self, FALSE, TRUE); } /*****************************************************************************/ @@ -3938,8 +4072,8 @@ finalize(GObject *object) nm_clear_g_source(&priv->kf_db_flush_idle_id_timestamps); nm_clear_g_source(&priv->kf_db_flush_idle_id_seen_bssids); - nm_key_file_db_to_file(priv->kf_db_timestamps, FALSE); - nm_key_file_db_to_file(priv->kf_db_seen_bssids, FALSE); + _kf_db_to_file(self, TRUE, FALSE); + _kf_db_to_file(self, FALSE, FALSE); nm_key_file_db_destroy(priv->kf_db_timestamps); nm_key_file_db_destroy(priv->kf_db_seen_bssids); @@ -4027,18 +4161,16 @@ static const NMDBusInterfaceInfoExtended interface_info_settings = { .in_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("hostname", "s"), ), ), .handle = impl_settings_save_hostname, ), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_new_connection, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_new_connection, &signal_info_connection_removed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Connections", - "ao", - NM_SETTINGS_CONNECTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Hostname", "s", NM_SETTINGS_HOSTNAME), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("CanModify", - "b", - NM_SETTINGS_CAN_MODIFY), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Connections", + "ao", + NM_SETTINGS_CONNECTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Hostname", "s", NM_SETTINGS_HOSTNAME), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("CanModify", + "b", + NM_SETTINGS_CAN_MODIFY), ), ), }; static void diff --git a/src/core/settings/nm-settings.h b/src/core/settings/nm-settings.h index 09a0af57..ce18fecc 100644 --- a/src/core/settings/nm-settings.h +++ b/src/core/settings/nm-settings.h @@ -79,6 +79,9 @@ void nm_settings_add_connection_dbus(NMSettings * self, NMSettingsConnection *const *nm_settings_get_connections(NMSettings *settings, guint *out_len); +NMSettingsConnection *const * +nm_settings_get_connections_sorted_by_autoconnect_priority(NMSettings *self, guint *out_len); + NMSettingsConnection **nm_settings_get_connections_clone(NMSettings * self, guint * out_len, NMSettingsConnectionFilterFunc func, @@ -127,4 +130,6 @@ const char *nm_settings_get_startup_complete_blocked_reason(NMSettings *self, void nm_settings_kf_db_write(NMSettings *settings); +void _nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(NMSettings *self); + #endif /* __NM_SETTINGS_H__ */ diff --git a/src/core/settings/plugins/ifcfg-rh/meson.build b/src/core/settings/plugins/ifcfg-rh/meson.build index a2f11a92..c62fa89d 100644 --- a/src/core/settings/plugins/ifcfg-rh/meson.build +++ b/src/core/settings/plugins/ifcfg-rh/meson.build @@ -28,7 +28,6 @@ libnms_ifcfg_rh_core = static_library( 'shvar.c', ), dependencies: core_default_dep, - c_args: daemon_c_flags, ) libnm_settings_plugin_ifcfg_rh = shared_module( @@ -38,7 +37,6 @@ libnm_settings_plugin_ifcfg_rh = shared_module( 'nms-ifcfg-rh-plugin.c', ), dependencies: core_plugin_dep, - c_args: daemon_c_flags, link_with: libnms_ifcfg_rh_core, link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, diff --git a/src/core/settings/plugins/ifcfg-rh/nm-ifdown b/src/core/settings/plugins/ifcfg-rh/nm-ifdown old mode 100644 new mode 100755 index e7bd73ae..3b05ef1c --- a/src/core/settings/plugins/ifcfg-rh/nm-ifdown +++ b/src/core/settings/plugins/ifcfg-rh/nm-ifdown @@ -1,3 +1,44 @@ -#!/bin/sh -nmcli connection load "/etc/sysconfig/network-scripts/ifcfg-$1" && -exec nmcli connection down filename "/etc/sysconfig/network-scripts/ifcfg-$1" +#!/bin/bash + +CONFIG="$1" + +if [ -z "${CONFIG}" ] ; then + echo $"Usage: ifdown " >&2 + exit 1 +fi + +usage_and_fail() { + cat <&2 +$1! + +See all profiles with \`nmcli connection\`. +Reload files from disk with \`nmcli connection reload\` +Deactivate the desired profile with \`nmcli connection down \"\$NAME\"\` +EOF + exit 1 +} + +OLD_IFS="$IFS" + +re='^/etc/sysconfig/network-scripts/ifcfg-[^/]+$' +for f in "/etc/sysconfig/network-scripts/ifcfg-$CONFIG" "/etc/sysconfig/network-scripts/$CONFIG" ; do + [[ "$f" =~ $re ]] || continue + [ -f "$f" ] || continue + + nmcli connection load "$f" \ + && nmcli connection down filename "$f" \ + && exit 0 + + usage_and_fail "Failure to deactivate file \"$CONFIG\"" +done + +IFS=$'\n ' +APATHS=( $(nmcli -g GENERAL.DBUS-PATH connection show --active "$CONFIG" 2>/dev/null) ) +IFS="$OLD_IFS" +if [ "${#APATHS[@]}" -eq 1 ] ; then + nmcli connection down apath "${APATHS[0]}" \ + && exit 0 + usage_and_fail "Failure to deactivate profile \"$CONFIG\" (apath ${APATHS[@]})" +fi + +usage_and_fail "No suitable profile \"$CONFIG\" found" diff --git a/src/core/settings/plugins/ifcfg-rh/nm-ifup b/src/core/settings/plugins/ifcfg-rh/nm-ifup old mode 100644 new mode 100755 index 96637a92..6b32fe1b --- a/src/core/settings/plugins/ifcfg-rh/nm-ifup +++ b/src/core/settings/plugins/ifcfg-rh/nm-ifup @@ -1,3 +1,44 @@ -#!/bin/sh -nmcli connection load "/etc/sysconfig/network-scripts/ifcfg-$1" && -exec nmcli connection up filename "/etc/sysconfig/network-scripts/ifcfg-$1" +#!/bin/bash + +CONFIG="$1" + +if [ -z "${CONFIG}" ] ; then + echo $"Usage: ifup " >&2 + exit 1 +fi + +usage_and_fail() { + cat <&2 +$1! + +See all profiles with \`nmcli connection\`. +Reload files from disk with \`nmcli connection reload\` +Activate the desired profile with \`nmcli connection up \"\$NAME\"\` +EOF + exit 1 +} + +OLD_IFS="$IFS" + +re='^/etc/sysconfig/network-scripts/ifcfg-[^/]+$' +for f in "/etc/sysconfig/network-scripts/ifcfg-$CONFIG" "/etc/sysconfig/network-scripts/$CONFIG" ; do + [[ "$f" =~ $re ]] || continue + [ -f "$f" ] || continue + + nmcli connection load "$f" \ + && nmcli connection up filename "$f" \ + && exit 0 + + usage_and_fail "Failure to activate file \"$CONFIG\"" +done + +IFS=$'\n ' +UUIDS=( $(nmcli -g connection.uuid connection show "$CONFIG" 2>/dev/null) ) +IFS="$OLD_IFS" +if [ "${#UUIDS[@]}" -eq 1 ] ; then + nmcli connection up uuid "${UUIDS[0]}" \ + && exit 0 + usage_and_fail "Failure to activate profile \"$CONFIG\" (uuid ${UUIDS[0]})" +fi + +usage_and_fail "No suitable profile \"$CONFIG\" found" diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index d114db0f..5038ac6a 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -13,12 +13,12 @@ #include #include -#include "nm-std-aux/c-list-util.h" -#include "nm-glib-aux/nm-c-list.h" -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-std-aux/c-list-util.h" +#include "libnm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-io-utils.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-config.h" #include "nm-dbus-manager.h" #include "settings/nm-settings-plugin.h" 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 a42c4188..03b347f9 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 @@ -18,7 +18,8 @@ #include #include -#include "nm-glib-aux/nm-secret-utils.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-secret-utils.h" #include "nm-connection.h" #include "nm-dbus-interface.h" #include "nm-setting-connection.h" @@ -38,11 +39,11 @@ #include "nm-setting-user.h" #include "nm-setting-proxy.h" #include "nm-setting-generic.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-utils.h" -#include "nm-base/nm-ethtool-base.h" +#include "libnm-base/nm-ethtool-base.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "NetworkManagerUtils.h" #include "nms-ifcfg-rh-common.h" @@ -405,11 +406,9 @@ make_connection_setting(const char *file, /* Try for a UUID key before falling back to hashing the file name */ uuid = svGetValueStr(ifcfg, "UUID", &uuid_free); if (!uuid) { - uuid_free = nm_utils_uuid_generate_from_string(svFileGetName(ifcfg), - -1, - NM_UTILS_UUID_TYPE_LEGACY, - NULL); - uuid = uuid_free; + uuid_free = + nm_uuid_generate_from_string_str(svFileGetName(ifcfg), -1, NM_UUID_TYPE_LEGACY, NULL); + uuid = uuid_free; } g_object_set(s_con, @@ -1896,6 +1895,8 @@ make_ip4_setting(shvarFile *ifcfg, svGetValueBoolean(ifcfg, "DHCP_SEND_HOSTNAME", TRUE), NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, (int) svGetValueInt64(ifcfg, "IPV4_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0), + NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, + (int) svGetValueInt64(ifcfg, "IPV4_REQUIRED_TIMEOUT", 10, 0, G_MAXINT32, -1), NULL); nm_clear_g_free(&value); @@ -1986,7 +1987,11 @@ make_ip4_setting(shvarFile *ifcfg, } else if (nm_utils_ipaddr_is_valid(AF_INET6, v)) { /* Ignore IPv6 addresses */ } else { - PARSE_WARNING("invalid DNS server address %s", v); + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid DNS server address '%s'", + v); return NULL; } } @@ -2153,6 +2158,8 @@ read_aliases(NMSettingIPConfig *s_ip4, gboolean read_defroute, const char *filen continue; } + svWarnInvalid(parsed, "alias", _NMLOG_DOMAIN); + device = svGetValueStr(parsed, "DEVICE", &device_value); if (!device) { PARSE_WARNING("alias file '%s' has no DEVICE", full_path); @@ -2404,6 +2411,8 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea svGetValueBoolean(ifcfg, "DHCPV6_SEND_HOSTNAME", TRUE), NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, (int) svGetValueInt64(ifcfg, "IPV6_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0), + NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, + (int) svGetValueInt64(ifcfg, "IPV6_REQUIRED_TIMEOUT", 10, 0, G_MAXINT32, -1), NM_SETTING_IP6_CONFIG_RA_TIMEOUT, (int) svGetValueInt64(ifcfg, "IPV6_RA_TIMEOUT", 10, 0, G_MAXINT32, 0), NULL); @@ -2505,7 +2514,11 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea } else if (nm_utils_ipaddr_is_valid(AF_INET, v)) { /* Ignore IPv4 addresses */ } else { - PARSE_WARNING("invalid DNS server address %s", v); + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid DNS server address '%s'", + v); return NULL; } } @@ -4303,7 +4316,7 @@ make_wireless_setting(shvarFile *ifcfg, GError **error) bytes = g_bytes_new(value, value_len); ssid_len = g_bytes_get_size(bytes); - if (ssid_len > 32 || ssid_len == 0) { + if (ssid_len == 0 || ssid_len > NM_IW_ESSID_MAX_SIZE) { g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -4679,7 +4692,9 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"--coalesce", NM_ETHTOOL_TYPE_COALESCE}, {"--features", NM_ETHTOOL_TYPE_FEATURE}, {"--offload", NM_ETHTOOL_TYPE_FEATURE}, + {"--pause", NM_ETHTOOL_TYPE_PAUSE}, {"--set-ring", NM_ETHTOOL_TYPE_RING}, + {"-A", NM_ETHTOOL_TYPE_PAUSE}, {"-C", NM_ETHTOOL_TYPE_COALESCE}, {"-G", NM_ETHTOOL_TYPE_RING}, {"-K", NM_ETHTOOL_TYPE_FEATURE}, ); @@ -4719,7 +4734,7 @@ parse_ethtool_option(const char * value, w_iter = &words[2]; while (w_iter && *w_iter) { - if (ethtool_type == NM_ETHTOOL_TYPE_FEATURE) { + if (NM_IN_SET(ethtool_type, NM_ETHTOOL_TYPE_FEATURE, NM_ETHTOOL_TYPE_PAUSE)) { w_iter = _next_ethtool_options_nmternary(w_iter, ethtool_type, &ifcfg_option); if (ifcfg_option.has_value) { @@ -5022,6 +5037,7 @@ make_wired_setting(shvarFile *ifcfg, const char *file, NMSetting8021x **s_8021x, const char * cvalue; gs_free char * value = NULL; gboolean found = FALSE; + NMTernary accept_all_mac_addresses; s_wired = NM_SETTING_WIRED(nm_setting_wired_new()); @@ -5119,15 +5135,15 @@ make_wired_setting(shvarFile *ifcfg, const char *file, NMSetting8021x **s_8021x, for (i = 0; options && options[i]; i++) { const char *line = options[i]; const char *equals; - gboolean valid = FALSE; equals = strchr(line, '='); - if (equals) { - ((char *) equals)[0] = '\0'; - valid = nm_setting_wired_add_s390_option(s_wired, line, equals + 1); - } - if (!valid) - PARSE_WARNING("invalid s390 OPTION '%s'", line); + if (!equals) + continue; + + /* Here we don't verify the key/value further. If the file contains invalid keys, + * we will later reject the connection as invalid. */ + ((char *) equals)[0] = '\0'; + nm_setting_wired_add_s390_option(s_wired, line, equals + 1); } found = TRUE; } @@ -5180,6 +5196,15 @@ make_wired_setting(shvarFile *ifcfg, const char *file, NMSetting8021x **s_8021x, } nm_clear_g_free(&value); + accept_all_mac_addresses = svGetValueTernary(ifcfg, "ACCEPT_ALL_MAC_ADDRESSES"); + if (accept_all_mac_addresses != NM_TERNARY_DEFAULT) { + g_object_set(s_wired, + NM_SETTING_WIRED_ACCEPT_ALL_MAC_ADDRESSES, + accept_all_mac_addresses, + NULL); + found = TRUE; + } + if (!found) { g_set_error(error, NM_UTILS_ERROR, @@ -6072,15 +6097,14 @@ make_vlan_setting(shvarFile *ifcfg, const char *file, GError **error) v = iface_name + 4; } - if (v) { - int device_vlan_id; - - /* Grab VLAN ID from interface name; this takes precedence over the - * separate VLAN_ID property for backwards compat. + if (vlan_id == -1 && v) { + /* Grab VLAN ID from interface name; The explicit VLAN_ID option takes precedence + * over detecting the ID based on PHYSDEV. + * + * Note that older versions of NetworkManager had a bug and this would overwrite the + * VLAN_ID in this case. */ - device_vlan_id = _nm_utils_ascii_str_to_int64(v, 10, 0, 4095, -1); - if (device_vlan_id != -1) - vlan_id = device_vlan_id; + vlan_id = _nm_utils_ascii_str_to_int64(v, 10, 0, 4095, -1); } } @@ -6288,6 +6312,7 @@ connection_from_file_full(const char *filename, NMSetting * s_ip4; NMSetting * s_ip6; const char * ifcfg_name = NULL; + gs_free char * s_tmp = NULL; gboolean has_ip4_defroute = FALSE; gboolean has_complex_routes_v4; gboolean has_complex_routes_v6; @@ -6315,8 +6340,6 @@ connection_from_file_full(const char *filename, if (!main_ifcfg) return NULL; - network_ifcfg = svOpenFile(network_file, NULL); - if (!svGetValueBoolean(main_ifcfg, "NM_CONTROLLED", TRUE)) { connection = create_unhandled_connection(filename, main_ifcfg, "unmanaged", out_unhandled); if (!connection) { @@ -6330,6 +6353,16 @@ connection_from_file_full(const char *filename, return g_steal_pointer(&connection); } + if (NM_IN_STRSET(svGetValueStr(main_ifcfg, "DEVICE", &s_tmp), "lo")) { + /* "lo" is not handled by NetworkManager and we ignore it. */ + } else + svWarnInvalid(main_ifcfg, "ifcfg", _NMLOG_DOMAIN); + nm_clear_g_free(&s_tmp); + + network_ifcfg = svOpenFile(network_file, NULL); + /* we don't call svWarnInvalid(network_ifcfg), because we will load this file for + * every profile. So we would get a large number of duplicate warnings. */ + /* iBFT is handled by nm-initrd-generator during boot. */ bootproto = svGetValueStr_cp(main_ifcfg, "BOOTPROTO"); if (bootproto && !g_ascii_strcasecmp(bootproto, "ibft")) { diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c index 3f674dea..134bdf68 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c @@ -7,8 +7,9 @@ #include "nms-ifcfg-rh-storage.h" +#include "libnm-glib-aux/nm-uuid.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-connection.h" #include "nms-ifcfg-rh-plugin.h" @@ -88,7 +89,7 @@ static NMSIfcfgRHStorage * _storage_new(NMSIfcfgRHPlugin *plugin, const char *uuid, const char *filename) { nm_assert(NMS_IS_IFCFG_RH_PLUGIN(plugin)); - nm_assert(!uuid || nm_utils_is_uuid(uuid)); + nm_assert(!uuid || nm_uuid_is_normalized(uuid)); nm_assert(filename && filename[0] == '/'); return g_object_new(NMS_TYPE_IFCFG_RH_STORAGE, diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index ada1942a..febfc120 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -9,7 +9,7 @@ #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nms-ifcfg-rh-common.h" @@ -593,6 +593,9 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), + ETHT_NAME(NM_ETHTOOL_ID_PAUSE_AUTONEG, "pause-autoneg"), + ETHT_NAME(NM_ETHTOOL_ID_PAUSE_RX, "pause-rx"), + ETHT_NAME(NM_ETHTOOL_ID_PAUSE_TX, "pause-tx"), ETHT_NAME(NM_ETHTOOL_ID_RING_RX, "rx"), ETHT_NAME(NM_ETHTOOL_ID_RING_RX_JUMBO, "rx-jumbo"), ETHT_NAME(NM_ETHTOOL_ID_RING_RX_MINI, "rx-mini"), @@ -722,6 +725,15 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"rx-mini", NM_ETHTOOL_ID_RING_RX_MINI}, {"tx", NM_ETHTOOL_ID_RING_TX}, ); +static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + _get_ethtoolid_pause_by_name, + NMEthtoolID, + { nm_assert(name); }, + { return NM_ETHTOOL_ID_UNKNOWN; }, + {"pause-autoneg", NM_ETHTOOL_ID_PAUSE_AUTONEG}, + {"pause-rx", NM_ETHTOOL_ID_PAUSE_RX}, + {"pause-tx", NM_ETHTOOL_ID_PAUSE_TX}, ); + const NMEthtoolData * nms_ifcfg_rh_utils_get_ethtool_by_name(const char *name, NMEthtoolType ethtool_type) { @@ -737,6 +749,9 @@ nms_ifcfg_rh_utils_get_ethtool_by_name(const char *name, NMEthtoolType ethtool_t case NM_ETHTOOL_TYPE_RING: id = _get_ethtoolid_ring_by_name(name); break; + case NM_ETHTOOL_TYPE_PAUSE: + id = _get_ethtoolid_pause_by_name(name); + break; default: nm_assert_not_reached(); return NULL; @@ -800,6 +815,7 @@ nms_ifcfg_rh_utils_is_numbered_tag_impl(const char *key, } const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { + _KEY_TYPE("ACCEPT_ALL_MAC_ADDRESSES", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("ACD_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("ADDRESS", NMS_IFCFG_KEY_TYPE_IS_NUMBERED), _KEY_TYPE("AP_ISOLATION", NMS_IFCFG_KEY_TYPE_IS_PLAIN), @@ -942,6 +958,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("IPV4_DHCP_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV4_DNS_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV4_FAILURE_FATAL", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("IPV4_REQUIRED_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV4_ROUTE_METRIC", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV4_ROUTE_TABLE", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV6ADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN), @@ -964,6 +981,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("IPV6_PRIVACY", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV6_PRIVACY_PREFER_PUBLIC_IP", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV6_RA_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("IPV6_REQUIRED_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV6_RES_OPTIONS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV6_ROUTE_METRIC", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IPV6_ROUTE_TABLE", NMS_IFCFG_KEY_TYPE_IS_PLAIN), diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 04a1b63d..b7751ec9 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -7,7 +7,7 @@ #define _UTILS_H_ #include "nm-connection.h" -#include "nm-base/nm-ethtool-base.h" +#include "libnm-base/nm-ethtool-base.h" #include "shvar.h" @@ -33,7 +33,7 @@ typedef struct { NMSIfcfgKeyTypeFlags key_flags; } NMSIfcfgKeyTypeInfo; -extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[248]; +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[251]; const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); 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 45b76456..ef85b6bf 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 @@ -15,8 +15,9 @@ #include #include -#include "nm-glib-aux/nm-enum-utils.h" -#include "nm-glib-aux/nm-io-utils.h" +#include "libnm-glib-aux/nm-enum-utils.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-glib-aux/nm-io-utils.h" #include "nm-manager.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" @@ -32,9 +33,9 @@ #include "nm-setting-team.h" #include "nm-setting-team-port.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" -#include "nm-base/nm-ethtool-base.h" +#include "libnm-base/nm-ethtool-base.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" @@ -203,18 +204,18 @@ write_object(NMSetting8021x * s_8021x, g_return_val_if_fail(ifcfg != NULL, FALSE); g_return_val_if_fail(objtype != NULL, FALSE); - scheme = (*(objtype->vtable->scheme_func))(s_8021x); + scheme = (*(objtype->vtable->scheme_func)) (s_8021x); switch (scheme) { case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: break; case NM_SETTING_802_1X_CK_SCHEME_BLOB: - blob = (*(objtype->vtable->blob_func))(s_8021x); + blob = (*(objtype->vtable->blob_func)) (s_8021x); break; case NM_SETTING_802_1X_CK_SCHEME_PATH: - value = (*(objtype->vtable->path_func))(s_8021x); + value = (*(objtype->vtable->path_func)) (s_8021x); break; case NM_SETTING_802_1X_CK_SCHEME_PKCS11: - value = (*(objtype->vtable->uri_func))(s_8021x); + value = (*(objtype->vtable->uri_func)) (s_8021x); break; default: g_set_error(error, @@ -227,8 +228,8 @@ write_object(NMSetting8021x * s_8021x, /* Set the password for certificate/private key. */ nm_sprintf_buf(secret_name, "%s_PASSWORD", objtype->ifcfg_rh_key); nm_sprintf_buf(secret_flags, "%s_PASSWORD_FLAGS", objtype->ifcfg_rh_key); - password = (*(objtype->vtable->passwd_func))(s_8021x); - flags = (*(objtype->vtable->pwflag_func))(s_8021x); + password = (*(objtype->vtable->passwd_func)) (s_8021x); + flags = (*(objtype->vtable->pwflag_func)) (s_8021x); set_secret(ifcfg, secrets, secret_name, password, secret_flags, flags); if (!objtype->vtable->format_func) @@ -299,6 +300,7 @@ write_blobs(GHashTable *blobs, GError **error) g_bytes_get_size(blob), 0600, NULL, + NULL, &write_error)) { g_set_error(error, NM_SETTINGS_ERROR, @@ -862,7 +864,7 @@ write_wireless_setting(NMConnection *connection, return FALSE; } ssid_data = g_bytes_get_data(ssid, &ssid_len); - if (!ssid_len || ssid_len > 32) { + if (ssid_len == 0 || ssid_len > NM_IW_ESSID_MAX_SIZE) { g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -903,9 +905,9 @@ write_wireless_setting(NMConnection *connection, svSetValueStr(ifcfg, "ESSID", str->str); g_string_free(str, TRUE); } else { - char buf[33]; + char buf[NM_IW_ESSID_MAX_SIZE + 1]; - nm_assert(ssid_len <= 32); + nm_assert(ssid_len <= NM_IW_ESSID_MAX_SIZE); memcpy(buf, ssid_data, ssid_len); buf[ssid_len] = '\0'; svSetValueStr(ifcfg, "ESSID", buf); @@ -1075,25 +1077,18 @@ write_hostname_setting(NMConnection *connection, shvarFile *ifcfg) svSetValueInt64_cond(ifcfg, "HOSTNAME_ONLY_FROM_DEFAULT", t != NM_TERNARY_DEFAULT, t); } -static gboolean -write_wired_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) +static void +write_wired_setting_impl(NMSettingWired *s_wired, shvarFile *ifcfg, gboolean is_virtual) { - NMSettingWired * s_wired; const char *const *s390_subchannels; - guint32 mtu, num_opts, i; + guint32 mtu; + guint32 num_opts; + guint32 i; const char *const *macaddr_blacklist; - s_wired = nm_connection_get_setting_wired(connection); - if (!s_wired) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_FAILED, - "Missing '%s' setting", - NM_SETTING_WIRED_SETTING_NAME); - return FALSE; - } - - svSetValueStr(ifcfg, "HWADDR", nm_setting_wired_get_mac_address(s_wired)); + svSetValue(ifcfg, + "HWADDR", + nm_setting_wired_get_mac_address(s_wired) ?: (is_virtual ? "" : NULL)); svSetValueStr(ifcfg, "MACADDR", nm_setting_wired_get_cloned_mac_address(s_wired)); @@ -1167,8 +1162,42 @@ write_wired_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) svSetValueStr(ifcfg, "OPTIONS", tmp->str); } + svSetValueTernary(ifcfg, + "ACCEPT_ALL_MAC_ADDRESSES", + nm_setting_wired_get_accept_all_mac_addresses(s_wired)); +} + +static gboolean +write_wired_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingWired *s_wired; + + s_wired = nm_connection_get_setting_wired(connection); + if (!s_wired) { + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "Missing '%s' setting", + NM_SETTING_WIRED_SETTING_NAME); + return FALSE; + } + svSetValueStr(ifcfg, "TYPE", TYPE_ETHERNET); + write_wired_setting_impl(s_wired, ifcfg, FALSE); + return TRUE; +} + +static gboolean +write_wired_for_virtual(NMConnection *connection, shvarFile *ifcfg) +{ + NMSettingWired *s_wired; + + s_wired = nm_connection_get_setting_wired(connection); + if (!s_wired) + return FALSE; + + write_wired_setting_impl(s_wired, ifcfg, TRUE); return TRUE; } @@ -1334,6 +1363,26 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error g_string_append(str, nms_ifcfg_rh_utils_get_ethtool_name(ethtool_id)); g_string_append_printf(str, " %" G_GUINT32_FORMAT, u32); } + 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)); + if (!nm_setting_option_get_boolean(NM_SETTING(s_ethtool), + nm_ethtool_data[ethtool_id]->optname, + &b)) + continue; + + _ethtool_gstring_prepare(&str, &is_first, 'A', iface); + 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"); + } + + if (!str) { + /* 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. */ + _ethtool_gstring_prepare(&str, &is_first, 'A', iface); + } } if (str) { @@ -1366,35 +1415,6 @@ vlan_priority_maplist_to_stringlist(NMSettingVlan *s_vlan, NMVlanPriorityMap map return value; } -static gboolean -write_wired_for_virtual(NMConnection *connection, shvarFile *ifcfg) -{ - NMSettingWired *s_wired; - gboolean has_wired = FALSE; - - s_wired = nm_connection_get_setting_wired(connection); - if (s_wired) { - const char *device_mac, *cloned_mac; - guint32 mtu; - - has_wired = TRUE; - - device_mac = nm_setting_wired_get_mac_address(s_wired); - svSetValue(ifcfg, "HWADDR", device_mac ?: ""); - - cloned_mac = nm_setting_wired_get_cloned_mac_address(s_wired); - svSetValueStr(ifcfg, "MACADDR", cloned_mac); - - svSetValueStr(ifcfg, - "GENERATE_MAC_ADDRESS_MASK", - nm_setting_wired_get_generate_mac_address_mask(s_wired)); - - mtu = nm_setting_wired_get_mtu(s_wired); - svSetValueInt64_cond(ifcfg, "MTU", mtu != 0, mtu); - } - return has_wired; -} - static gboolean write_vlan_setting(NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error) { @@ -1542,36 +1562,40 @@ write_team_setting(NMConnection *connection, shvarFile *ifcfg, gboolean *wired, static gboolean write_bridge_vlans(NMSetting * setting, - const char *property_name, + gboolean is_port, shvarFile * ifcfg, const char *key, GError ** error) { - gs_unref_ptrarray GPtrArray *vlans = NULL; - NMBridgeVlan * vlan; - GString * string; - guint i; + GPtrArray * vlans; + NMBridgeVlan * vlan; + nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(0, FALSE); + guint i; - g_object_get(setting, property_name, &vlans, NULL); + if (is_port) + vlans = _nm_setting_bridge_port_get_vlans(NM_SETTING_BRIDGE_PORT(setting)); + else + vlans = _nm_setting_bridge_get_vlans(NM_SETTING_BRIDGE(setting)); if (!vlans || !vlans->len) return TRUE; - string = g_string_new(""); for (i = 0; i < vlans->len; i++) { gs_free char *vlan_str = NULL; vlan = vlans->pdata[i]; vlan_str = nm_bridge_vlan_to_str(vlan, error); - if (!vlan_str) - return FALSE; - if (string->len > 0) - g_string_append(string, ","); - nm_utils_escaped_tokens_escape_gstr_assert(vlan_str, ",", string); + if (!vlan_str) { + /* nm_bridge_vlan_to_str() cannot fail (for now). */ + nm_assert_not_reached(); + continue; + } + if (strbuf.len > 0) + nm_str_buf_append_c(&strbuf, ','); + nm_str_buf_append(&strbuf, nm_utils_escaped_tokens_escape_unnecessary(vlan_str, ",")); } - svSetValueStr(ifcfg, key, string->str); - g_string_free(string, TRUE); + svSetValueStr(ifcfg, key, nm_str_buf_get_str(&strbuf)); return TRUE; } @@ -1807,11 +1831,7 @@ write_bridge_setting(NMConnection *connection, shvarFile *ifcfg, gboolean *wired svSetValueStr(ifcfg, "BRIDGING_OPTS", opts->str); g_string_free(opts, TRUE); - if (!write_bridge_vlans((NMSetting *) s_bridge, - NM_SETTING_BRIDGE_VLANS, - ifcfg, - "BRIDGE_VLANS", - error)) + if (!write_bridge_vlans((NMSetting *) s_bridge, FALSE, ifcfg, "BRIDGE_VLANS", error)) return FALSE; svSetValueStr(ifcfg, "TYPE", TYPE_BRIDGE); @@ -1862,11 +1882,7 @@ write_bridge_port_setting(NMConnection *connection, shvarFile *ifcfg, GError **e svSetValueStr(ifcfg, "BRIDGING_OPTS", string->str); g_string_free(string, TRUE); - if (!write_bridge_vlans((NMSetting *) s_port, - NM_SETTING_BRIDGE_PORT_VLANS, - ifcfg, - "BRIDGE_PORT_VLANS", - error)) + if (!write_bridge_vlans((NMSetting *) s_port, TRUE, ifcfg, "BRIDGE_PORT_VLANS", error)) return FALSE; return TRUE; @@ -2824,6 +2840,9 @@ write_ip4_setting(NMConnection *connection, timeout = nm_setting_ip_config_get_dhcp_timeout(s_ip4); svSetValueInt64_cond(ifcfg, "IPV4_DHCP_TIMEOUT", timeout != 0, timeout); + timeout = nm_setting_ip_config_get_required_timeout(s_ip4); + svSetValueInt64_cond(ifcfg, "IPV4_REQUIRED_TIMEOUT", timeout != -1, timeout); + svSetValueBoolean(ifcfg, "IPV4_FAILURE_FATAL", !nm_setting_ip_config_get_may_fail(s_ip4)); route_metric = nm_setting_ip_config_get_route_metric(s_ip4); @@ -3021,6 +3040,9 @@ write_ip6_setting(NMConnection *connection, timeout = nm_setting_ip_config_get_dhcp_timeout(s_ip6); svSetValueInt64_cond(ifcfg, "IPV6_DHCP_TIMEOUT", timeout != 0, timeout); + timeout = nm_setting_ip_config_get_required_timeout(s_ip6); + svSetValueInt64_cond(ifcfg, "IPV6_REQUIRED_TIMEOUT", timeout != -1, timeout); + flags = nm_setting_ip_config_get_dhcp_hostname_flags(s_ip6); svSetValueInt64_cond(ifcfg, "DHCPV6_HOSTNAME_FLAGS", diff --git a/src/core/settings/plugins/ifcfg-rh/shvar.c b/src/core/settings/plugins/ifcfg-rh/shvar.c index 386bcac7..d82efb3c 100644 --- a/src/core/settings/plugins/ifcfg-rh/shvar.c +++ b/src/core/settings/plugins/ifcfg-rh/shvar.c @@ -14,10 +14,11 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" -#include "nm-glib-aux/nm-enum-utils.h" -#include "nm-glib-aux/nm-io-utils.h" +#include "libnm-glib-aux/nm-enum-utils.h" +#include "libnm-glib-aux/nm-io-utils.h" #include "c-list/src/c-list.h" #include "nms-ifcfg-rh-utils.h" @@ -152,17 +153,42 @@ _escape_ansic(const char *source) const char *p; char * dest; char * q; + gsize n_alloc; nm_assert(source); - p = (const char *) source; - /* Each source byte needs maximally four destination chars (\777) */ - q = dest = g_malloc(strlen(source) * 4 + 1 + 3); + n_alloc = 4; + for (p = source; p[0]; p++) { + switch (*p) { + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + case '\\': + case '"': + case '\'': + n_alloc += 2; + break; + default: + if (!nm_ascii_is_regular(*p)) + n_alloc += 4; + else + n_alloc += 1; + break; + } + } + + dest = g_malloc(n_alloc); + + q = dest; *q++ = '$'; *q++ = '\''; - while (*p) { + for (p = source; p[0]; p++) { + nm_assert(q < &dest[n_alloc]); switch (*p) { case '\b': *q++ = '\\'; @@ -195,7 +221,7 @@ _escape_ansic(const char *source) *q++ = *p; break; default: - if ((*p < ' ') || (*p >= 0177)) { + if (!nm_ascii_is_regular(*p)) { *q++ = '\\'; *q++ = '0' + (((*p) >> 6) & 07); *q++ = '0' + (((*p) >> 3) & 07); @@ -204,12 +230,11 @@ _escape_ansic(const char *source) *q++ = *p; break; } - p++; } *q++ = '\''; *q++ = '\0'; - nm_assert(q - dest <= strlen(source) * 4 + 1 + 3); + nm_assert(q - dest == n_alloc); return dest; } @@ -217,7 +242,7 @@ _escape_ansic(const char *source) /*****************************************************************************/ #define _char_req_escape(ch) NM_IN_SET(ch, '"', '\\', '$', '`') -#define _char_req_escape_old(ch) NM_IN_SET(ch, '"', '\\', '\'', '$', '`', '~') +#define _char_req_escape_old(ch) NM_IN_SET(ch, '"', '\\', '$', '`', '\'', '~') #define _char_req_quotes(ch) NM_IN_SET(ch, ' ', '\'', '~', '\t', '|', '&', ';', '(', ')', '<', '>') const char * @@ -226,29 +251,48 @@ svEscape(const char *s, char **to_free) char *new; gsize mangle = 0; gboolean requires_quotes = FALSE; - int newlen; - size_t i, j, slen; + gsize n_alloc; + gsize slen; + gsize i; + gsize j; + gboolean all_ascii = TRUE; for (slen = 0; s[slen]; slen++) { if (_char_req_escape(s[slen])) mangle++; else if (_char_req_quotes(s[slen])) requires_quotes = TRUE; - else if (s[slen] < ' ') { - /* if the string contains newline we can only express it using ANSI C quotation - * (as we don't support line continuation). - * Additionally, ANSI control characters look odd with regular quotation, so handle - * them too. */ - return (*to_free = _escape_ansic(s)); + else if (!nm_ascii_is_regular(s[slen])) { + if (nm_ascii_is_ctrl_or_del(s[slen])) { + /* if the string contains newline we can only express it using ANSI C quotation + * (as we don't support line continuation). + * Additionally, ANSI control characters look odd with regular quotation, so handle + * them too. */ + return (*to_free = _escape_ansic(s)); + } + all_ascii = FALSE; + requires_quotes = TRUE; } } + + if (!all_ascii && !g_utf8_validate(s, -1, NULL)) { + /* The string is not valid ASCII/UTF-8. We can escape that via + * _escape_ansic(), however the reader might have a problem to + * do something sensible with the blob later. + * + * This is really a bug of the caller, which should not present us with + * non-text in the first place. But at this place, we cannot handle the + * error better, so just escape it. */ + return (*to_free = _escape_ansic(s)); + } + if (!mangle && !requires_quotes) { *to_free = NULL; return s; } - newlen = slen + mangle + 3; /* 3 is extra ""\0 */ - new = g_malloc(newlen); + n_alloc = slen + mangle + 3; /* 3 is extra ""\0 */ + new = g_malloc(n_alloc); j = 0; new[j++] = '"'; @@ -260,7 +304,7 @@ svEscape(const char *s, char **to_free) new[j++] = '"'; new[j++] = '\0'; - nm_assert(j == slen + mangle + 3); + nm_assert(j == n_alloc); *to_free = new; return new; @@ -318,14 +362,14 @@ _ch_hex_get(char ch) } static void -_gstr_init(GString **str, const char *value, gsize i) +_strbuf_init(NMStrBuf *str, const char *value, gsize i) { nm_assert(str); nm_assert(value); - if (!(*str)) { - /* if @str is not yet initialized, it allocates - * a new GString and copies @i characters from + if (str->allocated == 0) { + /* if @str is not yet initialized, it initializes + * a new NMStrBuf and copies @i characters from * @value over. * * Unescaping usually does not extend the length of a string, @@ -335,20 +379,26 @@ _gstr_init(GString **str, const char *value, gsize i) * (FACTOR*strlen(value) + CONST), which is non trivial to get * right in all cases. Also, we would have to provision for the * very unlikely extreme case. - * Instead, use a GString buffer which can grow as needed. But for an + * Instead, use a NMStrBuf buffer which can grow as needed. But for an * initial guess, strlen(value) is a good start */ - *str = g_string_new_len(NULL, strlen(value) + 3); - if (i) - g_string_append_len(*str, value, i); + nm_str_buf_maybe_expand(str, strlen(value) + 3u, FALSE); + nm_str_buf_append_len(str, value, i); } } const char * svUnescape(const char *value, char **to_free) { - gsize i, j; - GString *str = NULL; + return svUnescape_full(value, to_free, TRUE); +} + +const char * +svUnescape_full(const char *value, char **to_free, gboolean check_utf8) +{ + NMStrBuf str = NM_STR_BUF_INIT(0, FALSE); int looks_like_old_svescaped = -1; + gsize i; + gsize j; /* we handle bash syntax here (note that ifup has #!/bin/bash. * Thus, see https://www.gnu.org/software/bash/manual/html_node/Quoting.html#Quoting */ @@ -395,20 +445,20 @@ svUnescape(const char *value, char **to_free) if (value[i] == '\\') { /* backslash escape */ - _gstr_init(&str, value, i); + _strbuf_init(&str, value, i); i++; if (G_UNLIKELY(value[i] == '\0')) { /* we don't support line continuation */ goto out_error; } - g_string_append_c(str, value[i]); + nm_str_buf_append_c(&str, value[i]); i++; goto loop1_next; } if (value[i] == '\'') { /* single quotes */ - _gstr_init(&str, value, i); + _strbuf_init(&str, value, i); i++; j = i; while (TRUE) { @@ -420,14 +470,14 @@ svUnescape(const char *value, char **to_free) break; j++; } - g_string_append_len(str, &value[i], j - i); + nm_str_buf_append_len(&str, &value[i], j - i); i = j + 1; goto loop1_next; } if (value[i] == '"') { /* double quotes */ - _gstr_init(&str, value, i); + _strbuf_init(&str, value, i); i++; while (TRUE) { if (value[i] == '"') { @@ -466,11 +516,11 @@ svUnescape(const char *value, char **to_free) if (looks_like_old_svescaped < 0) looks_like_old_svescaped = _looks_like_old_svescaped(value); if (!looks_like_old_svescaped) - g_string_append_c(str, '\\'); + nm_str_buf_append_c(&str, '\\'); } else - g_string_append_c(str, '\\'); + nm_str_buf_append_c(&str, '\\'); } - g_string_append_c(str, value[i]); + nm_str_buf_append_c(&str, value[i]); i++; } goto loop1_next; @@ -478,7 +528,7 @@ svUnescape(const char *value, char **to_free) if (value[i] == '$' && value[i + 1] == '\'') { /* ANSI-C Quoting */ - _gstr_init(&str, value, i); + _strbuf_init(&str, value, i); i += 2; while (TRUE) { char ch; @@ -552,7 +602,7 @@ svUnescape(const char *value, char **to_free) } } /* like bash, we cut too large numbers off. E.g. A=$'\772' becomes 0xfa */ - g_string_append_c(str, (guint8) v); + nm_str_buf_append_c(&str, (guint8) v); } else if (NM_IN_SET(value[i], 'x', 'u', 'U')) { const char escape_type = value[i]; int max_digits = escape_type == 'x' ? 2 : escape_type == 'u' ? 4 : 8; @@ -561,8 +611,7 @@ svUnescape(const char *value, char **to_free) i++; if (!_ch_hex_is(value[i])) { /* missing hex value after "\x" escape. This is treated like no escaping. */ - g_string_append_c(str, '\\'); - g_string_append_c(str, escape_type); + nm_str_buf_append_c(&str, '\\', escape_type); } else { v = _ch_hex_get(value[i]); i++; @@ -574,22 +623,21 @@ svUnescape(const char *value, char **to_free) i++; } if (escape_type == 'x') - g_string_append_c(str, v); + nm_str_buf_append_c(&str, v); else { /* we treat the unicode escapes as utf-8 encoded values. */ - g_string_append_unichar(str, v); + nm_str_buf_append_unichar(&str, v); } } } else { - g_string_append_c(str, '\\'); - g_string_append_c(str, value[i]); + nm_str_buf_append_c(&str, '\\', value[i]); i++; } goto loop_ansic_next; } } else ch = value[i]; - g_string_append_c(str, ch); + nm_str_buf_append_c(&str, ch); i++; loop_ansic_next:; } @@ -603,8 +651,8 @@ loop_ansic_next:; } /* an unquoted, regular character. Just consume it directly. */ - if (str) - g_string_append_c(str, value[i]); + if (str.allocated > 0) + nm_str_buf_append_c(&str, value[i]); i++; loop1_next:; @@ -614,22 +662,30 @@ loop1_next:; out_value: if (i == 0) { - nm_assert(!str); + nm_assert(str.allocated == 0); + nm_assert(!str._priv_str); *to_free = NULL; return ""; } - if (str) { - if (str->len == 0 || str->str[0] == '\0') { - g_string_free(str, TRUE); + if (str.allocated > 0) { + if (check_utf8 && !nm_str_buf_utf8_validate(&str)) + goto out_error; + if (str.len == 0 || nm_str_buf_get_str_unsafe(&str)[0] == '\0') { + nm_str_buf_destroy(&str); *to_free = NULL; return ""; } else { - *to_free = g_string_free(str, FALSE); + *to_free = nm_str_buf_finalize(&str, NULL); return *to_free; } } + if (check_utf8 && !g_utf8_validate(value, i, NULL)) { + *to_free = NULL; + return NULL; + } + if (value[i] != '\0') { *to_free = g_strndup(value, i); return *to_free; @@ -639,8 +695,7 @@ out_value: return value; out_error: - if (str) - g_string_free(str, TRUE); + nm_str_buf_destroy(&str); *to_free = NULL; return NULL; } @@ -1095,9 +1150,8 @@ _svGetValue(shvarFile *s, const char *key, char **to_free) if (line && line->line) { v = svUnescape(line->line, to_free); if (!v) { - /* a wrongly quoted value is treated like the empty string. - * See also svWriteFile(), which handles unparsable values - * that way. */ + /* a wrongly quoted value or non-UTF-8 is treated like the empty string. + * See also svWriteFile(), which handles unparsable values that way. */ nm_assert(!*to_free); return ""; } @@ -1470,6 +1524,91 @@ svUnsetValue(shvarFile *s, const char *key) /*****************************************************************************/ +void +svWarnInvalid(shvarFile *s, const char *file_type, NMLogDomain log_domain) +{ + shvarLine *line; + gsize n; + + if (!nm_logging_enabled(LOGL_WARN, log_domain)) + return; + + n = 0; + c_list_for_each_entry (line, &s->lst_head, lst) { + gs_free char *s_tmp = NULL; + + n++; + + if (!line->key) { + const char *str; + + nm_assert(line->line); + str = nm_str_skip_leading_spaces(line->line); + if (!NM_IN_SET(str[0], '\0', '#')) { + nm_log_warn(log_domain, + "ifcfg-rh: %s,%s:%zu: invalid line ignored", + file_type, + s->fileName, + n); + } + continue; + } + + if (g_hash_table_lookup(s->lst_idx, line) != line) { + nm_log_warn( + log_domain, + "ifcfg-rh: %s,%s:%zu: key %s is duplicated and the early occurrence ignored", + file_type, + s->fileName, + n, + line->key); + continue; + } + + if (!line->line) { + /* the line is deleted via svUnsetValue(). Ignore. */ + continue; + } + + if (!svUnescape(line->line, &s_tmp)) { + if (!svUnescape_full(line->line, &s_tmp, FALSE)) { + nm_log_warn(log_domain, + "ifcfg-rh: %s,%s:%zu: key %s is badly quoted and is treated as \"\"", + file_type, + s->fileName, + n, + line->key); + } else { + nm_log_warn(log_domain, + "ifcfg-rh: %s,%s:%zu: key %s does not contain valid UTF-8 and is " + "treated as \"\"", + file_type, + s->fileName, + n, + line->key); + } + continue; + } + + /* TODO: we read different shell scripts, and whether a key is recognized + * depends on the type. For example, alias files only accept a subset of + * known keys. + * + * Basically, depending on the @file_type, different keys are valid. */ + if (!nms_ifcfg_rh_utils_is_well_known_key(line->key)) { + nm_log_dbg(log_domain, + "ifcfg-rh: %s,%s:%zu: key %s is unknown and ignored", + file_type, + s->fileName, + n, + line->key); + continue; + } + } +} + +/*****************************************************************************/ + /* Write the current contents iff modified. Returns FALSE on error * and TRUE on success. Do not write if no values have been modified. * The mode argument is only used if creating the file, not if diff --git a/src/core/settings/plugins/ifcfg-rh/shvar.h b/src/core/settings/plugins/ifcfg-rh/shvar.h index 6965d873..cf91642f 100644 --- a/src/core/settings/plugins/ifcfg-rh/shvar.h +++ b/src/core/settings/plugins/ifcfg-rh/shvar.h @@ -107,6 +107,7 @@ void svCloseFile(shvarFile *s); const char *svEscape(const char *s, char **to_free); const char *svUnescape(const char *s, char **to_free); +const char *svUnescape_full(const char *value, char **to_free, gboolean check_utf8); static inline void _nm_auto_shvar_file_close(shvarFile **p_s) @@ -120,4 +121,6 @@ _nm_auto_shvar_file_close(shvarFile **p_s) } #define nm_auto_shvar_file_close nm_auto(_nm_auto_shvar_file_close) +void svWarnInvalid(shvarFile *s, const char *file_type, NMLogDomain log_domain); + #endif /* _SHVAR_H */ diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected index d81d9187..aebcd2b8 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected @@ -1,5 +1,5 @@ -HWADDR=00:22:15:59:62:97 TYPE=Ethernet +HWADDR=00:22:15:59:62:97 BRIDGING_OPTS="priority=28 hairpin_mode=1" NAME="System test-bridge-component" UUID=${UUID} diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected index 2e69c5e7..71d2cda8 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected @@ -1,5 +1,5 @@ -HWADDR=00:22:15:59:62:97 TYPE=Ethernet +HWADDR=00:22:15:59:62:97 NAME="System test-bridge-component" UUID=${UUID} DEVICE=eth0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected index 59a6f79b..240cd5c1 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected @@ -1,5 +1,5 @@ -HWADDR=00:11:22:33:44:EE TYPE=Ethernet +HWADDR=00:11:22:33:44:EE KEY_MGMT=IEEE8021X IEEE_8021X_EAP_METHODS=PEAP IEEE_8021X_IDENTITY="Jara Cimrman" diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected index a8ff8df3..d31d8ff5 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected @@ -1,6 +1,6 @@ +TYPE=Ethernet HWADDR=31:33:33:37:BE:CD MTU=1492 -TYPE=Ethernet BRIDGING_OPTS="priority=50 path_cost=33" BRIDGE_PORT_VLANS="1 untagged,2 pvid,4-4094 untagged" NAME="Test Write Bridge Component" diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected index cd8fc96f..cc29a2cc 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected @@ -1,6 +1,6 @@ +TYPE=Ethernet HWADDR=31:33:33:37:BE:CD MTU=1492 -TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected index a28c5c1c..8197f320 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected @@ -1,5 +1,5 @@ -HWADDR=00:16:41:11:22:33 TYPE=Ethernet +HWADDR=00:16:41:11:22:33 PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=dhcp diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use new file mode 100644 index 00000000..fc9c8a45 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use @@ -0,0 +1,4 @@ +VLAN=yes +TYPE=Vlan +DEVICE=eth0.9 +VLAN_ID=10 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected new file mode 100644 index 00000000..a7be14ce --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected @@ -0,0 +1,15 @@ +VLAN=yes +TYPE=Vlan +PHYSDEV=eth0 +VLAN_ID=10 +REORDER_HDR=yes +GVRP=no +MVRP=no +HWADDR= +PROXY_METHOD=none +BROWSER_ONLY=no +IPV6INIT=no +NAME="Vlan test-vlan-vlanid-use" +UUID=${UUID} +DEVICE=eth0.9 +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls index 9a74bb4d..a21c301c 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls @@ -3,7 +3,6 @@ DEVICE=eth2 HWADDR=00:16:41:11:22:33 BOOTPROTO=dhcp ONBOOT=yes -ONBOOT=yes USERCTL=yes IPV6INIT=no NM_CONTROLLED=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls index 42ed1d68..bb63d5e8 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls @@ -4,7 +4,6 @@ DEVICE=eth2 HWADDR=00:16:41:11:22:33 BOOTPROTO=dhcp ONBOOT=yes -ONBOOT=yes USERCTL=yes IPV6INIT=no NM_CONTROLLED=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected index 040ddc9d..92c03b12 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected @@ -13,8 +13,10 @@ #L2 METRIC1='' -METRIC2=$'\U0x' -METRIC3=$'x\U0' +METRIC2= +#NM: METRIC2=$'\U0x' +METRIC3= +#NM: METRIC3=$'x\U0' #L4 IPADDR=set-by-test1 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-1.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-1.cexpected new file mode 100644 index 00000000..5186f90c --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-1.cexpected @@ -0,0 +1,14 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-2.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-2.cexpected new file mode 100644 index 00000000..5632ebec --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-2.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="-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=stable-privacy +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-3.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-3.cexpected new file mode 100644 index 00000000..96eec43b --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-3.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-4.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-4.cexpected new file mode 100644 index 00000000..90250a30 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-4.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="-K net0 rx on" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-5.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-5.cexpected new file mode 100644 index 00000000..721eacb2 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-5.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -K net0 rx on" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +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 9d9ed626..d9829f84 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 @@ -17,7 +17,8 @@ #include #include -#include "nm-glib-aux/nm-json-aux.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-json-aux.h" #include "nm-utils.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" @@ -36,9 +37,9 @@ #include "nm-setting-serial.h" #include "nm-setting-vlan.h" #include "nm-setting-dcb.h" -#include "nm-core-internal.h" -#include "nm-base/nm-ethtool-base.h" -#include "nm-base/nm-ethtool-utils-base.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-base/nm-ethtool-base.h" +#include "libnm-base/nm-ethtool-utils-base.h" #include "NetworkManagerUtils.h" @@ -180,8 +181,20 @@ _assert_expected_content(NMConnection *connection, const char *filename, const c } if (len_expectd != len_written || memcmp(content_expectd, content_written, len_expectd) != 0) { - if (g_getenv("NMTST_IFCFG_RH_UPDATE_EXPECTED") - || nm_streq0(g_getenv("NM_TEST_REGENERATE"), "1")) { + static int rewrite_static = 0; + int rewrite; + + rewrite = g_atomic_int_get(&rewrite_static); + if (G_UNLIKELY(rewrite == 0)) { + rewrite = (g_getenv("NMTST_IFCFG_RH_UPDATE_EXPECTED") + || nm_streq0(g_getenv("NM_TEST_REGENERATE"), "1")) + ? 1 + : -1; + if (!g_atomic_int_compare_and_exchange(&rewrite_static, 0, rewrite)) + g_assert_not_reached(); + } + + if (rewrite > 0) { if (uuid) { gs_free char *search = g_strdup_printf("UUID=%s\n", uuid); const char * s; @@ -209,15 +222,16 @@ _assert_expected_content(NMConnection *connection, const char *filename, const c success = g_file_set_contents(expected, content_written, len_written, &error); nmtst_assert_success(success, error); } else { - g_error("The content of \"%s\" (%zu) differs from \"%s\" (%zu). Set " - "NMTST_IFCFG_RH_UPDATE_EXPECTED=yes to update the files " - "inplace\n\n>>>%s<<<\n\n>>>%s<<<\n", - filename, - len_written, - expected, - len_expectd, - content_written, - content_expectd); + g_error( + "The content of \"%s\" (%zu) differs from \"%s\" (%zu). Set " + "NMTST_IFCFG_RH_UPDATE_EXPECTED=yes (or NM_TEST_REGENERATE=1) to update the files " + "inplace\n\n>>>%s<<<\n\n>>>%s<<<\n", + filename, + len_written, + expected, + len_expectd, + content_written, + content_expectd); } } } @@ -359,8 +373,10 @@ _writer_new_connection_reread(NMConnection * connection, if (out_filename) *out_filename = filename; - else + else { + nmtst_file_unlink(filename); g_free(filename); + } } static void @@ -722,10 +738,13 @@ test_read_variables_corner_cases(void) const char * mac; char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; + NMTST_EXPECT_NM_WARN("*key NAME is badly quoted and is treated as \"\"*"); + NMTST_EXPECT_NM_WARN("*key ZONE is badly quoted and is treated as \"\"*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-variables-corner-cases-1", NULL, TYPE_ETHERNET, NULL); + g_test_assert_expected_messages(); /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection(connection); @@ -814,10 +833,12 @@ test_read_unrecognized(void) gs_free char * unhandled_spec = NULL; guint64 expected_timestamp = 0; + NMTST_EXPECT_NM_WARN("*key NAME is badly quoted and is treated as \"\"*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-unrecognized", NULL, NULL, &unhandled_spec); + g_test_assert_expected_messages(); g_assert_cmpstr(unhandled_spec, ==, "unrecognized:mac:00:11:22:33"); /* ===== CONNECTION SETTING ===== */ @@ -988,10 +1009,12 @@ test_read_wired_dhcp(void) char expected_mac_address[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xee}; const char * mac; + NMTST_EXPECT_NM_WARN("*key IPV6INIT is duplicated and the early occurrence ignored*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-dhcp", NULL, TYPE_ETHERNET, &unmanaged); + g_test_assert_expected_messages(); g_assert(unmanaged == NULL); /* ===== CONNECTION SETTING ===== */ @@ -2519,7 +2542,7 @@ test_write_dns_options(void) NM_SETTING_CONNECTION_ID, "Test DNS options", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -3567,10 +3590,12 @@ test_read_wifi_wpa_eap_tls(void) char * unmanaged = NULL; const char * expected_privkey_password = "test1"; + NMTST_EXPECT_NM_WARN("*key ONBOOT is duplicated and the early occurrence ignored*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-eap-tls", NULL, TYPE_ETHERNET, &unmanaged); + g_test_assert_expected_messages(); g_assert(!unmanaged); /* ===== WIRELESS SETTING ===== */ @@ -3775,10 +3800,12 @@ test_read_wifi_wep_eap_ttls_chap(void) NMSetting8021x * s_8021x; char * unmanaged = NULL; + NMTST_EXPECT_NM_WARN("*key ONBOOT is duplicated and the early occurrence ignored*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-eap-ttls-chap", NULL, TYPE_WIRELESS, &unmanaged); + g_test_assert_expected_messages(); g_assert(!unmanaged); /* ===== WIRELESS SETTING ===== */ @@ -3932,6 +3959,76 @@ test_read_wired_unknown_ethtool_opt(void) g_assert_cmpstr(nm_setting_wired_get_wake_on_lan_password(s_wired), ==, "00:11:22:33:44:55"); } +static void +test_roundtrip_ethtool(void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSetting * s_ethtool; + NMSetting * s_wired; + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-1.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_ethtool = nm_setting_ethtool_new(); + nm_connection_add_setting(connection, s_ethtool); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-2.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nm_connection_get_setting(connection, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-3.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_ethtool = nm_setting_ethtool_new(); + nm_connection_add_setting(connection, s_ethtool); + nm_setting_option_set_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX, TRUE); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-4.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nm_connection_get_setting(connection, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); + s_ethtool = nm_setting_ethtool_new(); + nm_connection_add_setting(connection, s_ethtool); + nm_setting_option_set_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX, TRUE); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-5.cexpected", + NULL); + g_clear_object(&connection); +} + static void test_read_wifi_hidden(void) { @@ -3977,7 +4074,7 @@ test_write_wifi_hidden(void) NM_SETTING_CONNECTION_ID, "Test Write Wi-Fi Hidden", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -4062,7 +4159,7 @@ test_write_wifi_mac_random(gconstpointer user_data) NM_SETTING_CONNECTION_ID, val, NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -4122,7 +4219,7 @@ test_write_wired_wake_on_lan(void) NM_SETTING_CONNECTION_ID, "Test Write Wired Wake-on-LAN", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); @@ -4305,7 +4402,7 @@ test_write_wifi_band_a(void) NM_SETTING_CONNECTION_ID, "Test Write Wi-Fi Band A", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -4363,7 +4460,7 @@ test_write_wifi_ap_mode(void) NM_SETTING_CONNECTION_ID, "Test Write Wi-Fi AP Mode", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -4676,7 +4773,7 @@ test_write_wired_static(void) NM_SETTING_CONNECTION_ID, "Test Write Wired Static", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, @@ -4831,7 +4928,7 @@ test_write_wired_static_with_generic(void) NM_SETTING_CONNECTION_ID, "Test Write Wired Static", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, @@ -4999,7 +5096,7 @@ test_write_wired_dhcp(void) NM_SETTING_CONNECTION_ID, "Test Write Wired DHCP", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5111,7 +5208,7 @@ test_write_routing_rules(void) NM_SETTING_CONNECTION_ID, "Test Write Routing Rules", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5169,7 +5266,7 @@ test_write_wired_match(void) NM_SETTING_CONNECTION_ID, "Test Write Wired with Match setting", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5315,7 +5412,7 @@ test_write_wired_static_ip6_only(void) NM_SETTING_CONNECTION_ID, "Test Write Wired Static IP6 Only", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5432,7 +5529,7 @@ test_write_wired_static_ip6_only_gw(gconstpointer user_data) NM_SETTING_CONNECTION_ID, id, NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5587,7 +5684,7 @@ test_write_wired_static_routes(void) NM_SETTING_CONNECTION_ID, "Test Write Wired Static Routes", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5711,7 +5808,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2(void) NM_SETTING_CONNECTION_ID, "Test Write Wired DHCP 802.1x PEAP MSCHAPv2", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5813,7 +5910,7 @@ test_write_wired_8021x_tls(gconstpointer test_data) NM_SETTING_CONNECTION_ID, "Test Write Wired 802.1x TLS Blobs", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -5983,7 +6080,7 @@ test_write_wired_aliases(void) NM_SETTING_CONNECTION_ID, "alias0", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); @@ -6110,7 +6207,7 @@ test_write_gateway(void) NM_SETTING_CONNECTION_ID, "Test Write Static Addresses Gateway", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); @@ -6187,7 +6284,7 @@ test_write_wifi_open(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi Open", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6273,7 +6370,7 @@ test_write_wifi_open_hex_ssid(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi Open Hex SSID", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6347,7 +6444,7 @@ test_write_wifi_wep(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6445,7 +6542,7 @@ test_write_wifi_wep_adhoc(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP AdHoc", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6539,7 +6636,7 @@ test_write_wifi_wep_passphrase(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP Passphrase", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6634,7 +6731,7 @@ test_write_wifi_wep_40_ascii(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP 40 ASCII", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6732,7 +6829,7 @@ test_write_wifi_wep_104_ascii(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP 104 ASCII", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6833,7 +6930,7 @@ test_write_wifi_leap(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi LEAP", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -6931,7 +7028,7 @@ test_write_wifi_leap_secret_flags(gconstpointer data) NM_SETTING_CONNECTION_ID, "Test Write Wifi LEAP Secret Flags", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -7037,7 +7134,7 @@ test_write_wifi_wpa_psk(gconstpointer test_data) NM_SETTING_CONNECTION_ID, args.name, NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -7142,7 +7239,7 @@ test_write_wifi_wpa_psk_adhoc(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA PSK", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -7252,7 +7349,7 @@ test_write_wifi_wpa_eap_tls(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TLS", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -7295,8 +7392,8 @@ test_write_wifi_wpa_eap_tls(void) g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); g_object_set(s_8021x, NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, - (guint)(NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE - | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE), + (guint) (NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE + | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE), NULL); nm_setting_802_1x_add_eap_method(s_8021x, "tls"); @@ -7379,7 +7476,7 @@ test_write_wifi_wpa_eap_ttls_tls(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TTLS (TLS)", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -7515,7 +7612,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TTLS (MSCHAPv2)", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -7630,7 +7727,7 @@ test_write_wifi_wpa_then_open(void) NM_SETTING_CONNECTION_ID, "random wifi connection", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -7747,7 +7844,7 @@ test_write_wifi_wpa_then_wep_with_perms(void) NM_SETTING_CONNECTION_ID, "random wifi connection 2", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_PERMISSIONS, @@ -7872,7 +7969,7 @@ test_write_wifi_dynamic_wep_leap(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi Dynamic WEP LEAP", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -7969,7 +8066,7 @@ test_write_wired_qeth_dhcp(void) NM_SETTING_CONNECTION_ID, "Test Write Wired qeth Static", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -8043,7 +8140,7 @@ test_write_wired_ctc_dhcp(void) NM_SETTING_CONNECTION_ID, "Test Write Wired ctc Static", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); @@ -8118,7 +8215,7 @@ test_write_permissions(void) NM_SETTING_CONNECTION_ID, "Test Write Permissions", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -8187,7 +8284,7 @@ test_write_wifi_wep_agent_keys(void) NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP Agent Owned", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); @@ -8273,7 +8370,7 @@ test_write_wired_pppoe(void) NM_SETTING_CONNECTION_ID, "Test Write Wired PPPoE", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -8334,7 +8431,7 @@ test_write_vpn(void) NM_SETTING_CONNECTION_ID, "Test Write VPN", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -8392,7 +8489,7 @@ test_write_mobile_broadband(gconstpointer data) NM_SETTING_CONNECTION_ID, gsm ? "Test Write GSM" : "Test Write CDMA", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -8510,7 +8607,7 @@ test_write_bridge_main(void) NM_SETTING_CONNECTION_ID, "Test Write Bridge Main", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -8639,7 +8736,7 @@ test_write_bridge_component(void) NM_SETTING_CONNECTION_ID, "Test Write Bridge Component", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -8786,6 +8883,38 @@ test_read_vlan_only_vlan_id(void) g_object_unref(connection); } +static void +test_read_vlan_vlanid_use(void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingVlan * s_vlan; + + connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-vlanid-use", + NULL, + TYPE_ETHERNET, + NULL); + + g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "eth0.9"); + + s_vlan = nm_connection_get_setting_vlan(connection); + g_assert(s_vlan); + + g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); + g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 10); + g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS); + + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test-vlan-vlanid-use.cexpected", + &testfile); + + reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); + + nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); +} + static void test_read_vlan_only_device(void) { @@ -8991,7 +9120,7 @@ test_write_vlan_reorder_hdr(void) NM_SETTING_CONNECTION_ID, "Test Write VLAN reorder_hdr", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NM_SETTING_CONNECTION_TYPE, @@ -9046,7 +9175,7 @@ test_write_ethernet_missing_ipv6(void) NM_SETTING_CONNECTION_ID, "Test Write Ethernet Without IPv6 Setting", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -9170,7 +9299,7 @@ test_write_bond_main(void) NM_SETTING_CONNECTION_ID, "Test Write Bond Main", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -9270,7 +9399,7 @@ test_write_bond_slave(void) NM_SETTING_CONNECTION_ID, "Test Write Bond Slave", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -9357,7 +9486,7 @@ test_write_infiniband(void) NM_SETTING_CONNECTION_ID, "Test Write InfiniBand", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -9446,7 +9575,7 @@ test_write_bond_slave_ib(void) NM_SETTING_CONNECTION_ID, "Test Write Bond Slave InfiniBand", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_TYPE, @@ -9604,7 +9733,7 @@ test_write_dcb_basic(void) NM_SETTING_CONNECTION_ID, "dcb-test", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -9850,7 +9979,7 @@ test_write_fcoe_mode(gconstpointer user_data) NM_SETTING_CONNECTION_ID, "fcoe-test", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -9968,7 +10097,7 @@ test_write_team_master(void) NM_SETTING_CONNECTION_ID, "Test Write Team Master", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_INTERFACE_NAME, "team0", NM_SETTING_CONNECTION_TYPE, @@ -10060,7 +10189,7 @@ test_write_team_port(void) NM_SETTING_CONNECTION_ID, "Test Write Team Port", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_CONNECTION_MASTER, @@ -10119,7 +10248,7 @@ test_write_team_infiniband_port(void) NM_SETTING_CONNECTION_ID, "Test Write Team Infiniband Port", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_CONNECTION_MASTER, @@ -10309,7 +10438,7 @@ test_write_proxy_basic(void) NM_SETTING_CONNECTION_ID, "Test Write Proxy Basic", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); @@ -10358,7 +10487,7 @@ _svUnescape(const char *str, char **to_free) str = (str_free = g_strdup(str)); } - s = svUnescape(str, to_free); + s = svUnescape_full(str, to_free, FALSE); if (*to_free) { g_assert(s == *to_free); g_assert(s[0]); @@ -10366,6 +10495,37 @@ _svUnescape(const char *str, char **to_free) g_assert(s == NULL || (!s[0] && (s < str || s > strchr(str, '\0'))) || (s[0] && s >= str && s <= strchr(str, '\0'))); } + + { + const char * s2; + gs_free char *to_free2 = NULL; + + gboolean is_utf8 = s && g_utf8_validate(s, -1, NULL); + + s2 = svUnescape_full(str, &to_free2, TRUE); + if (NM_IN_STRSET(str, "$'\\U0x'", "$'\\x0'", "$'\\008'", "$'\\08'")) { + g_assert_cmpstr(s2, ==, NULL); + g_assert(!to_free2); + g_assert_cmpstr(s, ==, ""); + g_assert(!*to_free); + } else if (NM_IN_STRSET(str, "$'x\\U0'")) { + g_assert_cmpstr(s2, ==, NULL); + g_assert(!to_free2); + g_assert_cmpstr(s, ==, "x"); + g_assert(*to_free == s); + } else if (!is_utf8) { + g_assert(!s2); + g_assert(!to_free2); + } else if (!to_free2) { + g_assert_cmpstr(s, ==, s2); + g_assert(s == s2); + } else { + g_assert_cmpstr(s, ==, s2); + g_assert(s != s2); + g_assert(s2 == to_free2); + } + } + return s; } @@ -10547,6 +10707,9 @@ test_svUnescape(void) V1("\"\\'\"''", "\\'"), V0("\"b\\~b\" ", "b\\~b"), V1("\"b\\~b\"x", "b\\~bx"), + + V0("$'x\\U0'", "x"), + V0("$'\\U0x'", ""), }; const UnescapeTestData data_ansi[] = { /* strings inside $''. They cannot be compared directly, but must @@ -10733,7 +10896,7 @@ test_write_unknown(gconstpointer test_data) _svGetValue_check(sv, "METRIC", NULL); _svGetValue_check(sv, "METRIC1", ""); _svGetValue_check(sv, "METRIC2", ""); - _svGetValue_check(sv, "METRIC3", "x"); + _svGetValue_check(sv, "METRIC3", ""); _svGetValue_check(sv, "IPADDR", "set-by-test1"); _svGetValue_check(sv, "IPADDR2", "set-by-test2"); @@ -10999,7 +11162,7 @@ test_sriov_write(void) NM_SETTING_CONNECTION_ID, "Test Write SR-IOV config", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -11132,7 +11295,7 @@ test_tc_write_empty(void) NM_SETTING_CONNECTION_ID, "Test Write TC config", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -11213,7 +11376,7 @@ test_tc_write(void) NM_SETTING_CONNECTION_ID, "Test Write TC config", NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_a(), + nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, @@ -11405,6 +11568,7 @@ test_ethtool_names(void) } s_idxs[] = { {_NM_ETHTOOL_ID_FEATURE_FIRST, _NM_ETHTOOL_ID_FEATURE_LAST}, {_NM_ETHTOOL_ID_COALESCE_FIRST, _NM_ETHTOOL_ID_COALESCE_LAST}, + {_NM_ETHTOOL_ID_PAUSE_FIRST, _NM_ETHTOOL_ID_PAUSE_LAST}, {_NM_ETHTOOL_ID_RING_FIRST, _NM_ETHTOOL_ID_RING_LAST}, }; const NMEthtoolData *data; @@ -11599,6 +11763,8 @@ main(int argc, char **argv) g_test_add_func(TPATH "802-1x/password_raw", test_read_write_802_1x_password_raw); g_test_add_func(TPATH "802-1x/tls-p12-no-client-cert", test_read_802_1x_tls_p12_no_client_cert); + g_test_add_func(TPATH "wired/roundtrip/ethtool", test_roundtrip_ethtool); + g_test_add_data_func(TPATH "wired/read/aliases/good/0", GINT_TO_POINTER(0), test_read_wired_aliases_good); @@ -11705,6 +11871,7 @@ main(int argc, char **argv) g_test_add_func(TPATH "vlan/read/physdev", test_read_vlan_physdev); g_test_add_func(TPATH "vlan/read/reorder-hdr-1", test_read_vlan_reorder_hdr_1); g_test_add_func(TPATH "vlan/read/reorder-hdr-2", test_read_vlan_reorder_hdr_2); + g_test_add_func(TPATH "vlan/read/vlanid-use", test_read_vlan_vlanid_use); g_test_add_func(TPATH "wired/read/read-wake-on-lan", test_read_wired_wake_on_lan); g_test_add_func(TPATH "wired/read/read-auto-negotiate-off", test_read_wired_auto_negotiate_off); g_test_add_func(TPATH "wired/read/read-auto-negotiate-on", test_read_wired_auto_negotiate_on); diff --git a/src/core/settings/plugins/ifupdown/meson.build b/src/core/settings/plugins/ifupdown/meson.build index dd252783..1bff8155 100644 --- a/src/core/settings/plugins/ifupdown/meson.build +++ b/src/core/settings/plugins/ifupdown/meson.build @@ -7,14 +7,12 @@ libnms_ifupdown_core = static_library( 'nms-ifupdown-parser.c', ), dependencies: core_default_dep, - c_args: daemon_c_flags, ) libnm_settings_plugin_ifupdown = shared_module( 'nm-settings-plugin-ifupdown', sources: 'nms-ifupdown-plugin.c', dependencies: core_plugin_dep, - c_args: daemon_c_flags, link_with: libnms_ifupdown_core, link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c index a4974a96..db6b1aef 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -12,7 +12,8 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings-plugin.h" #include "nms-ifupdown-plugin.h" @@ -32,14 +33,6 @@ /*****************************************************************************/ -#define _str_has_prefix(val, prefix, require_suffix) \ - ({ \ - const char *_val = (val); \ - \ - (strncmp(_val, "" prefix "", NM_STRLEN(prefix)) == 0) \ - && (!(require_suffix) || _val[NM_STRLEN(prefix)] != '\0'); \ - }) - static const char * _ifupdownplugin_guess_connection_type(if_block *block) { @@ -51,8 +44,7 @@ _ifupdownplugin_guess_connection_type(if_block *block) if_data *ifb; c_list_for_each_entry (ifb, &block->data_lst_head, data_lst) { - if (_str_has_prefix(ifb->key, "wireless-", FALSE) - || _str_has_prefix(ifb->key, "wpa-", FALSE)) { + if (NM_STR_HAS_PREFIX(ifb->key, "wireless-") || NM_STR_HAS_PREFIX(ifb->key, "wpa-")) { ret_type = NM_SETTING_WIRELESS_SETTING_NAME; break; } @@ -102,7 +94,7 @@ update_wireless_setting_from_if_block(NMConnection *connection, if_block *block) wireless_setting = NM_SETTING_WIRELESS(nm_setting_wireless_new()); c_list_for_each_entry (curr, &block->data_lst_head, data_lst) { - if (_str_has_prefix(curr->key, "wireless-", TRUE)) { + if (NM_STR_HAS_PREFIX_WITH_MORE(curr->key, "wireless-")) { const char *newkey = map_by_mapping(mapping, curr->key + NM_STRLEN("wireless-")); _LOGI("wireless setting key: %s='%s'", newkey, curr->data); @@ -137,7 +129,7 @@ update_wireless_setting_from_if_block(NMConnection *connection, if_block *block) } else { g_object_set(wireless_setting, newkey, curr->data, NULL); } - } else if (_str_has_prefix(curr->key, "wpa-", TRUE)) { + } else if (NM_STR_HAS_PREFIX_WITH_MORE(curr->key, "wpa-")) { const char *newkey = map_by_mapping(mapping, curr->key + NM_STRLEN("wpa-")); if (nm_streq0(newkey, "ssid")) { @@ -304,7 +296,7 @@ update_wireless_security_setting_from_if_block(NMConnection *connection, if_bloc wireless_security_setting = NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new()); c_list_for_each_entry (curr, &block->data_lst_head, data_lst) { - if (_str_has_prefix(curr->key, "wireless-", TRUE)) { + if (NM_STR_HAS_PREFIX_WITH_MORE(curr->key, "wireless-")) { const char * key = curr->key + NM_STRLEN("wireless-"); char * property_value = NULL; gpointer typed_property_value = NULL; @@ -336,7 +328,7 @@ wireless_next: if (typed_property_value && free_func) (*free_func)(typed_property_value); - } else if (_str_has_prefix(curr->key, "wpa-", TRUE)) { + } else if (NM_STR_HAS_PREFIX_WITH_MORE(curr->key, "wpa-")) { const char * key = curr->key + NM_STRLEN("wpa-"); char * property_value = NULL; gpointer typed_property_value = NULL; @@ -644,7 +636,7 @@ ifupdown_new_connection_from_if_block(if_block *block, gboolean autoconnect, GEr type = _ifupdownplugin_guess_connection_type(block); idstr = g_strconcat("Ifupdown (", block->name, ")", NULL); - uuid = nm_utils_uuid_generate_from_string(idstr, -1, NM_UTILS_UUID_TYPE_LEGACY, NULL); + uuid = nm_uuid_generate_from_string_str(idstr, -1, NM_UUID_TYPE_LEGACY, NULL); g_object_set(s_con, NM_SETTING_CONNECTION_TYPE, type, @@ -655,7 +647,7 @@ ifupdown_new_connection_from_if_block(if_block *block, gboolean autoconnect, GEr NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_AUTOCONNECT, - (gboolean)(!!autoconnect), + (gboolean) (!!autoconnect), NULL); _LOGD("update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s", diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 34523f8d..80a5638a 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -9,7 +9,7 @@ #include "nms-ifupdown-plugin.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" #include "nm-config.h" #include "settings/nm-settings-plugin.h" diff --git a/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c index 6e3eb0e7..0e8db733 100644 --- a/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -5,7 +5,7 @@ #include "src/core/nm-default-daemon.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/plugins/ifupdown/nms-ifupdown-interface-parser.h" #include "settings/plugins/ifupdown/nms-ifupdown-parser.h" diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c index 789bfc1a..e8ae1814 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -13,19 +13,20 @@ #include #include -#include "nm-std-aux/c-list-util.h" -#include "nm-glib-aux/nm-c-list.h" -#include "nm-glib-aux/nm-io-utils.h" +#include "libnm-std-aux/c-list-util.h" +#include "libnm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-io-utils.h" #include "nm-connection.h" #include "nm-setting.h" #include "nm-setting-connection.h" #include "nm-utils.h" #include "nm-config.h" -#include "nm-core-internal.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" -#include "systemd/nm-sd-utils-shared.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" #include "settings/nm-settings-plugin.h" #include "settings/nm-settings-storage.h" @@ -233,7 +234,7 @@ _read_from_file(const char * full_filename, nm_assert(!connection || (_nm_connection_verify(connection, NULL) == NM_SETTING_VERIFY_SUCCESS)); - nm_assert(!connection || nm_utils_is_uuid(nm_connection_get_uuid(connection))); + nm_assert(!connection || nm_uuid_is_normalized(nm_connection_get_uuid(connection))); return connection; } @@ -260,7 +261,7 @@ _nm_assert_storage(gpointer plugin /* NMSKeyfilePlugin */, uuid = nms_keyfile_storage_get_uuid(storage); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); nm_assert(((NMSKeyfileStorage *) storage)->is_meta_data || !(((NMSKeyfileStorage *) storage)->u.conn_data.connection) @@ -1106,7 +1107,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone(NMSKeyfilePlugin * self, const char * dirname; nm_assert(NMS_IS_KEYFILE_PLUGIN(self)); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); nm_assert(!out_storage || !*out_storage); nm_assert(!shadowed_storage || (set && in_memory)); @@ -1246,9 +1247,9 @@ nms_keyfile_plugin_init(NMSKeyfilePlugin *plugin) /* dirname_libs are a set of read-only directories with lower priority than /etc or /run. * There is nothing complicated about having multiple of such directories, so dirname_libs * is a list (which currently only has at most one directory). */ - priv->dirname_libs[0] = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_LIB), FALSE); + priv->dirname_libs[0] = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_LIB)); priv->dirname_libs[1] = NULL; - priv->dirname_run = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_RUN), FALSE); + priv->dirname_run = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_RUN)); priv->dirname_etc = nm_config_data_get_value(NM_CONFIG_GET_DATA_ORIG, NM_CONFIG_KEYFILE_GROUP_KEYFILE, NM_CONFIG_KEYFILE_KEY_KEYFILE_PATH, @@ -1261,10 +1262,9 @@ nms_keyfile_plugin_init(NMSKeyfilePlugin *plugin) } else if (!priv->dirname_etc || priv->dirname_etc[0] != '/') { /* either invalid path or unspecified. Use the default. */ g_free(priv->dirname_etc); - priv->dirname_etc = - nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_ETC_DEFAULT), FALSE); + priv->dirname_etc = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_ETC_DEFAULT)); } else - nm_sd_utils_path_simplify(priv->dirname_etc, FALSE); + nm_sd_utils_path_simplify(priv->dirname_etc); /* no duplicates */ if (NM_IN_STRSET(priv->dirname_libs[0], priv->dirname_etc, priv->dirname_run)) diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-reader.c b/src/core/settings/plugins/keyfile/nms-keyfile-reader.c index 70b047f3..8b9d982f 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-reader.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-reader.c @@ -9,7 +9,7 @@ #include -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "NetworkManagerUtils.h" #include "nms-keyfile-utils.h" diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-storage.c b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c index 89be817a..8c526c81 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-storage.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c @@ -7,8 +7,9 @@ #include "nms-keyfile-storage.h" +#include "libnm-glib-aux/nm-uuid.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nms-keyfile-plugin.h" /*****************************************************************************/ @@ -108,7 +109,7 @@ _storage_new(NMSKeyfilePlugin * plugin, NMSKeyfileStorage *self; nm_assert(NMS_IS_KEYFILE_PLUGIN(plugin)); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); nm_assert(filename && filename[0] == '/'); self = g_object_new(NMS_TYPE_KEYFILE_STORAGE, @@ -135,7 +136,7 @@ nms_keyfile_storage_new_tombstone(NMSKeyfilePlugin * plugin, { NMSKeyfileStorage *self; - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); nm_assert(filename && filename[0] == '/'); nm_assert(nms_keyfile_nmmeta_check_filename(filename, NULL)); nm_assert(NM_IN_SET(storage_type, NMS_KEYFILE_STORAGE_TYPE_ETC, NMS_KEYFILE_STORAGE_TYPE_RUN)); diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c index ca1233f5..e2c68bbe 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c @@ -10,8 +10,9 @@ #include #include -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-keyfile-internal.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-io-utils.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nm-utils.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" @@ -30,9 +31,9 @@ const char * nms_keyfile_nmmeta_check_filename(const char *filename, guint *out_uuid_len) { - const char *uuid; const char *s; gsize len; + char uuid[37]; s = strrchr(filename, '/'); if (s) @@ -50,17 +51,18 @@ nms_keyfile_nmmeta_check_filename(const char *filename, guint *out_uuid_len) len -= NM_STRLEN(NM_KEYFILE_PATH_SUFFIX_NMMETA); - if (!NM_IN_SET(len, 36, 40)) { + if (len != 36) { /* the remaining part of the filename has not the right length to - * contain a UUID (according to nm_utils_is_uuid()). */ + * contain a UUID (according to nm_uuid_is_normalized()). */ return NULL; } - uuid = nm_strndup_a(100, filename, len, NULL); - if (!nm_utils_is_uuid(uuid)) + memcpy(uuid, filename, 36); + uuid[36] = '\0'; + if (!nm_uuid_is_normalized(uuid)) return NULL; - NM_SET_OUT(out_uuid_len, len); + NM_SET_OUT(out_uuid_len, 36); return filename; } @@ -71,7 +73,7 @@ nms_keyfile_nmmeta_filename(const char *dirname, const char *uuid, gboolean temp char *s; nm_assert(dirname && dirname[0] == '/'); - nm_assert(nm_utils_is_uuid(uuid) && !strchr(uuid, '/')); + nm_assert(nm_uuid_is_normalized(uuid) && !strchr(uuid, '/')); if (g_snprintf(filename, sizeof(filename), @@ -80,7 +82,7 @@ nms_keyfile_nmmeta_filename(const char *dirname, const char *uuid, gboolean temp NM_KEYFILE_PATH_SUFFIX_NMMETA, temporary ? "~" : "") >= sizeof(filename)) { - /* valid uuids are limited in length (nm_utils_is_uuid). The buffer should always + /* valid uuids are limited in length (nm_uuid_is_normalized). The buffer should always * be large enough. */ nm_assert_not_reached(); } @@ -215,7 +217,7 @@ nms_keyfile_nmmeta_write(const char *dirname, int errsv; nm_assert(dirname && dirname[0] == '/'); - nm_assert(nm_utils_is_uuid(uuid) && !strchr(uuid, '/')); + nm_assert(nm_uuid_is_normalized(uuid) && !strchr(uuid, '/')); nm_assert(!loaded_path || loaded_path[0] == '/'); nm_assert(!shadowed_storage || loaded_path); @@ -273,7 +275,13 @@ nms_keyfile_nmmeta_write(const char *dirname, contents = g_key_file_to_data(kf, &length, NULL); - if (!nm_utils_file_set_contents(full_filename, contents, length, 0600, &errsv, NULL)) { + if (!nm_utils_file_set_contents(full_filename, + contents, + length, + 0600, + NULL, + &errsv, + NULL)) { NM_SET_OUT(out_full_filename, g_steal_pointer(&full_filename_tmp)); return -NM_ERRNO_NATIVE(errsv); } diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c index 0e2c94b5..70afdc23 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c @@ -12,12 +12,12 @@ #include #include -#include "nm-keyfile-internal.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nms-keyfile-utils.h" #include "nms-keyfile-reader.h" -#include "nm-glib-aux/nm-io-utils.h" +#include "libnm-glib-aux/nm-io-utils.h" /*****************************************************************************/ @@ -125,13 +125,14 @@ cert_writer(NMConnection * connection, /* FIXME(keyfile-parse-in-memory): writer must not access/write to the file system before * being sure that the entire profile can be written and all circumstances are good to - * proceed. That means, while writing we must only collect the blogs in-memory, and write + * proceed. That means, while writing we must only collect the blobs in-memory, and write * them all in the end together (or not at all). */ success = nm_utils_file_set_contents(new_path, (const char *) blob_data, blob_len, 0600, NULL, + NULL, &local); if (success) { /* Write the path value to the keyfile. @@ -378,7 +379,7 @@ _internal_write_connection(NMConnection * connection, } } - nm_utils_file_set_contents(path, kf_content_buf, kf_content_len, 0600, NULL, &local_err); + nm_utils_file_set_contents(path, kf_content_buf, kf_content_len, 0600, NULL, NULL, &local_err); if (local_err) { g_set_error(error, NM_SETTINGS_ERROR, 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 348b0ed6..a13c2586 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -15,7 +15,8 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-core-intern/nm-core-internal.h" #include "settings/plugins/keyfile/nms-keyfile-reader.h" #include "settings/plugins/keyfile/nms-keyfile-writer.h" @@ -2289,7 +2290,7 @@ test_read_missing_id_uuid(void) gs_free char * expected_uuid = NULL; const char * FILENAME = TEST_KEYFILES_DIR "/Test_Missing_ID_UUID"; - expected_uuid = _nm_utils_uuid_generate_from_strings("keyfile", FILENAME, NULL); + expected_uuid = nm_uuid_generate_from_strings("keyfile", FILENAME, NULL); connection = keyfile_read_connection_from_file(FILENAME); diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c index bc2a692e..1959a161 100644 --- a/src/core/supplicant/nm-supplicant-config.c +++ b/src/core/supplicant/nm-supplicant-config.c @@ -10,11 +10,11 @@ #include -#include "nm-glib-aux/nm-str-buf.h" -#include "nm-core-internal.h" +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-supplicant-settings-verify.h" #include "nm-setting.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-setting-ip4-config.h" @@ -334,11 +334,10 @@ nm_supplicant_config_to_variant(NMSupplicantConfig *self) break; case NM_SUPPL_OPT_TYPE_BYTES: case NM_SUPPL_OPT_TYPE_UTF8: - g_variant_builder_add( - &builder, - "{sv}", - key, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, option->value, option->len, 1)); + g_variant_builder_add(&builder, + "{sv}", + key, + nm_g_variant_new_ay((const guint8 *) option->value, option->len)); break; case NM_SUPPL_OPT_TYPE_KEYWORD: case NM_SUPPL_OPT_TYPE_STRING: @@ -667,8 +666,8 @@ add_string_val(NMSupplicantConfig *self, display_value, \ error) \ ({ \ - typeof(*(setting)) *_setting = (setting); \ - gboolean _success = TRUE; \ + typeof(setting) _setting = (setting); \ + gboolean _success = TRUE; \ \ if (nm_setting_##setting_name##_get_num_##field_plural(_setting)) { \ const char _separator = (separator); \ @@ -815,7 +814,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * nm_auto_free_gstring GString *key_mgmt_conf = NULL; const char * key_mgmt, *auth_alg; const char * psk; - gboolean set_pmf; + gboolean set_pmf, wps_disabled; g_return_val_if_fail(NM_IS_SUPPLICANT_CONFIG(self), FALSE); g_return_val_if_fail(setting != NULL, FALSE); @@ -835,58 +834,82 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } key_mgmt = nm_setting_wireless_security_get_key_mgmt(setting); - key_mgmt_conf = g_string_new(key_mgmt); - if (nm_streq(key_mgmt, "wpa-psk")) { + key_mgmt_conf = g_string_new(""); + + if (nm_streq(key_mgmt, "none")) { + g_string_append(key_mgmt_conf, "NONE"); + + } else if (nm_streq(key_mgmt, "ieee8021x")) { + g_string_append(key_mgmt_conf, "IEEE8021X"); + + } else if (nm_streq(key_mgmt, "owe")) { + pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; + + g_string_append(key_mgmt_conf, "OWE"); + + } else if (nm_streq(key_mgmt, "wpa-psk")) { + if (pmf != NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) + g_string_append(key_mgmt_conf, "WPA-PSK"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) - g_string_append(key_mgmt_conf, " wpa-psk-sha256"); + g_string_append(key_mgmt_conf, " WPA-PSK-SHA256"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) - g_string_append(key_mgmt_conf, " ft-psk"); + g_string_append(key_mgmt_conf, " FT-PSK"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)) { - g_string_append(key_mgmt_conf, " sae"); + g_string_append(key_mgmt_conf, " SAE"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) - g_string_append(key_mgmt_conf, " ft-sae"); + g_string_append(key_mgmt_conf, " FT-SAE"); } + + } else if (nm_streq(key_mgmt, "sae")) { + pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; + + g_string_append(key_mgmt_conf, "SAE"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) + g_string_append(key_mgmt_conf, " FT-SAE"); + } else if (nm_streq(key_mgmt, "wpa-eap")) { + if (pmf != NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) + g_string_append(key_mgmt_conf, "WPA-EAP"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) { + g_string_append(key_mgmt_conf, " FT-EAP"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) + g_string_append(key_mgmt_conf, " FT-EAP-SHA384"); + } if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { - g_string_append(key_mgmt_conf, " wpa-eap-sha256"); - + g_string_append(key_mgmt_conf, " WPA-EAP-SHA256"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SUITEB192) && pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) - g_string_append(key_mgmt_conf, " wpa-eap-suite-b-192"); + g_string_append(key_mgmt_conf, " WPA-EAP-SUITE-B-192"); } - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) - g_string_append(key_mgmt_conf, " ft-eap"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT) - && _get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) - g_string_append(key_mgmt_conf, " ft-eap-sha384"); + switch (fils) { case NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED: g_string_truncate(key_mgmt_conf, 0); if (!_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) - g_string_assign(key_mgmt_conf, "fils-sha256 fils-sha384"); + g_string_assign(key_mgmt_conf, "FILS-SHA256 FILS-SHA384"); /* fall-through */ case NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL: - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) - g_string_append(key_mgmt_conf, " fils-sha256 fils-sha384"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF) - && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) - g_string_append(key_mgmt_conf, " ft-fils-sha256"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF) - && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT) - && _get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) - g_string_append(key_mgmt_conf, " ft-fils-sha384"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { + g_string_append(key_mgmt_conf, " FILS-SHA256 FILS-SHA384"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) { + g_string_append(key_mgmt_conf, " FT-FILS-SHA256"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) + g_string_append(key_mgmt_conf, " FT-FILS-SHA384"); + } + } break; + default: break; } - } else if (nm_streq(key_mgmt, "sae")) { - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) - g_string_append(key_mgmt_conf, " ft-sae"); + } else if (nm_streq(key_mgmt, "wpa-eap-suite-b-192")) { pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; - if (!nm_supplicant_config_add_option(self, "pairwise", "GCMP-256", -1, NULL, error) - || !nm_supplicant_config_add_option(self, "group", "GCMP-256", -1, NULL, error)) - return FALSE; + + g_string_append(key_mgmt_conf, "WPA-EAP-SUITE-B-192"); + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT) + && _get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) + g_string_append(key_mgmt_conf, " FT-EAP-SHA384"); } if (!add_string_val(self, key_mgmt_conf->str, "key_mgmt", TRUE, NULL, error)) @@ -955,10 +978,6 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } } - /* Don't try to enable PMF on non-WPA/SAE/OWE networks */ - if (!NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192", "wpa-psk", "sae", "owe")) - pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; - /* Check if we actually support PMF */ set_pmf = TRUE; if (!_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { @@ -973,7 +992,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } /* Only WPA-specific things when using WPA */ - if (NM_IN_STRSET(key_mgmt, "wpa-psk", "wpa-eap", "sae", "owe")) { + if (NM_IN_STRSET(key_mgmt, "owe", "wpa-psk", "sae", "wpa-eap", "wpa-eap-suite-b-192")) { if (!ADD_STRING_LIST_VAL(self, setting, wireless_security, @@ -985,29 +1004,40 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * NULL, error)) return FALSE; - if (!ADD_STRING_LIST_VAL(self, - setting, - wireless_security, - pairwise, - pairwise, - "pairwise", - ' ', - TRUE, - NULL, - error)) - return FALSE; - if (!ADD_STRING_LIST_VAL(self, - setting, - wireless_security, - group, - groups, - "group", - ' ', - TRUE, - NULL, - error)) - return FALSE; + if (nm_streq(key_mgmt, "wpa-eap-suite-b-192")) { + if (!nm_supplicant_config_add_option(self, "pairwise", "GCMP-256", -1, NULL, error)) + return FALSE; + if (!nm_supplicant_config_add_option(self, "group", "GCMP-256", -1, NULL, error)) + return FALSE; + } else { + if (!ADD_STRING_LIST_VAL(self, + setting, + wireless_security, + pairwise, + pairwise, + "pairwise", + ' ', + TRUE, + NULL, + error)) + return FALSE; + if (!ADD_STRING_LIST_VAL(self, + setting, + wireless_security, + group, + groups, + "group", + ' ', + TRUE, + NULL, + error)) + return FALSE; + } + + /* We set the supplicants global "pmf" config value to "1" (optional), + * so no need to set it network-specific again if PMF_OPTIONAL is set. + */ if (set_pmf && NM_IN_SET(pmf, NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE, @@ -1107,6 +1137,13 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } } + wps_disabled = (nm_setting_wireless_security_get_wps_method(setting) + == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED); + if (wps_disabled) { + if (!nm_supplicant_config_add_option(self, "wps_disabled", "1", 1, NULL, error)) + return FALSE; + } + return TRUE; } diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index a38ebf18..1556e290 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -12,13 +12,13 @@ #include #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" -#include "nm-glib-aux/nm-c-list.h" -#include "nm-glib-aux/nm-ref-string.h" -#include "nm-std-aux/nm-dbus-compat.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-c-list.h" +#include "libnm-glib-aux/nm-ref-string.h" +#include "libnm-glib-aux/nm-dbus-aux.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-supplicant-config.h" #include "nm-supplicant-manager.h" -#include "shared/nm-glib-aux/nm-dbus-aux.h" #define DBUS_TIMEOUT_MSEC 20000 @@ -267,30 +267,41 @@ security_from_vardict(GVariant *security) NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; const char ** array; const char * tmp; + gsize i; + const char * v; nm_assert(g_variant_is_of_type(security, G_VARIANT_TYPE_VARDICT)); if (g_variant_lookup(security, "KeyMgmt", "^a&s", &array)) { - if (g_strv_contains(array, "wpa-psk") || g_strv_contains(array, "wpa-ft-psk")) - flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; - if (g_strv_contains(array, "wpa-eap") || g_strv_contains(array, "wpa-ft-eap") - || g_strv_contains(array, "wpa-fils-sha256") - || g_strv_contains(array, "wpa-fils-sha384")) - flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; - if (g_strv_contains(array, "sae")) - flags |= NM_802_11_AP_SEC_KEY_MGMT_SAE; - if (g_strv_contains(array, "owe")) - flags |= NM_802_11_AP_SEC_KEY_MGMT_OWE; - if (g_strv_contains(array, "wpa-eap-suite-b-192")) - flags |= NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192; + for (i = 0; (v = array[i]); i++) { + if (NM_IN_STRSET(v, "wpa-psk", "wpa-psk-sha256", "wpa-ft-psk")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; + else if (NM_IN_STRSET(v, + "wpa-eap", + "wpa-eap-sha256", + "wpa-ft-eap", + "wpa-fils-sha256", + "wpa-fils-sha384", + "wpa-fils-ft-sha256", + "wpa-fils-ft-sha384")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; + else if (NM_IN_STRSET(v, "sae", "ft-sae")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_SAE; + else if (NM_IN_STRSET(v, "owe")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_OWE; + else if (NM_IN_STRSET(v, "wpa-eap-suite-b-192", "wpa-ft-eap-sha384")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192; + } g_free(array); } if (g_variant_lookup(security, "Pairwise", "^a&s", &array)) { - if (g_strv_contains(array, "tkip")) - flags |= NM_802_11_AP_SEC_PAIR_TKIP; - if (g_strv_contains(array, "ccmp")) - flags |= NM_802_11_AP_SEC_PAIR_CCMP; + for (i = 0; (v = array[i]); i++) { + if (NM_IN_STRSET(v, "tkip")) + flags |= NM_802_11_AP_SEC_PAIR_TKIP; + else if (NM_IN_STRSET(v, "ccmp")) + flags |= NM_802_11_AP_SEC_PAIR_CCMP; + } g_free(array); } @@ -359,8 +370,12 @@ _dbus_connection_call_simple_cb(GObject *source, GAsyncResult *result, gpointer gs_free_error GError *error = NULL; const char * log_reason; gs_free char * remote_error = NULL; + gpointer p_suppress_warning; + gboolean suppress_warning; + + nm_utils_user_data_unpack(user_data, &self, &log_reason, &p_suppress_warning); - nm_utils_user_data_unpack(user_data, &self, &log_reason); + suppress_warning = GPOINTER_TO_INT(p_suppress_warning); res = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error); if (nm_utils_error_is_cancelled(error)) @@ -371,37 +386,70 @@ _dbus_connection_call_simple_cb(GObject *source, GAsyncResult *result, gpointer return; } - remote_error = g_dbus_error_get_remote_error(error); - if (!nm_streq0(remote_error, "fi.w1.wpa_supplicant1.NotConnected")) { - g_dbus_error_strip_remote_error(error); - _LOGW("call-%s: failed with %s", log_reason, error->message); - return; + if (!suppress_warning) { + remote_error = g_dbus_error_get_remote_error(error); + if (!nm_streq0(remote_error, "fi.w1.wpa_supplicant1.NotConnected")) { + g_dbus_error_strip_remote_error(error); + _LOGW("call-%s: failed with %s", log_reason, error->message); + return; + } } _LOGT("call-%s: failed with %s", log_reason, error->message); } static void -_dbus_connection_call_simple(NMSupplicantInterface *self, - const char * interface_name, - const char * method_name, - GVariant * parameters, - const GVariantType * reply_type, - const char * log_reason) +_dbus_connection_call_simple_full_impl(NMSupplicantInterface *self, + const char * interface_name, + const char * method_name, + GVariant * parameters, + const GVariantType * reply_type, + const char * log_reason, + gboolean suppress_warning) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self); - _dbus_connection_call(self, - interface_name, - method_name, - parameters, - reply_type, - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT_MSEC, - priv->main_cancellable, - _dbus_connection_call_simple_cb, - nm_utils_user_data_pack(self, log_reason)); -} + _dbus_connection_call( + self, + interface_name, + method_name, + parameters, + reply_type, + G_DBUS_CALL_FLAGS_NONE, + DBUS_TIMEOUT_MSEC, + priv->main_cancellable, + _dbus_connection_call_simple_cb, + nm_utils_user_data_pack(self, log_reason, GINT_TO_POINTER(suppress_warning))); +} + +#define _dbus_connection_call_simple_full(self, \ + interface_name, \ + method_name, \ + parameters, \ + reply_type, \ + log_reason, \ + suppress_warning) \ + _dbus_connection_call_simple_full_impl((self), \ + (interface_name), \ + (method_name), \ + (parameters), \ + (reply_type), \ + "" log_reason "", \ + (suppress_warning)) + +#define _dbus_connection_call_simple(self, \ + interface_name, \ + method_name, \ + parameters, \ + reply_type, \ + log_reason) \ + _dbus_connection_call_simple_full_impl((self), \ + (interface_name), \ + (method_name), \ + (parameters), \ + (reply_type), \ + "" log_reason "", \ + FALSE) /*****************************************************************************/ @@ -557,7 +605,7 @@ _bss_info_properties_changed(NMSupplicantInterface *self, guint16 v_u16; guint32 v_u32; NM80211ApFlags p_ap_flags; - NM80211Mode p_mode; + _NM80211Mode p_mode; guint8 p_signal_percent; const guint8 * arr_data; gsize arr_len; @@ -605,15 +653,15 @@ _bss_info_properties_changed(NMSupplicantInterface *self, if (nm_g_variant_lookup(properties, "Mode", "&s", &v_s)) { if (nm_streq(v_s, "infrastructure")) - p_mode = NM_802_11_MODE_INFRA; + p_mode = _NM_802_11_MODE_INFRA; else if (nm_streq(v_s, "ad-hoc")) - p_mode = NM_802_11_MODE_ADHOC; + p_mode = _NM_802_11_MODE_ADHOC; else if (nm_streq(v_s, "mesh")) - p_mode = NM_802_11_MODE_MESH; + p_mode = _NM_802_11_MODE_MESH; else - p_mode = NM_802_11_MODE_UNKNOWN; + p_mode = _NM_802_11_MODE_UNKNOWN; } else if (initial) - p_mode = NM_802_11_MODE_UNKNOWN; + p_mode = _NM_802_11_MODE_UNKNOWN; else p_mode = bss_info->mode; if (bss_info->mode != p_mode) { @@ -1619,11 +1667,10 @@ _wps_handle_set_pc_cb(GVariant *res, GError *error, gpointer user_data) * enroll with any BSS in range. */ if (!nm_utils_hwaddr_aton(wps_data->bssid, bssid_buf, sizeof(bssid_buf))) nm_assert_not_reached(); - g_variant_builder_add( - &start_args, - "{sv}", - "Bssid", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, bssid_buf, ETH_ALEN, sizeof(guint8))); + g_variant_builder_add(&start_args, + "{sv}", + "Bssid", + nm_g_variant_new_ay(bssid_buf, ETH_ALEN)); } wps_data->needs_cancelling = TRUE; @@ -1901,7 +1948,7 @@ _properties_changed_main(NMSupplicantInterface *self, GVariant *properties) if (nm_g_variant_lookup(properties, "CurrentBSS", "&o", &v_s)) { v_s = nm_dbus_path_not_empty(v_s); - if (!nm_ref_string_equals_str(priv->current_bss, v_s)) { + if (!nm_ref_string_equal_str(priv->current_bss, v_s)) { nm_ref_string_unref(priv->current_bss); priv->current_bss = nm_ref_string_new(v_s); do_notify_current_bss = TRUE; @@ -2721,12 +2768,13 @@ nm_supplicant_interface_p2p_cancel_connect(NMSupplicantInterface *self) { g_return_if_fail(NM_IS_SUPPLICANT_INTERFACE(self)); - _dbus_connection_call_simple(self, - NM_WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE, - "Cancel", - NULL, - G_VARIANT_TYPE("()"), - "p2p-cancel"); + _dbus_connection_call_simple_full(self, + NM_WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE, + "Cancel", + NULL, + G_VARIANT_TYPE("()"), + "p2p-cancel", + TRUE); } void diff --git a/src/core/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c index 7cf1a2bb..e432889b 100644 --- a/src/core/supplicant/nm-supplicant-manager.c +++ b/src/core/supplicant/nm-supplicant-manager.c @@ -8,13 +8,13 @@ #include "nm-supplicant-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" -#include "nm-glib-aux/nm-dbus-aux.h" -#include "nm-glib-aux/nm-ref-string.h" +#include "libnm-glib-aux/nm-dbus-aux.h" +#include "libnm-glib-aux/nm-ref-string.h" #include "nm-supplicant-interface.h" #include "nm-supplicant-types.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" /*****************************************************************************/ diff --git a/src/core/supplicant/nm-supplicant-settings-verify.c b/src/core/supplicant/nm-supplicant-settings-verify.c index 3f0a33e0..5e77b207 100644 --- a/src/core/supplicant/nm-supplicant-settings-verify.c +++ b/src/core/supplicant/nm-supplicant-settings-verify.c @@ -144,6 +144,7 @@ static const struct Opt opt_table[] = { OPT_BYTES("wep_key2", 0), OPT_BYTES("wep_key3", 0), OPT_INT("wep_tx_keyidx", 0, 3), + OPT_INT("wps_disabled", 0, 1), }; static gboolean diff --git a/src/core/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h index ae2db3f6..c9b72de1 100644 --- a/src/core/supplicant/nm-supplicant-types.h +++ b/src/core/supplicant/nm-supplicant-types.h @@ -7,6 +7,7 @@ #define __NETWORKMANAGER_SUPPLICANT_TYPES_H__ #include "c-list/src/c-list.h" +#include "libnm-base/nm-base.h" #define NM_WPAS_DBUS_SERVICE "fi.w1.wpa_supplicant1" #define NM_WPAS_DBUS_PATH "/fi/w1/wpa_supplicant1" @@ -50,9 +51,9 @@ typedef enum { _NM_SUPPL_CAP_TYPE_NUM, } NMSupplCapType; -#define NM_SUPPL_CAP_MASK_NO(type) ((NMSupplCapMask)(1llu << ((type) *2u))) -#define NM_SUPPL_CAP_MASK_YES(type) ((NMSupplCapMask)(2llu << ((type) *2u))) -#define NM_SUPPL_CAP_MASK_MASK(type) ((NMSupplCapMask)(3llu << ((type) *2u))) +#define NM_SUPPL_CAP_MASK_NO(type) ((NMSupplCapMask) (1llu << ((type) *2u))) +#define NM_SUPPL_CAP_MASK_YES(type) ((NMSupplCapMask) (2llu << ((type) *2u))) +#define NM_SUPPL_CAP_MASK_MASK(type) ((NMSupplCapMask) (3llu << ((type) *2u))) typedef enum { NM_SUPPL_CAP_MASK_NONE = 0, @@ -113,7 +114,7 @@ NM_SUPPL_CAP_MASK_GET(NMSupplCapMask features, NMSupplCapType type) nm_assert(NM_IN_SET(f, 0, 1, 2)); - return (NMTernary)(f - 1); + return (NMTernary) (f - 1); } static inline char @@ -178,7 +179,7 @@ typedef struct _NMSupplicantBssInfo { NM80211ApFlags ap_flags : 5; - NM80211Mode mode : 4; + _NM80211Mode mode : 4; bool bssid_valid : 1; diff --git a/src/core/supplicant/tests/test-supplicant-config.c b/src/core/supplicant/tests/test-supplicant-config.c index 99729c18..0cf35d0e 100644 --- a/src/core/supplicant/tests/test-supplicant-config.c +++ b/src/core/supplicant/tests/test-supplicant-config.c @@ -14,7 +14,7 @@ #include #include -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "supplicant/nm-supplicant-config.h" #include "supplicant/nm-supplicant-settings-verify.h" @@ -394,7 +394,17 @@ test_wifi_wpa_psk(const char * detail, NMTST_EXPECT_NM_INFO("Config: added 'scan_ssid' value '1'*"); NMTST_EXPECT_NM_INFO("Config: added 'bssid' value '11:22:33:44:55:66'*"); NMTST_EXPECT_NM_INFO("Config: added 'freq_list' value *"); - NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'"); + switch (pmf) { + case NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE: + case NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL: + NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value 'WPA-PSK WPA-PSK-SHA256'"); + break; + case NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: + NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value ' WPA-PSK-SHA256'"); + break; + default: + break; + } NMTST_EXPECT_NM_INFO("Config: added 'psk' value *"); NMTST_EXPECT_NM_INFO("Config: added 'proto' value 'WPA RSN'"); NMTST_EXPECT_NM_INFO("Config: added 'pairwise' value 'TKIP CCMP'"); @@ -421,11 +431,22 @@ test_wifi_wpa_psk(const char * detail, validate_opt(detail, config_dict, "scan_ssid", NM_SUPPL_OPT_TYPE_INT, GINT_TO_POINTER(1)); validate_opt(detail, config_dict, "ssid", NM_SUPPL_OPT_TYPE_BYTES, ssid); validate_opt(detail, config_dict, "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, bssid_str); - validate_opt(detail, - config_dict, - "key_mgmt", - NM_SUPPL_OPT_TYPE_KEYWORD, - "WPA-PSK WPA-PSK-SHA256"); + switch (pmf) { + case NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE: + case NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL: + validate_opt(detail, + config_dict, + "key_mgmt", + NM_SUPPL_OPT_TYPE_KEYWORD, + "WPA-PSK WPA-PSK-SHA256"); + break; + case NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: + validate_opt(detail, config_dict, "key_mgmt", NM_SUPPL_OPT_TYPE_KEYWORD, " WPA-PSK-SHA256"); + break; + default: + break; + } + validate_opt(detail, config_dict, "proto", NM_SUPPL_OPT_TYPE_KEYWORD, "WPA RSN"); validate_opt(detail, config_dict, "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, "TKIP CCMP"); validate_opt(detail, config_dict, "group", NM_SUPPL_OPT_TYPE_KEYWORD, "TKIP CCMP"); @@ -483,6 +504,7 @@ test_wifi_sae_psk(const char *psk) NMTST_EXPECT_NM_INFO("Config: added 'proto' value 'RSN'"); NMTST_EXPECT_NM_INFO("Config: added 'pairwise' value 'TKIP CCMP'"); NMTST_EXPECT_NM_INFO("Config: added 'group' value 'TKIP CCMP'"); + NMTST_EXPECT_NM_INFO("Config: added 'ieee80211w' value '2'"); config_dict = build_supplicant_config(connection, 1500, @@ -815,9 +837,10 @@ test_wifi_eap_suite_b_generation(void) NMTST_EXPECT_NM_INFO("Config: added 'scan_ssid' value '1'*"); NMTST_EXPECT_NM_INFO("Config: added 'bssid' value '11:22:33:44:55:66'*"); NMTST_EXPECT_NM_INFO("Config: added 'freq_list' value *"); + NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value 'WPA-EAP-SUITE-B-192'"); NMTST_EXPECT_NM_INFO("Config: added 'pairwise' value 'GCMP-256'"); NMTST_EXPECT_NM_INFO("Config: added 'group' value 'GCMP-256'"); - NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value 'WPA-EAP-SUITE-B-192'"); + NMTST_EXPECT_NM_INFO("Config: added 'ieee80211w' value '2'"); NMTST_EXPECT_NM_INFO("Config: added 'eap' value 'TLS'"); NMTST_EXPECT_NM_INFO("Config: added 'fragment_size' value '1086'"); NMTST_EXPECT_NM_INFO("Config: added 'ca_cert' value '*/test-ca-cert.pem'"); diff --git a/src/core/systemd/meson.build b/src/core/systemd/meson.build deleted file mode 100644 index 70f6b542..00000000 --- a/src/core/systemd/meson.build +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -incs = include_directories( - 'sd-adapt-core', - 'src/libsystemd-network', - 'src/libsystemd/sd-event', - 'src/systemd', -) - -libnm_systemd_core = static_library( - 'nm-systemd-core', - sources: files( - 'src/libsystemd-network/arp-util.c', - 'src/libsystemd-network/dhcp-identifier.c', - 'src/libsystemd-network/dhcp-network.c', - 'src/libsystemd-network/dhcp-option.c', - 'src/libsystemd-network/dhcp-packet.c', - 'src/libsystemd-network/dhcp6-network.c', - 'src/libsystemd-network/dhcp6-option.c', - 'src/libsystemd-network/lldp-neighbor.c', - 'src/libsystemd-network/lldp-network.c', - 'src/libsystemd-network/network-internal.c', - 'src/libsystemd-network/sd-dhcp-client.c', - 'src/libsystemd-network/sd-dhcp-lease.c', - 'src/libsystemd-network/sd-dhcp6-client.c', - 'src/libsystemd-network/sd-dhcp6-lease.c', - 'src/libsystemd-network/sd-ipv4acd.c', - 'src/libsystemd-network/sd-ipv4ll.c', - 'src/libsystemd-network/sd-lldp.c', - 'src/libsystemd/sd-event/event-util.c', - 'src/libsystemd/sd-event/sd-event.c', - 'src/libsystemd/sd-id128/id128-util.c', - 'src/libsystemd/sd-id128/sd-id128.c', - 'nm-sd.c', - 'nm-sd-utils-core.c', - 'nm-sd-utils-dhcp.c', - 'sd-adapt-core/nm-sd-adapt-core.c', - ), - include_directories: [ - incs, - src_inc, - ], - dependencies: [ - glib_nm_default_dep, - libnm_core_dep, - libnm_systemd_shared_dep, - ], - c_args: [ - '-DG_LOG_DOMAIN="NetworkManager"', - ], - link_with: libc_siphash, -) - -libnm_systemd_core_dep = declare_dependency( - include_directories: incs, - dependencies: [ - glib_dep, - libnm_core_dep, - libnm_systemd_shared_dep, - ], - link_with: libnm_systemd_core, -) diff --git a/src/core/systemd/nm-default-systemd.h b/src/core/systemd/nm-default-systemd.h deleted file mode 100644 index 1979d9c9..00000000 --- a/src/core/systemd/nm-default-systemd.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_DEFAULT_SYSTEMD_H__ -#define __NM_DEFAULT_SYSTEMD_H__ - -/*****************************************************************************/ - -#include "nm-default-daemon.h" - -#undef NETWORKMANAGER_COMPILATION -#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_SYSTEMD - -/*****************************************************************************/ - -#endif /* __NM_DEFAULT_SYSTEMD_H__ */ diff --git a/src/core/systemd/nm-sd-utils-core.c b/src/core/systemd/nm-sd-utils-core.c deleted file mode 100644 index af68603e..00000000 --- a/src/core/systemd/nm-sd-utils-core.c +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "src/core/systemd/nm-default-systemd.h" - -#include "nm-sd-utils-core.h" - -#include "nm-core-internal.h" - -#include "nm-sd-adapt-core.h" - -#include "sd-id128.h" - -/*****************************************************************************/ - -NMUuid * -nm_sd_utils_id128_get_machine(NMUuid *out_uuid) -{ - g_assert(out_uuid); - - G_STATIC_ASSERT_EXPR(sizeof(*out_uuid) == sizeof(sd_id128_t)); - if (sd_id128_get_machine((sd_id128_t *) out_uuid) < 0) - return NULL; - return out_uuid; -} diff --git a/src/core/systemd/nm-sd-utils-core.h b/src/core/systemd/nm-sd-utils-core.h deleted file mode 100644 index ccad0029..00000000 --- a/src/core/systemd/nm-sd-utils-core.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef __NM_SD_UTILS_CORE_H__ -#define __NM_SD_UTILS_CORE_H__ - -/*****************************************************************************/ - -struct _NMUuid; - -struct _NMUuid *nm_sd_utils_id128_get_machine(struct _NMUuid *out_uuid); - -/*****************************************************************************/ - -#endif /* __NM_SD_UTILS_CORE_H__ */ diff --git a/src/core/systemd/nm-sd-utils-dhcp.c b/src/core/systemd/nm-sd-utils-dhcp.c deleted file mode 100644 index b5aa315a..00000000 --- a/src/core/systemd/nm-sd-utils-dhcp.c +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#include "src/core/systemd/nm-default-systemd.h" - -#include "nm-sd-utils-dhcp.h" - -#include "sd-adapt-core/nm-sd-adapt-core.h" -#include "src/libsystemd-network/dhcp-lease-internal.h" - -int -nm_sd_dhcp_lease_get_private_options(sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options) -{ - struct sd_dhcp_raw_option *raw_option; - int cnt = 0; - - g_return_val_if_fail(lease, -EINVAL); - g_return_val_if_fail(out_options, -EINVAL); - g_return_val_if_fail(*out_options == NULL, -EINVAL); - - if (lease->private_options == NULL) - return -ENODATA; - - LIST_FOREACH(options, raw_option, lease->private_options) - cnt++; - - *out_options = g_new(nm_sd_dhcp_option, cnt); - cnt = 0; - - LIST_FOREACH(options, raw_option, lease->private_options) - { - (*out_options)[cnt].code = raw_option->tag; - (*out_options)[cnt].data = raw_option->data; - (*out_options)[cnt].data_len = raw_option->length; - cnt++; - } - - return cnt; -} diff --git a/src/core/systemd/nm-sd-utils-dhcp.h b/src/core/systemd/nm-sd-utils-dhcp.h deleted file mode 100644 index 5d126d5b..00000000 --- a/src/core/systemd/nm-sd-utils-dhcp.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ -#define __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ - -#include "nm-sd.h" - -typedef struct { - uint8_t code; - uint8_t data_len; - void * data; -} nm_sd_dhcp_option; - -int nm_sd_dhcp_lease_get_private_options(sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options); - -#endif /* __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ */ diff --git a/src/core/systemd/nm-sd.c b/src/core/systemd/nm-sd.c deleted file mode 100644 index 11f3abbd..00000000 --- a/src/core/systemd/nm-sd.c +++ /dev/null @@ -1,113 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2014 - 2016 Red Hat, Inc. - */ - -#include "src/core/systemd/nm-default-systemd.h" - -#include "nm-sd.h" - -#include "sd-event.h" - -/***************************************************************************** - * Integrating sd_event into glib. Taken and adjusted from - * https://www.freedesktop.org/software/systemd/man/sd_event_get_fd.html - *****************************************************************************/ - -typedef struct SDEventSource { - GSource source; - GPollFD pollfd; - sd_event *event; -} SDEventSource; - -static gboolean -event_prepare(GSource *source, int *timeout_) -{ - return sd_event_prepare(((SDEventSource *) source)->event) > 0; -} - -static gboolean -event_check(GSource *source) -{ - return sd_event_wait(((SDEventSource *) source)->event, 0) > 0; -} - -static gboolean -event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) -{ - return sd_event_dispatch(((SDEventSource *) source)->event) > 0; -} - -static void -event_finalize(GSource *source) -{ - SDEventSource *s = (SDEventSource *) source; - - sd_event_unref(s->event); -} - -static SDEventSource * -event_create_source(sd_event *event) -{ - static const GSourceFuncs event_funcs = { - .prepare = event_prepare, - .check = event_check, - .dispatch = event_dispatch, - .finalize = event_finalize, - }; - SDEventSource *source; - gboolean is_default_event = FALSE; - int r; - - if (!event) { - is_default_event = TRUE; - r = sd_event_default(&event); - if (r < 0) - g_return_val_if_reached(NULL); - } - - source = (SDEventSource *) g_source_new((GSourceFuncs *) &event_funcs, sizeof(SDEventSource)); - - source->event = is_default_event ? g_steal_pointer(&event) : sd_event_ref(event); - - source->pollfd = (GPollFD){ - .fd = sd_event_get_fd(source->event), - .events = G_IO_IN | G_IO_HUP | G_IO_ERR, - }; - - g_source_add_poll(&source->source, &source->pollfd); - - return source; -} - -static guint -event_attach(sd_event *event, GMainContext *context) -{ - SDEventSource *source; - guint id; - - source = event_create_source(event); - - g_return_val_if_fail(source, 0); - - id = g_source_attach((GSource *) source, context); - g_source_unref((GSource *) source); - - nm_assert(id != 0); - return id; -} - -guint -nm_sd_event_attach_default(void) -{ - return event_attach(NULL, NULL); -} - -/*****************************************************************************/ - -/* ensure that defines in nm-sd.h correspond to the internal defines. */ - -#include "nm-sd-adapt-core.h" -#include "dhcp-lease-internal.h" - -/*****************************************************************************/ diff --git a/src/core/systemd/nm-sd.h b/src/core/systemd/nm-sd.h deleted file mode 100644 index 0ea4be22..00000000 --- a/src/core/systemd/nm-sd.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2014 - 2016 Red Hat, Inc. - */ - -#ifndef __NM_SD_H__ -#define __NM_SD_H__ - -#include "systemd/src/systemd/sd-dhcp-client.h" -#include "systemd/src/systemd/sd-dhcp6-client.h" -#include "systemd/src/systemd/sd-lldp.h" -#include "systemd/src/systemd/sd-ipv4ll.h" - -/*****************************************************************************/ - -guint nm_sd_event_attach_default(void); - -/***************************************************************************** - * expose internal systemd API - * - * FIXME: don't use any internal systemd API. - *****************************************************************************/ - -struct sd_dhcp_lease; - -int dhcp_lease_save(struct sd_dhcp_lease *lease, const char *lease_file); -int dhcp_lease_load(struct sd_dhcp_lease **ret, const char *lease_file); - -#endif /* __NM_SD_H__ */ diff --git a/src/core/systemd/sd-adapt-core/condition.h b/src/core/systemd/sd-adapt-core/condition.h deleted file mode 100644 index d3a6812a..00000000 --- a/src/core/systemd/sd-adapt-core/condition.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -/* dummy header */ - -typedef struct _sd_adapt_Condition Condition; diff --git a/src/core/systemd/sd-adapt-core/conf-parser.h b/src/core/systemd/sd-adapt-core/conf-parser.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/conf-parser.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/sd-adapt-core/device-util.h b/src/core/systemd/sd-adapt-core/device-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/device-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/sd-adapt-core/khash.h b/src/core/systemd/sd-adapt-core/khash.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/khash.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/sd-adapt-core/network-util.h b/src/core/systemd/sd-adapt-core/network-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/network-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c b/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c deleted file mode 100644 index 9339b33d..00000000 --- a/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2014 - 2016 Red Hat, Inc. - */ - -#include "src/core/systemd/nm-default-systemd.h" - -#include "nm-sd-adapt-core.h" - -#include "fd-util.h" - -/*****************************************************************************/ - -int -asynchronous_close(int fd) -{ - safe_close(fd); - return -1; -} - -/*****************************************************************************/ diff --git a/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h b/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h deleted file mode 100644 index f627d7d4..00000000 --- a/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2014 - 2018 Red Hat, Inc. - */ - -#ifndef __NM_SD_ADAPT_CORE_H__ -#define __NM_SD_ADAPT_CORE_H__ - -#include "src/core/systemd/nm-default-systemd.h" - -#include -#include -#include - -#undef NETWORKMANAGER_COMPILATION -#include "systemd/sd-adapt-shared/nm-sd-adapt-shared.h" -#undef NETWORKMANAGER_COMPILATION -#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_SYSTEMD - -#ifndef HAVE_SYS_AUXV_H - #define HAVE_SYS_AUXV_H 0 -#endif - -/***************************************************************************** - * The remainder of the header is only enabled when building the systemd code - * itself. - *****************************************************************************/ - -#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_SYSTEMD - - #include - #include - #include - #include - #include - #ifdef HAVE_SYS_AUXV_H - #include - #endif - #include - #include - #include - - /* Missing in Linux 3.2.0, in Ubuntu 12.04 */ - #ifndef BPF_XOR - #define BPF_XOR 0xa0 - #endif - - #ifndef ETHERTYPE_LLDP - #define ETHERTYPE_LLDP 0x88cc - #endif - - #ifndef HAVE_SECURE_GETENV - #ifdef HAVE___SECURE_GETENV - #define secure_getenv __secure_getenv - #else - #error neither secure_getenv nor __secure_getenv is available - #endif - #endif - -/*****************************************************************************/ - -static inline int -sd_notify(int unset_environment, const char *state) -{ - return 0; -} - - /* Can't include both net/if.h and linux/if.h; so have to define this here */ - #ifndef IF_NAMESIZE - #define IF_NAMESIZE 16 - #endif - - #ifndef IFNAMSIZ - #define IFNAMSIZ IF_NAMESIZE - #endif - - #ifndef MAX_HANDLE_SZ - #define MAX_HANDLE_SZ 128 - #endif - - #include "sd-id128.h" - #include "sparse-endian.h" - #include "async.h" - #include "util.h" - -#endif /* (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_SYSTEMD */ - -#endif /* __NM_SD_ADAPT_CORE_H__ */ diff --git a/src/core/systemd/sd-adapt-core/sd-daemon.h b/src/core/systemd/sd-adapt-core/sd-daemon.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/sd-daemon.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/sd-adapt-core/sd-device.h b/src/core/systemd/sd-adapt-core/sd-device.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/sd-device.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/sd-adapt-core/udev-util.h b/src/core/systemd/sd-adapt-core/udev-util.h deleted file mode 100644 index 637892c2..00000000 --- a/src/core/systemd/sd-adapt-core/udev-util.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -/* dummy header */ diff --git a/src/core/systemd/src/libsystemd-network/arp-util.c b/src/core/systemd/src/libsystemd-network/arp-util.c deleted file mode 100644 index 1c777d8a..00000000 --- a/src/core/systemd/src/libsystemd-network/arp-util.c +++ /dev/null @@ -1,140 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "arp-util.h" -#include "fd-util.h" -#include "unaligned.h" -#include "util.h" - -int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_addr *eth_mac) { - struct sock_filter filter[] = { - BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ - BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0), /* packet >= arp packet ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hrd)), /* A <- header */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0), /* header == ethernet ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pro)), /* A <- protocol */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0), /* protocol == IP ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hln)), /* A <- hardware address length */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct ether_addr), 1, 0), /* length == sizeof(ether_addr)? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pln)), /* A <- protocol address length */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct in_addr), 1, 0), /* length == sizeof(in_addr) ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_op)), /* A <- operation */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0), /* protocol == request ? */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), /* protocol == reply ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - /* Sender Hardware Address must be different from our own */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])),/* A <- 4 bytes of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)), /* A <- 4 bytes of SHA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 6), /* A == 0 ? */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])),/* A <- remainder of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4), /* A <- remainder of SHA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about */ - BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_spa)), /* A <- SPA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ - BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_tpa)), /* A <- TPA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - }; - struct sock_fprog fprog = { - .len = ELEMENTSOF(filter), - .filter = (struct sock_filter*) filter - }; - union sockaddr_union link = { - .ll.sll_family = AF_PACKET, - .ll.sll_protocol = htobe16(ETH_P_ARP), - .ll.sll_ifindex = ifindex, - .ll.sll_halen = ETH_ALEN, - .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - }; - _cleanup_close_ int s = -1; - int r; - - assert(ifindex > 0); - - s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (s < 0) - return -errno; - - r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); - if (r < 0) - return -errno; - - r = bind(s, &link.sa, sizeof(link.ll)); - if (r < 0) - return -errno; - - return TAKE_FD(s); -} - -static int arp_send_packet(int fd, int ifindex, - be32_t pa, const struct ether_addr *ha, - bool announce) { - union sockaddr_union link = { - .ll.sll_family = AF_PACKET, - .ll.sll_protocol = htobe16(ETH_P_ARP), - .ll.sll_ifindex = ifindex, - .ll.sll_halen = ETH_ALEN, - .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - }; - struct ether_arp arp = { - .ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER), /* HTYPE */ - .ea_hdr.ar_pro = htobe16(ETHERTYPE_IP), /* PTYPE */ - .ea_hdr.ar_hln = ETH_ALEN, /* HLEN */ - .ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */ - .ea_hdr.ar_op = htobe16(ARPOP_REQUEST), /* REQUEST */ - }; - int r; - - assert(fd >= 0); - assert(pa != 0); - assert(ha); - - memcpy(&arp.arp_sha, ha, ETH_ALEN); - memcpy(&arp.arp_tpa, &pa, sizeof(pa)); - - if (announce) - memcpy(&arp.arp_spa, &pa, sizeof(pa)); - - r = sendto(fd, &arp, sizeof(struct ether_arp), 0, &link.sa, sizeof(link.ll)); - if (r < 0) - return -errno; - - return 0; -} - -int arp_send_probe(int fd, int ifindex, - be32_t pa, const struct ether_addr *ha) { - return arp_send_packet(fd, ifindex, pa, ha, false); -} - -int arp_send_announcement(int fd, int ifindex, - be32_t pa, const struct ether_addr *ha) { - return arp_send_packet(fd, ifindex, pa, ha, true); -} diff --git a/src/core/systemd/src/libsystemd-network/arp-util.h b/src/core/systemd/src/libsystemd-network/arp-util.h deleted file mode 100644 index 2dac8cfb..00000000 --- a/src/core/systemd/src/libsystemd-network/arp-util.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. -***/ - -#include - -#include "socket-util.h" -#include "sparse-endian.h" - -int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac); - -int arp_send_probe(int fd, int ifindex, - be32_t pa, const struct ether_addr *ha); -int arp_send_announcement(int fd, int ifindex, - be32_t pa, const struct ether_addr *ha); diff --git a/src/core/systemd/src/libsystemd-network/dhcp-identifier.c b/src/core/systemd/src/libsystemd-network/dhcp-identifier.c deleted file mode 100644 index 0720e381..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-identifier.c +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "sd-device.h" -#include "sd-id128.h" - -#include "dhcp-identifier.h" -#include "dhcp6-protocol.h" -#include "network-util.h" -#include "siphash24.h" -#include "sparse-endian.h" -#include "stdio-util.h" -#include "udev-util.h" -#include "virt.h" - -#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) -#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03) -#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */ - -int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) { - struct duid d; - - assert_cc(sizeof(d.raw) >= MAX_DUID_LEN); - if (duid_len > MAX_DUID_LEN) - return -EINVAL; - - if (!strict) - /* Strict validation is not requested. We only ensure that the - * DUID is not too long. */ - return 0; - - switch (duid_type) { - case DUID_TYPE_LLT: - if (duid_len <= sizeof(d.llt)) - return -EINVAL; - break; - case DUID_TYPE_EN: - if (duid_len != sizeof(d.en)) - return -EINVAL; - break; - case DUID_TYPE_LL: - if (duid_len <= sizeof(d.ll)) - return -EINVAL; - break; - case DUID_TYPE_UUID: - if (duid_len != sizeof(d.uuid)) - return -EINVAL; - break; - default: - /* accept unknown type in order to be forward compatible */ - break; - } - return 0; -} - -#if 0 /* NM_IGNORED */ -int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { - uint16_t time_from_2000y; - - assert(duid); - assert(len); - assert(addr); - - if (arp_type == ARPHRD_ETHER) - assert_return(addr_len == ETH_ALEN, -EINVAL); - else if (arp_type == ARPHRD_INFINIBAND) - assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); - else - return -EINVAL; - - if (t < USEC_2000) - time_from_2000y = 0; - else - time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff); - - unaligned_write_be16(&duid->type, DUID_TYPE_LLT); - unaligned_write_be16(&duid->llt.htype, arp_type); - unaligned_write_be32(&duid->llt.time, time_from_2000y); - memcpy(duid->llt.haddr, addr, addr_len); - - *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len; - - return 0; -} - -int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { - assert(duid); - assert(len); - assert(addr); - - if (arp_type == ARPHRD_ETHER) - assert_return(addr_len == ETH_ALEN, -EINVAL); - else if (arp_type == ARPHRD_INFINIBAND) - assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); - else - return -EINVAL; - - unaligned_write_be16(&duid->type, DUID_TYPE_LL); - unaligned_write_be16(&duid->ll.htype, arp_type); - memcpy(duid->ll.haddr, addr, addr_len); - - *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len; - - return 0; -} -#endif /* NM_IGNORED */ - -int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { - sd_id128_t machine_id; - uint64_t hash; - int r; - - assert(duid); - assert(len); - - r = sd_id128_get_machine(&machine_id); - if (r < 0) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - machine_id = SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10); -#else - return r; -#endif - } - - unaligned_write_be16(&duid->type, DUID_TYPE_EN); - unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN); - - *len = sizeof(duid->type) + sizeof(duid->en); - - /* a bit of snake-oil perhaps, but no need to expose the machine-id - * directly; duid->en.id might not be aligned, so we need to copy */ - hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes)); - memcpy(duid->en.id, &hash, sizeof(duid->en.id)); - - return 0; -} - -#if 0 /* NM_IGNORED */ -int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) { - sd_id128_t machine_id; - int r; - - assert(duid); - assert(len); - - r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id); - if (r < 0) - return r; - - unaligned_write_be16(&duid->type, DUID_TYPE_UUID); - memcpy(&duid->raw.data, &machine_id, sizeof(machine_id)); - - *len = sizeof(duid->type) + sizeof(machine_id); - - return 0; -} -#endif - -int dhcp_identifier_set_iaid( - int ifindex, - const uint8_t *mac, - size_t mac_len, - bool legacy_unstable_byteorder, - void *_id) { -#if 0 /* NM_IGNORED */ - /* name is a pointer to memory in the sd_device struct, so must - * have the same scope */ - _cleanup_(sd_device_unrefp) sd_device *device = NULL; - const char *name = NULL; - uint64_t id; - uint32_t id32; - - if (detect_container() <= 0) { - /* not in a container, udev will be around */ - char ifindex_str[1 + DECIMAL_STR_MAX(int)]; - int r; - - xsprintf(ifindex_str, "n%d", ifindex); - if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) { - r = sd_device_get_is_initialized(device); - if (r < 0) - return r; - if (r == 0) - /* not yet ready */ - return -EBUSY; - - r = device_is_renaming(device); - if (r < 0) - return r; - if (r > 0) - /* device is under renaming */ - return -EBUSY; - - name = net_get_name_persistent(device); - } - } - - if (name) - id = siphash24(name, strlen(name), HASH_KEY.bytes); - else - /* fall back to MAC address if no predictable name available */ - id = siphash24(mac, mac_len, HASH_KEY.bytes); - - id32 = (id & 0xffffffff) ^ (id >> 32); - - if (legacy_unstable_byteorder) - /* for historical reasons (a bug), the bits were swapped and thus - * the result was endianness dependent. Preserve that behavior. */ - id32 = __bswap_32(id32); - else - /* the fixed behavior returns a stable byte order. Since LE is expected - * to be more common, swap the bytes on LE to give the same as legacy - * behavior. */ - id32 = be32toh(id32); - - unaligned_write_ne32(_id, id32); - return 0; -#else /* NM_IGNORED */ - /* for NetworkManager, we don't use this function and we should never call here. - * This got replaced by nm_utils_create_dhcp_iaid(). */ - g_return_val_if_reached (-EINVAL); -#endif /* NM_IGNORED */ -} diff --git a/src/core/systemd/src/libsystemd-network/dhcp-identifier.h b/src/core/systemd/src/libsystemd-network/dhcp-identifier.h deleted file mode 100644 index e9f2ea7e..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-identifier.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "sd-id128.h" - -#include "macro.h" -#include "sparse-endian.h" -#include "time-util.h" -#include "unaligned.h" - -#define SYSTEMD_PEN 43793 - -typedef enum DUIDType { - DUID_TYPE_LLT = 1, - DUID_TYPE_EN = 2, - DUID_TYPE_LL = 3, - DUID_TYPE_UUID = 4, - _DUID_TYPE_MAX, - _DUID_TYPE_INVALID = -1, -} DUIDType; - -/* RFC 3315 section 9.1: - * A DUID can be no more than 128 octets long (not including the type code). - */ -#define MAX_DUID_LEN 128 - -/* https://tools.ietf.org/html/rfc3315#section-9.1 */ -struct duid { - be16_t type; - union { - struct { - /* DUID_TYPE_LLT */ - be16_t htype; - be32_t time; - uint8_t haddr[0]; - } _packed_ llt; - struct { - /* DUID_TYPE_EN */ - be32_t pen; - uint8_t id[8]; - } _packed_ en; - struct { - /* DUID_TYPE_LL */ - be16_t htype; - uint8_t haddr[0]; - } _packed_ ll; - struct { - /* DUID_TYPE_UUID */ - sd_id128_t uuid; - } _packed_ uuid; - struct { - uint8_t data[MAX_DUID_LEN]; - } _packed_ raw; - }; -} _packed_; - -int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict); -int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); -int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); -int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); -int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len); -int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id); diff --git a/src/core/systemd/src/libsystemd-network/dhcp-internal.h b/src/core/systemd/src/libsystemd-network/dhcp-internal.h deleted file mode 100644 index 40e6b1f2..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-internal.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include -#include -#include - -#include "sd-dhcp-client.h" - -#include "dhcp-protocol.h" -#include "socket-util.h" - -typedef struct sd_dhcp_option { - unsigned n_ref; - - uint8_t option; - void *data; - size_t length; -} sd_dhcp_option; - -typedef struct DHCPServerData { - struct in_addr *addr; - size_t size; -} DHCPServerData; - -extern const struct hash_ops dhcp_option_hash_ops; - -int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, - const uint8_t *mac_addr, size_t mac_addr_len, - const uint8_t *bcast_addr, size_t bcast_addr_len, - uint16_t arp_type, uint16_t port); -int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type); -int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, - const void *packet, size_t len); -int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, - const void *packet, size_t len); - -int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, - uint8_t code, size_t optlen, const void *optval); - -typedef int (*dhcp_option_callback_t)(uint8_t code, uint8_t len, - const void *option, void *userdata); - -int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **error_message); - -int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, - uint8_t type, uint16_t arp_type, size_t optlen, - size_t *optoffset); - -uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len); - -void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, - uint16_t source, be32_t destination_addr, - uint16_t destination, uint16_t len, int ip_service_type); - -int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port); - -/* If we are invoking callbacks of a dhcp-client, ensure unreffing the - * client from the callback doesn't destroy the object we are working - * on */ -#define DHCP_CLIENT_DONT_DESTROY(client) \ - _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client) - -#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) -#define log_dhcp_client(client, fmt, ...) log_dhcp_client_errno(client, 0, fmt, ##__VA_ARGS__) diff --git a/src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h deleted file mode 100644 index 49392d1b..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include "sd-dhcp-client.h" - -#include "dhcp-internal.h" -#include "dhcp-protocol.h" -#include "list.h" -#include "util.h" - -struct sd_dhcp_route { - struct in_addr dst_addr; - struct in_addr gw_addr; - unsigned char dst_prefixlen; - - uint8_t option; -}; - -struct sd_dhcp_raw_option { - LIST_FIELDS(struct sd_dhcp_raw_option, options); - - uint8_t tag; - uint8_t length; - void *data; -}; - -struct sd_dhcp_lease { - unsigned n_ref; - - /* each 0 if unset */ - uint32_t t1; - uint32_t t2; - uint32_t lifetime; - - /* each 0 if unset */ - be32_t address; - be32_t server_address; - be32_t next_server; - - bool have_subnet_mask; - be32_t subnet_mask; - - bool have_broadcast; - be32_t broadcast; - - struct in_addr *router; - size_t router_size; - - DHCPServerData servers[_SD_DHCP_LEASE_SERVER_TYPE_MAX]; - - struct sd_dhcp_route *static_route; - size_t static_route_size, static_route_allocated; - - uint16_t mtu; /* 0 if unset */ - - char *domainname; - char **search_domains; - char *hostname; - char *root_path; - - void *client_id; - size_t client_id_len; - - void *vendor_specific; - size_t vendor_specific_len; - - char *timezone; - - LIST_HEAD(struct sd_dhcp_raw_option, private_options); -}; - -int dhcp_lease_new(sd_dhcp_lease **ret); - -int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata); -int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains); -int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len); - -int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease); - -int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len); diff --git a/src/core/systemd/src/libsystemd-network/dhcp-network.c b/src/core/systemd/src/libsystemd-network/dhcp-network.c deleted file mode 100644 index 4477f46f..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-network.c +++ /dev/null @@ -1,246 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dhcp-internal.h" -#include "fd-util.h" -#include "socket-util.h" -#include "unaligned.h" - -static int _bind_raw_socket(int ifindex, union sockaddr_union *link, - uint32_t xid, - const uint8_t *bcast_addr, - size_t bcast_addr_len, - const struct ether_addr *eth_mac, - uint16_t arp_type, uint8_t dhcp_hlen, - uint16_t port) { - struct sock_filter filter[] = { - BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ - BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), /* packet >= DHCPPacket ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.protocol)), /* A <- IP protocol */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0), /* IP protocol == UDP ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags */ - BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x20), /* A <- A & 0x20 (More Fragments bit) */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags + Fragment offset */ - BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x1fff), /* A <- A & 0x1fff (Fragment offset) */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, udp.dest)), /* A <- UDP destination port */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, port, 1, 0), /* UDP destination port == DHCP client port ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.op)), /* A <- DHCP op */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0), /* op == BOOTREPLY ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)), /* A <- DHCP header type */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0), /* header type == arp_type ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)), /* A <- client identifier */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), /* client identifier == xid ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)), /* A <- MAC address length */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0), /* address length == dhcp_hlen ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - - /* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally - * compare chaddr for ETH_ALEN bytes. */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 12), /* A (the MAC address length) == ETH_ALEN ? */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* A <- 4 bytes of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* A <- remainder of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */ - BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ - }; - struct sock_fprog fprog = { - .len = ELEMENTSOF(filter), - .filter = filter - }; - _cleanup_close_ int s = -1; - int r; - - assert(ifindex > 0); - assert(link); - - s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (s < 0) - return -errno; - - r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true); - if (r < 0) - return r; - - r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); - if (r < 0) - return -errno; - - link->ll = (struct sockaddr_ll) { - .sll_family = AF_PACKET, - .sll_protocol = htobe16(ETH_P_IP), - .sll_ifindex = ifindex, - .sll_hatype = htobe16(arp_type), - .sll_halen = bcast_addr_len, - }; - memcpy(link->ll.sll_addr, bcast_addr, bcast_addr_len); /* We may overflow link->ll. link->ll_buffer ensures we have enough space. */ - - r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll)); - if (r < 0) - return -errno; - - return TAKE_FD(s); -} - -int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, - const uint8_t *mac_addr, size_t mac_addr_len, - const uint8_t *bcast_addr, size_t bcast_addr_len, - uint16_t arp_type, uint16_t port) { - static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - /* Default broadcast address for IPoIB */ - static const uint8_t ib_bcast[] = { - 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff - }; - struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } }; - const uint8_t *default_bcast_addr; - size_t expected_bcast_addr_len; - uint8_t dhcp_hlen = 0; - - if (arp_type == ARPHRD_ETHER) { - assert_return(mac_addr_len == ETH_ALEN, -EINVAL); - memcpy(ð_mac, mac_addr, ETH_ALEN); - dhcp_hlen = ETH_ALEN; - - default_bcast_addr = eth_bcast; - expected_bcast_addr_len = ETH_ALEN; - } else if (arp_type == ARPHRD_INFINIBAND) { - default_bcast_addr = ib_bcast; - expected_bcast_addr_len = INFINIBAND_ALEN; - } else - return -EINVAL; - - if (bcast_addr && bcast_addr_len > 0) - assert_return(bcast_addr_len == expected_bcast_addr_len, -EINVAL); - else { - bcast_addr = default_bcast_addr; - bcast_addr_len = expected_bcast_addr_len; - } - - return _bind_raw_socket(ifindex, link, xid, bcast_addr, bcast_addr_len, - ð_mac, arp_type, dhcp_hlen, port); -} - -int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) { - union sockaddr_union src = { - .in.sin_family = AF_INET, - .in.sin_port = htobe16(port), - .in.sin_addr.s_addr = address, - }; - _cleanup_close_ int s = -1; - int r; - - s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (s < 0) - return -errno; - - if (ip_service_type >= 0) - r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type); - else - r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6); - - if (r < 0) - return r; - - r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); - if (r < 0) - return r; - - if (ifindex > 0) { - r = socket_bind_to_ifindex(s, ifindex); - if (r < 0) - return r; - } - - if (address == INADDR_ANY) { - r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true); - if (r < 0) - return r; - - r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true); - if (r < 0) - return r; - - } else { - r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true); - if (r < 0) - return r; - } - - r = bind(s, &src.sa, sizeof(src.in)); - if (r < 0) - return -errno; - - return TAKE_FD(s); -} - -int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, - const void *packet, size_t len) { - int r; - - assert(link); - assert(packet); - assert(len); - - r = sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)); - if (r < 0) - return -errno; - - return 0; -} - -int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, - const void *packet, size_t len) { - union sockaddr_union dest = { - .in.sin_family = AF_INET, - .in.sin_port = htobe16(port), - .in.sin_addr.s_addr = address, - }; - int r; - - assert(s >= 0); - assert(packet); - assert(len); - - r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)); - if (r < 0) - return -errno; - - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/dhcp-option.c b/src/core/systemd/src/libsystemd-network/dhcp-option.c deleted file mode 100644 index 2c15d85a..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-option.c +++ /dev/null @@ -1,358 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "alloc-util.h" -#include "dhcp-internal.h" -#include "dhcp-server-internal.h" -#include "memory-util.h" -#include "strv.h" -#include "utf8.h" - -static int option_append(uint8_t options[], size_t size, size_t *offset, - uint8_t code, size_t optlen, const void *optval) { - assert(options); - assert(offset); - - if (code != SD_DHCP_OPTION_END) - /* always make sure there is space for an END option */ - size--; - - switch (code) { - - case SD_DHCP_OPTION_PAD: - case SD_DHCP_OPTION_END: - if (*offset + 1 > size) - return -ENOBUFS; - - options[*offset] = code; - *offset += 1; - break; - - case SD_DHCP_OPTION_USER_CLASS: { - size_t total = 0; - char **s; - - STRV_FOREACH(s, (char **) optval) { - size_t len = strlen(*s); - - if (len > 255) - return -ENAMETOOLONG; - - total += 1 + len; - } - - if (*offset + 2 + total > size) - return -ENOBUFS; - - options[*offset] = code; - options[*offset + 1] = total; - *offset += 2; - - STRV_FOREACH(s, (char **) optval) { - size_t len = strlen(*s); - - options[*offset] = len; - - memcpy(&options[*offset + 1], *s, len); - *offset += 1 + len; - } - - break; - } - case SD_DHCP_OPTION_SIP_SERVER: - if (*offset + 3 + optlen > size) - return -ENOBUFS; - - options[*offset] = code; - options[*offset + 1] = optlen + 1; - options[*offset + 2] = 1; - - memcpy_safe(&options[*offset + 3], optval, optlen); - *offset += 3 + optlen; - - break; - case SD_DHCP_OPTION_VENDOR_SPECIFIC: { - OrderedHashmap *s = (OrderedHashmap *) optval; - struct sd_dhcp_option *p; - size_t l = 0; - - ORDERED_HASHMAP_FOREACH(p, s) - l += p->length + 2; - - if (*offset + l + 2 > size) - return -ENOBUFS; - - options[*offset] = code; - options[*offset + 1] = l; - - *offset += 2; - - ORDERED_HASHMAP_FOREACH(p, s) { - options[*offset] = p->option; - options[*offset + 1] = p->length; - memcpy(&options[*offset + 2], p->data, p->length); - *offset += 2 + p->length; - } - - break; - } - default: - if (*offset + 2 + optlen > size) - return -ENOBUFS; - - options[*offset] = code; - options[*offset + 1] = optlen; - - memcpy_safe(&options[*offset + 2], optval, optlen); - *offset += 2 + optlen; - - break; - } - - return 0; -} - -int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, - uint8_t overload, - uint8_t code, size_t optlen, const void *optval) { - const bool use_file = overload & DHCP_OVERLOAD_FILE; - const bool use_sname = overload & DHCP_OVERLOAD_SNAME; - int r; - - assert(message); - assert(offset); - - /* If *offset is in range [0, size), we are writing to ->options, - * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file, - * if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname)) - * and use_sname, we are writing to ->sname. - */ - - if (*offset < size) { - /* still space in the options array */ - r = option_append(message->options, size, offset, code, optlen, optval); - if (r >= 0) - return 0; - else if (r == -ENOBUFS && (use_file || use_sname)) { - /* did not fit, but we have more buffers to try - close the options array and move the offset to its end */ - r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - *offset = size; - } else - return r; - } - - if (use_file) { - size_t file_offset = *offset - size; - - if (file_offset < sizeof(message->file)) { - /* still space in the 'file' array */ - r = option_append(message->file, sizeof(message->file), &file_offset, code, optlen, optval); - if (r >= 0) { - *offset = size + file_offset; - return 0; - } else if (r == -ENOBUFS && use_sname) { - /* did not fit, but we have more buffers to try - close the file array and move the offset to its end */ - r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - *offset = size + sizeof(message->file); - } else - return r; - } - } - - if (use_sname) { - size_t sname_offset = *offset - size - use_file*sizeof(message->file); - - if (sname_offset < sizeof(message->sname)) { - /* still space in the 'sname' array */ - r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval); - if (r >= 0) { - *offset = size + use_file*sizeof(message->file) + sname_offset; - return 0; - } else - /* no space, or other error, give up */ - return r; - } - } - - return -ENOBUFS; -} - -static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload, - uint8_t *message_type, char **error_message, dhcp_option_callback_t cb, - void *userdata) { - uint8_t code, len; - const uint8_t *option; - size_t offset = 0; - - while (offset < buflen) { - code = options[offset ++]; - - switch (code) { - case SD_DHCP_OPTION_PAD: - continue; - - case SD_DHCP_OPTION_END: - return 0; - } - - if (buflen < offset + 1) - return -ENOBUFS; - - len = options[offset ++]; - - if (buflen < offset + len) - return -EINVAL; - - option = &options[offset]; - - switch (code) { - case SD_DHCP_OPTION_MESSAGE_TYPE: - if (len != 1) - return -EINVAL; - - if (message_type) - *message_type = *option; - - break; - - case SD_DHCP_OPTION_ERROR_MESSAGE: - if (len == 0) - return -EINVAL; - - if (error_message) { - _cleanup_free_ char *string = NULL; - - /* Accept a trailing NUL byte */ - if (memchr(option, 0, len - 1)) - return -EINVAL; - - string = memdup_suffix0((const char *) option, len); - if (!string) - return -ENOMEM; - - if (!ascii_is_valid(string)) - return -EINVAL; - - free_and_replace(*error_message, string); - } - - break; - case SD_DHCP_OPTION_OVERLOAD: - if (len != 1) - return -EINVAL; - - if (overload) - *overload = *option; - - break; - - default: - if (cb) - cb(code, len, option, userdata); - - break; - } - - offset += len; - } - - if (offset < buflen) - return -EINVAL; - - return 0; -} - -int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **_error_message) { - _cleanup_free_ char *error_message = NULL; - uint8_t overload = 0; - uint8_t message_type = 0; - int r; - - if (!message) - return -EINVAL; - - if (len < sizeof(DHCPMessage)) - return -EINVAL; - - len -= sizeof(DHCPMessage); - - r = parse_options(message->options, len, &overload, &message_type, &error_message, cb, userdata); - if (r < 0) - return r; - - if (overload & DHCP_OVERLOAD_FILE) { - r = parse_options(message->file, sizeof(message->file), NULL, &message_type, &error_message, cb, userdata); - if (r < 0) - return r; - } - - if (overload & DHCP_OVERLOAD_SNAME) { - r = parse_options(message->sname, sizeof(message->sname), NULL, &message_type, &error_message, cb, userdata); - if (r < 0) - return r; - } - - if (message_type == 0) - return -ENOMSG; - - if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) - *_error_message = TAKE_PTR(error_message); - - return message_type; -} - -static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) { - if (!i) - return NULL; - - free(i->data); - return mfree(i); -} - -int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) { - assert_return(ret, -EINVAL); - assert_return(length == 0 || data, -EINVAL); - - _cleanup_free_ void *q = memdup(data, length); - if (!q) - return -ENOMEM; - - sd_dhcp_option *p = new(sd_dhcp_option, 1); - if (!p) - return -ENOMEM; - - *p = (sd_dhcp_option) { - .n_ref = 1, - .option = option, - .length = length, - .data = TAKE_PTR(q), - }; - - *ret = TAKE_PTR(p); - return 0; -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free); -DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( - dhcp_option_hash_ops, - void, - trivial_hash_func, - trivial_compare_func, - sd_dhcp_option, - sd_dhcp_option_unref); diff --git a/src/core/systemd/src/libsystemd-network/dhcp-packet.c b/src/core/systemd/src/libsystemd-network/dhcp-packet.c deleted file mode 100644 index eeadd562..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-packet.c +++ /dev/null @@ -1,173 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include - -#include "dhcp-internal.h" -#include "dhcp-protocol.h" - -#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312 - -int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, - uint8_t type, uint16_t arp_type, size_t optlen, - size_t *optoffset) { - size_t offset = 0; - int r; - - assert(IN_SET(op, BOOTREQUEST, BOOTREPLY)); - assert(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND)); - - message->op = op; - message->htype = arp_type; - message->hlen = (arp_type == ARPHRD_ETHER) ? ETHER_ADDR_LEN : 0; - message->xid = htobe32(xid); - message->magic = htobe32(DHCP_MAGIC_COOKIE); - - r = dhcp_option_append(message, optlen, &offset, 0, - SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type); - if (r < 0) - return r; - - *optoffset = offset; - - return 0; -} - -uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) { - uint64_t *buf_64 = (uint64_t*)buf; - uint64_t *end_64 = buf_64 + (len / sizeof(uint64_t)); - uint64_t sum = 0; - - /* See RFC1071 */ - - while (buf_64 < end_64) { - sum += *buf_64; - if (sum < *buf_64) - /* wrap around in one's complement */ - sum++; - - buf_64++; - } - - if (len % sizeof(uint64_t)) { - /* If the buffer is not aligned to 64-bit, we need - to zero-pad the last few bytes and add them in */ - uint64_t buf_tail = 0; - - memcpy(&buf_tail, buf_64, len % sizeof(uint64_t)); - - sum += buf_tail; - if (sum < buf_tail) - /* wrap around */ - sum++; - } - - while (sum >> 16) - sum = (sum & 0xffff) + (sum >> 16); - - return ~sum; -} - -void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, - uint16_t source_port, be32_t destination_addr, - uint16_t destination_port, uint16_t len, int ip_service_type) { - packet->ip.version = IPVERSION; - packet->ip.ihl = DHCP_IP_SIZE / 4; - packet->ip.tot_len = htobe16(len); - - if (ip_service_type >= 0) - packet->ip.tos = ip_service_type; - else - packet->ip.tos = IPTOS_CLASS_CS6; - - packet->ip.protocol = IPPROTO_UDP; - packet->ip.saddr = source_addr; - packet->ip.daddr = destination_addr; - - packet->udp.source = htobe16(source_port); - packet->udp.dest = htobe16(destination_port); - - packet->udp.len = htobe16(len - DHCP_IP_SIZE); - - packet->ip.check = packet->udp.len; - packet->udp.check = dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, len - 8); - - packet->ip.ttl = IPDEFTTL; - packet->ip.check = 0; - packet->ip.check = dhcp_packet_checksum((uint8_t*)&packet->ip, DHCP_IP_SIZE); -} - -int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port) { - size_t hdrlen; - - assert(packet); - - /* IP */ - - if (packet->ip.version != IPVERSION) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: not IPv4"); - - if (packet->ip.ihl < 5) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: IPv4 IHL (%u words) invalid", - packet->ip.ihl); - - hdrlen = packet->ip.ihl * 4; - if (hdrlen < 20) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: IPv4 IHL (%zu bytes) " - "smaller than minimum (20 bytes)", - hdrlen); - - if (len < hdrlen) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: packet (%zu bytes) " - "smaller than expected (%zu) by IP header", - len, hdrlen); - - /* UDP */ - - if (packet->ip.protocol != IPPROTO_UDP) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: not UDP"); - - if (len < hdrlen + be16toh(packet->udp.len)) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: packet (%zu bytes) " - "smaller than expected (%zu) by UDP header", - len, hdrlen + be16toh(packet->udp.len)); - - if (be16toh(packet->udp.dest) != port) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: to port %u, which " - "is not the DHCP client port (%u)", - be16toh(packet->udp.dest), port); - - /* checksums - computing these is relatively expensive, so only do it - if all the other checks have passed - */ - - if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen)) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: invalid IP checksum"); - - if (checksum && packet->udp.check) { - packet->ip.check = packet->udp.len; - packet->ip.ttl = 0; - - if (dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, - be16toh(packet->udp.len) + 12)) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "ignoring packet: invalid UDP checksum"); - } - - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/dhcp-protocol.h b/src/core/systemd/src/libsystemd-network/dhcp-protocol.h deleted file mode 100644 index 11f4201a..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp-protocol.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include -#include -#include - -#include "macro.h" -#include "sparse-endian.h" - -struct DHCPMessage { - uint8_t op; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - be32_t xid; - be16_t secs; - be16_t flags; - be32_t ciaddr; - be32_t yiaddr; - be32_t siaddr; - be32_t giaddr; - uint8_t chaddr[16]; - uint8_t sname[64]; - uint8_t file[128]; - be32_t magic; - uint8_t options[0]; -} _packed_; - -typedef struct DHCPMessage DHCPMessage; - -struct DHCPPacket { - struct iphdr ip; - struct udphdr udp; - DHCPMessage dhcp; -} _packed_; - -typedef struct DHCPPacket DHCPPacket; - -#define DHCP_IP_SIZE (int32_t)(sizeof(struct iphdr)) -#define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE) -#define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage)) -#define DHCP_DEFAULT_MIN_SIZE 576 /* the minimum internet hosts must be able to receive */ -#define DHCP_MIN_OPTIONS_SIZE (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE) -#define DHCP_MAGIC_COOKIE (uint32_t)(0x63825363) - -enum { - DHCP_PORT_SERVER = 67, - DHCP_PORT_CLIENT = 68, -}; - -enum DHCPState { - DHCP_STATE_INIT = 0, - DHCP_STATE_SELECTING = 1, - DHCP_STATE_INIT_REBOOT = 2, - DHCP_STATE_REBOOTING = 3, - DHCP_STATE_REQUESTING = 4, - DHCP_STATE_BOUND = 5, - DHCP_STATE_RENEWING = 6, - DHCP_STATE_REBINDING = 7, - DHCP_STATE_STOPPED = 8, -}; - -typedef enum DHCPState DHCPState; - -enum { - BOOTREQUEST = 1, - BOOTREPLY = 2, -}; - -enum { - DHCP_DISCOVER = 1, - DHCP_OFFER = 2, - DHCP_REQUEST = 3, - DHCP_DECLINE = 4, - DHCP_ACK = 5, - DHCP_NAK = 6, - DHCP_RELEASE = 7, - DHCP_INFORM = 8, - DHCP_FORCERENEW = 9, -}; - -enum { - DHCP_OVERLOAD_FILE = 1, - DHCP_OVERLOAD_SNAME = 2, -}; - -#define DHCP_MAX_FQDN_LENGTH 255 - -enum { - DHCP_FQDN_FLAG_S = (1 << 0), - DHCP_FQDN_FLAG_O = (1 << 1), - DHCP_FQDN_FLAG_E = (1 << 2), - DHCP_FQDN_FLAG_N = (1 << 3), -}; diff --git a/src/core/systemd/src/libsystemd-network/dhcp6-internal.h b/src/core/systemd/src/libsystemd-network/dhcp6-internal.h deleted file mode 100644 index 24d8a314..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp6-internal.h +++ /dev/null @@ -1,123 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2014-2015 Intel Corporation. All rights reserved. -***/ - -#include -#include - -#include "sd-event.h" - -#include "list.h" -#include "hashmap.h" -#include "macro.h" -#include "sparse-endian.h" - -typedef struct sd_dhcp6_option { - unsigned n_ref; - - uint32_t enterprise_identifier; - uint16_t option; - void *data; - size_t length; -} sd_dhcp6_option; - -extern const struct hash_ops dhcp6_option_hash_ops; - -/* Common option header */ -typedef struct DHCP6Option { - be16_t code; - be16_t len; - uint8_t data[]; -} _packed_ DHCP6Option; - -/* Address option */ -struct iaaddr { - struct in6_addr address; - be32_t lifetime_preferred; - be32_t lifetime_valid; -} _packed_; - -/* Prefix Delegation Prefix option */ -struct iapdprefix { - be32_t lifetime_preferred; - be32_t lifetime_valid; - uint8_t prefixlen; - struct in6_addr address; -} _packed_; - -typedef struct DHCP6Address DHCP6Address; - -struct DHCP6Address { - LIST_FIELDS(DHCP6Address, addresses); - - union { - struct iaaddr iaaddr; - struct iapdprefix iapdprefix; - }; -}; - -/* Non-temporary Address option */ -struct ia_na { - be32_t id; - be32_t lifetime_t1; - be32_t lifetime_t2; -} _packed_; - -/* Prefix Delegation option */ -struct ia_pd { - be32_t id; - be32_t lifetime_t1; - be32_t lifetime_t2; -} _packed_; - -/* Temporary Address option */ -struct ia_ta { - be32_t id; -} _packed_; - -struct DHCP6IA { - uint16_t type; - union { - struct ia_na ia_na; - struct ia_pd ia_pd; - struct ia_ta ia_ta; - }; - - LIST_HEAD(DHCP6Address, addresses); -}; - -typedef struct DHCP6IA DHCP6IA; - -#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) -#define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__) - -int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, - size_t optlen, const void *optval); -int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia); -int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix); -int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); -int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class); -int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_class); -int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options); -int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, - size_t *optlen, uint8_t **optvalue); -int dhcp6_option_parse_status(DHCP6Option *option, size_t len); -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code); -int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, - struct in6_addr **addrs, size_t count, - size_t *allocated); -int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen, - char ***str_arr); -int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char **str); - -int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *address); -int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, - const void *packet, size_t len); - -const char *dhcp6_message_type_to_string(int s) _const_; -int dhcp6_message_type_from_string(const char *s) _pure_; -const char *dhcp6_message_status_to_string(int s) _const_; -int dhcp6_message_status_from_string(const char *s) _pure_; diff --git a/src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h deleted file mode 100644 index e9e2362d..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2014-2015 Intel Corporation. All rights reserved. -***/ - -#include - -#include "sd-dhcp6-lease.h" - -#include "dhcp6-internal.h" - -struct sd_dhcp6_lease { - unsigned n_ref; - - uint8_t *serverid; - size_t serverid_len; - uint8_t preference; - bool rapid_commit; - - DHCP6IA ia; - DHCP6IA pd; - - DHCP6Address *addr_iter; - DHCP6Address *prefix_iter; - - struct in6_addr *dns; - size_t dns_count; - size_t dns_allocated; - char **domains; - size_t domains_count; - struct in6_addr *ntp; - size_t ntp_count; - size_t ntp_allocated; - char **ntp_fqdn; - size_t ntp_fqdn_count; - char *fqdn; -}; - -int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire); -DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia); - -int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, - size_t len); -int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len); -int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference); -int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference); -int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease); -int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit); - -int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid); -int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid); - -int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); -int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, - size_t optlen); -int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); -int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, - size_t optlen) ; -int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); - -int dhcp6_lease_new(sd_dhcp6_lease **ret); diff --git a/src/core/systemd/src/libsystemd-network/dhcp6-network.c b/src/core/systemd/src/libsystemd-network/dhcp6-network.c deleted file mode 100644 index b6816de4..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp6-network.c +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dhcp6-internal.h" -#include "dhcp6-protocol.h" -#include "fd-util.h" -#include "socket-util.h" - -int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) { - union sockaddr_union src = { - .in6.sin6_family = AF_INET6, - .in6.sin6_port = htobe16(DHCP6_PORT_CLIENT), - .in6.sin6_scope_id = ifindex, - }; - _cleanup_close_ int s = -1; - int r; - - assert(ifindex > 0); - assert(local_address); - - src.in6.sin6_addr = *local_address; - - s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP); - if (s < 0) - return -errno; - - r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true); - if (r < 0) - return r; - - r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false); - if (r < 0) - return r; - - r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); - if (r < 0) - return r; - - r = bind(s, &src.sa, sizeof(src.in6)); - if (r < 0) - return -errno; - - return TAKE_FD(s); -} - -int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, - const void *packet, size_t len) { - union sockaddr_union dest = { - .in6.sin6_family = AF_INET6, - .in6.sin6_port = htobe16(DHCP6_PORT_SERVER), - }; - int r; - - assert(server_address); - - memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr)); - - r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6)); - if (r < 0) - return -errno; - - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/dhcp6-option.c b/src/core/systemd/src/libsystemd-network/dhcp6-option.c deleted file mode 100644 index 21e2d3f0..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp6-option.c +++ /dev/null @@ -1,795 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014-2015 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include - -#include "sd-dhcp6-client.h" - -#include "alloc-util.h" -#include "dhcp-identifier.h" -#include "dhcp6-internal.h" -#include "dhcp6-lease-internal.h" -#include "dhcp6-protocol.h" -#include "dns-domain.h" -#include "memory-util.h" -#include "sparse-endian.h" -#include "strv.h" -#include "unaligned.h" - -typedef struct DHCP6StatusOption { - struct DHCP6Option option; - be16_t status; - char msg[]; -} _packed_ DHCP6StatusOption; - -typedef struct DHCP6AddressOption { - struct DHCP6Option option; - struct iaaddr iaaddr; - uint8_t options[]; -} _packed_ DHCP6AddressOption; - -typedef struct DHCP6PDPrefixOption { - struct DHCP6Option option; - struct iapdprefix iapdprefix; - uint8_t options[]; -} _packed_ DHCP6PDPrefixOption; - -#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na)) -#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd)) -#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta)) - -static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, - size_t optlen) { - DHCP6Option *option = (DHCP6Option*) *buf; - - assert_return(buf, -EINVAL); - assert_return(*buf, -EINVAL); - assert_return(buflen, -EINVAL); - - if (optlen > 0xffff || *buflen < optlen + offsetof(DHCP6Option, data)) - return -ENOBUFS; - - option->code = htobe16(optcode); - option->len = htobe16(optlen); - - *buf += offsetof(DHCP6Option, data); - *buflen -= offsetof(DHCP6Option, data); - - return 0; -} - -int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, - size_t optlen, const void *optval) { - int r; - - assert_return(optval || optlen == 0, -EINVAL); - - r = option_append_hdr(buf, buflen, code, optlen); - if (r < 0) - return r; - - memcpy_safe(*buf, optval, optlen); - - *buf += optlen; - *buflen -= optlen; - - return 0; -} - -int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) { - sd_dhcp6_option *options; - int r; - - assert(buf); - assert(*buf); - assert(buflen); - assert(vendor_options); - - ORDERED_HASHMAP_FOREACH(options, vendor_options) { - _cleanup_free_ uint8_t *p = NULL; - size_t total; - - total = 4 + 2 + 2 + options->length; - - p = malloc(total); - if (!p) - return -ENOMEM; - - unaligned_write_be32(p, options->enterprise_identifier); - unaligned_write_be16(p + 4, options->option); - unaligned_write_be16(p + 6, options->length); - memcpy(p + 8, options->data, options->length); - - r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_OPTS, total, p); - if (r < 0) - return r; - } - - return 0; -} - -int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { - uint16_t len; - uint8_t *ia_hdr; - size_t iaid_offset, ia_buflen, ia_addrlen = 0; - DHCP6Address *addr; - int r; - - assert_return(buf, -EINVAL); - assert_return(*buf, -EINVAL); - assert_return(buflen, -EINVAL); - assert_return(ia, -EINVAL); - - switch (ia->type) { - case SD_DHCP6_OPTION_IA_NA: - len = DHCP6_OPTION_IA_NA_LEN; - iaid_offset = offsetof(DHCP6IA, ia_na); - break; - - case SD_DHCP6_OPTION_IA_TA: - len = DHCP6_OPTION_IA_TA_LEN; - iaid_offset = offsetof(DHCP6IA, ia_ta); - break; - - default: - return -EINVAL; - } - - if (*buflen < offsetof(DHCP6Option, data) + len) - return -ENOBUFS; - - ia_hdr = *buf; - ia_buflen = *buflen; - - *buf += offsetof(DHCP6Option, data); - *buflen -= offsetof(DHCP6Option, data); - - memcpy(*buf, (char*) ia + iaid_offset, len); - - *buf += len; - *buflen -= len; - - LIST_FOREACH(addresses, addr, ia->addresses) { - r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, - sizeof(addr->iaaddr)); - if (r < 0) - return r; - - memcpy(*buf, &addr->iaaddr, sizeof(addr->iaaddr)); - - *buf += sizeof(addr->iaaddr); - *buflen -= sizeof(addr->iaaddr); - - ia_addrlen += offsetof(DHCP6Option, data) + sizeof(addr->iaaddr); - } - - r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen); - if (r < 0) - return r; - - return 0; -} - -int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { - uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX]; - int r; - - assert_return(buf && *buf && buflen && fqdn, -EINVAL); - - buffer[0] = DHCP6_FQDN_FLAG_S; /* Request server to perform AAAA RR DNS updates */ - - /* Store domain name after flags field */ - r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false); - if (r <= 0) - return r; - - /* - * According to RFC 4704, chapter 4.2 only add terminating zero-length - * label in case a FQDN is provided. Since dns_name_to_wire_format - * always adds terminating zero-length label remove if only a hostname - * is provided. - */ - if (dns_name_is_single_label(fqdn)) - r--; - - r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_FQDN, 1 + r, buffer); - - return r; -} - -int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) { - _cleanup_free_ uint8_t *p = NULL; - size_t total = 0, offset = 0; - char **s; - - assert_return(buf && *buf && buflen && user_class, -EINVAL); - - STRV_FOREACH(s, user_class) { - size_t len = strlen(*s); - uint8_t *q; - - if (len > 0xffff) - return -ENAMETOOLONG; - q = realloc(p, total + len + 2); - if (!q) - return -ENOMEM; - - p = q; - - unaligned_write_be16(&p[offset], len); - memcpy(&p[offset + 2], *s, len); - - offset += 2 + len; - total += 2 + len; - } - - return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p); -} - -int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendor_class) { - _cleanup_free_ uint8_t *p = NULL; - uint32_t enterprise_identifier; - size_t total, offset; - char **s; - - assert(buf); - assert(*buf); - assert(buflen); - assert(vendor_class); - - enterprise_identifier = htobe32(SYSTEMD_PEN); - - p = memdup(&enterprise_identifier, sizeof(enterprise_identifier)); - if (!p) - return -ENOMEM; - - total = sizeof(enterprise_identifier); - offset = total; - - STRV_FOREACH(s, vendor_class) { - size_t len = strlen(*s); - uint8_t *q; - - q = realloc(p, total + len + 2); - if (!q) - return -ENOMEM; - - p = q; - - unaligned_write_be16(&p[offset], len); - memcpy(&p[offset + 2], *s, len); - - offset += 2 + len; - total += 2 + len; - } - - return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p); -} - -int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) { - DHCP6Option *option = (DHCP6Option *)buf; - size_t i = sizeof(*option) + sizeof(pd->ia_pd); - DHCP6PDPrefixOption *prefix_opt; - DHCP6Address *prefix; - - assert_return(buf, -EINVAL); - assert_return(pd, -EINVAL); - assert_return(pd->type == SD_DHCP6_OPTION_IA_PD, -EINVAL); - - if (len < i) - return -ENOBUFS; - - option->code = htobe16(SD_DHCP6_OPTION_IA_PD); - - memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd)); - LIST_FOREACH(addresses, prefix, pd->addresses) { - if (len < i + sizeof(*prefix_opt)) - return -ENOBUFS; - - prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; - prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); - prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); - - memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix)); - i += sizeof(*prefix_opt); - } - - if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) { - if (len < i + sizeof(*prefix_opt)) - return -ENOBUFS; - - prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; - prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); - prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); - - memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix)); - i += sizeof(*prefix_opt); - } - - option->len = htobe16(i - sizeof(*option)); - - return i; -} - -static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) { - DHCP6Option *option = (DHCP6Option*) *buf; - uint16_t len; - - assert_return(buf, -EINVAL); - assert_return(optcode, -EINVAL); - assert_return(optlen, -EINVAL); - - if (*buflen < offsetof(DHCP6Option, data)) - return -ENOMSG; - - len = be16toh(option->len); - - if (len > *buflen) - return -ENOMSG; - - *optcode = be16toh(option->code); - *optlen = len; - - *buf += 4; - *buflen -= 4; - - return 0; -} - -int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, - size_t *optlen, uint8_t **optvalue) { - int r; - - assert_return(buf && buflen && optcode && optlen && optvalue, -EINVAL); - - r = option_parse_hdr(buf, buflen, optcode, optlen); - if (r < 0) - return r; - - if (*optlen > *buflen) - return -ENOBUFS; - - *optvalue = *buf; - *buflen -= *optlen; - *buf += *optlen; - - return 0; -} - -int dhcp6_option_parse_status(DHCP6Option *option, size_t len) { - DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option; - - if (len < sizeof(DHCP6StatusOption) || - be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(DHCP6StatusOption)) - return -ENOBUFS; - - return be16toh(statusopt->status); -} - -static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, - uint32_t *lifetime_valid) { - DHCP6AddressOption *addr_option = (DHCP6AddressOption *)option; - DHCP6Address *addr; - uint32_t lt_valid, lt_pref; - int r; - - if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*addr_option)) - return -ENOBUFS; - - lt_valid = be32toh(addr_option->iaaddr.lifetime_valid); - lt_pref = be32toh(addr_option->iaaddr.lifetime_preferred); - - if (lt_valid == 0 || lt_pref > lt_valid) { - log_dhcp6_client(client, "Valid lifetime of an IA address is zero or preferred lifetime %d > valid lifetime %d", - lt_pref, lt_valid); - - return 0; - } - - if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*addr_option)) { - r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*addr_option)); - if (r != 0) - return r < 0 ? r: 0; - } - - addr = new0(DHCP6Address, 1); - if (!addr) - return -ENOMEM; - - LIST_INIT(addresses, addr); - memcpy(&addr->iaaddr, option->data, sizeof(addr->iaaddr)); - - LIST_PREPEND(addresses, ia->addresses, addr); - - *lifetime_valid = be32toh(addr->iaaddr.lifetime_valid); - - return 0; -} - -static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, - uint32_t *lifetime_valid) { - DHCP6PDPrefixOption *pdprefix_option = (DHCP6PDPrefixOption *)option; - DHCP6Address *prefix; - uint32_t lt_valid, lt_pref; - int r; - - if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*pdprefix_option)) - return -ENOBUFS; - - lt_valid = be32toh(pdprefix_option->iapdprefix.lifetime_valid); - lt_pref = be32toh(pdprefix_option->iapdprefix.lifetime_preferred); - - if (lt_valid == 0 || lt_pref > lt_valid) { - log_dhcp6_client(client, "Valid lifetieme of a PD prefix is zero or preferred lifetime %d > valid lifetime %d", - lt_pref, lt_valid); - - return 0; - } - - if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*pdprefix_option)) { - r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*pdprefix_option)); - if (r != 0) - return r < 0 ? r: 0; - } - - prefix = new0(DHCP6Address, 1); - if (!prefix) - return -ENOMEM; - - LIST_INIT(addresses, prefix); - memcpy(&prefix->iapdprefix, option->data, sizeof(prefix->iapdprefix)); - - LIST_PREPEND(addresses, ia->addresses, prefix); - - *lifetime_valid = be32toh(prefix->iapdprefix.lifetime_valid); - - return 0; -} - -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) { - uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX; - uint16_t iatype, optlen; - size_t iaaddr_offset; - int r = 0, status; - size_t i, len; - uint16_t opt; - - assert_return(ia, -EINVAL); - assert_return(!ia->addresses, -EINVAL); - - iatype = be16toh(iaoption->code); - len = be16toh(iaoption->len); - - switch (iatype) { - case SD_DHCP6_OPTION_IA_NA: - - if (len < DHCP6_OPTION_IA_NA_LEN) - return -ENOBUFS; - - iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; - memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na)); - - lt_t1 = be32toh(ia->ia_na.lifetime_t1); - lt_t2 = be32toh(ia->ia_na.lifetime_t2); - - if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { - log_dhcp6_client(client, "IA NA T1 %ds > T2 %ds", - lt_t1, lt_t2); - return -EINVAL; - } - - break; - - case SD_DHCP6_OPTION_IA_PD: - - if (len < sizeof(ia->ia_pd)) - return -ENOBUFS; - - iaaddr_offset = sizeof(ia->ia_pd); - memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd)); - - lt_t1 = be32toh(ia->ia_pd.lifetime_t1); - lt_t2 = be32toh(ia->ia_pd.lifetime_t2); - - if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { - log_dhcp6_client(client, "IA PD T1 %ds > T2 %ds", - lt_t1, lt_t2); - return -EINVAL; - } - - break; - - case SD_DHCP6_OPTION_IA_TA: - if (len < DHCP6_OPTION_IA_TA_LEN) - return -ENOBUFS; - - iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; - memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta)); - - break; - - default: - return -ENOMSG; - } - - ia->type = iatype; - i = iaaddr_offset; - - while (i < len) { - DHCP6Option *option = (DHCP6Option *)&iaoption->data[i]; - - if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len)) - return -ENOBUFS; - - opt = be16toh(option->code); - optlen = be16toh(option->len); - - switch (opt) { - case SD_DHCP6_OPTION_IAADDR: - - if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) { - log_dhcp6_client(client, "IA Address option not in IA NA or TA option"); - return -EINVAL; - } - - r = dhcp6_option_parse_address(option, ia, <_valid); - if (r < 0) - return r; - - if (lt_valid < lt_min) - lt_min = lt_valid; - - break; - - case SD_DHCP6_OPTION_IA_PD_PREFIX: - - if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_PD)) { - log_dhcp6_client(client, "IA PD Prefix option not in IA PD option"); - return -EINVAL; - } - - r = dhcp6_option_parse_pdprefix(option, ia, <_valid); - if (r < 0) - return r; - - if (lt_valid < lt_min) - lt_min = lt_valid; - - break; - - case SD_DHCP6_OPTION_STATUS_CODE: - - status = dhcp6_option_parse_status(option, optlen + offsetof(DHCP6Option, data)); - if (status < 0) - return status; - - if (status > 0) { - if (ret_status_code) - *ret_status_code = status; - - log_dhcp6_client(client, "IA status %s", - dhcp6_message_status_to_string(status)); - - return 0; - } - - break; - - default: - log_dhcp6_client(client, "Unknown IA option %d", opt); - break; - } - - i += sizeof(*option) + optlen; - } - - switch(iatype) { - case SD_DHCP6_OPTION_IA_NA: - if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2) { - lt_t1 = lt_min / 2; - lt_t2 = lt_min / 10 * 8; - ia->ia_na.lifetime_t1 = htobe32(lt_t1); - ia->ia_na.lifetime_t2 = htobe32(lt_t2); - - log_dhcp6_client(client, "Computed IA NA T1 %ds and T2 %ds as both were zero", - lt_t1, lt_t2); - } - - break; - - case SD_DHCP6_OPTION_IA_PD: - if (!ia->ia_pd.lifetime_t1 && !ia->ia_pd.lifetime_t2) { - lt_t1 = lt_min / 2; - lt_t2 = lt_min / 10 * 8; - ia->ia_pd.lifetime_t1 = htobe32(lt_t1); - ia->ia_pd.lifetime_t2 = htobe32(lt_t2); - - log_dhcp6_client(client, "Computed IA PD T1 %ds and T2 %ds as both were zero", - lt_t1, lt_t2); - } - - break; - - default: - break; - } - - if (ret_status_code) - *ret_status_code = 0; - - return 1; -} - -int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, - struct in6_addr **addrs, size_t count, - size_t *allocated) { - - if (optlen == 0 || optlen % sizeof(struct in6_addr) != 0) - return -EINVAL; - - if (!GREEDY_REALLOC(*addrs, *allocated, - count * sizeof(struct in6_addr) + optlen)) - return -ENOMEM; - - memcpy(*addrs + count, optval, optlen); - - count += optlen / sizeof(struct in6_addr); - - return count; -} - -static int parse_domain(const uint8_t **data, uint16_t *len, char **out_domain) { - _cleanup_free_ char *ret = NULL; - size_t n = 0, allocated = 0; - const uint8_t *optval = *data; - uint16_t optlen = *len; - bool first = true; - int r; - - if (optlen <= 1) - return -ENODATA; - - for (;;) { - const char *label; - uint8_t c; - - if (optlen == 0) - break; - - c = *optval; - optval++; - optlen--; - - if (c == 0) - /* End label */ - break; - if (c > 63) - return -EBADMSG; - if (c > optlen) - return -EMSGSIZE; - - /* Literal label */ - label = (const char *)optval; - optval += c; - optlen -= c; - - if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) - return -ENOMEM; - - if (first) - first = false; - else - ret[n++] = '.'; - - r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); - if (r < 0) - return r; - - n += r; - } - - if (n) { - if (!GREEDY_REALLOC(ret, allocated, n + 1)) - return -ENOMEM; - ret[n] = 0; - } - - *out_domain = TAKE_PTR(ret); - *data = optval; - *len = optlen; - - return n; -} - -int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char **str) { - _cleanup_free_ char *domain = NULL; - int r; - - r = parse_domain(&optval, &optlen, &domain); - if (r < 0) - return r; - if (r == 0) - return -ENODATA; - if (optlen != 0) - return -EINVAL; - - *str = TAKE_PTR(domain); - return 0; -} - -int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen, char ***str_arr) { - size_t idx = 0; - _cleanup_strv_free_ char **names = NULL; - int r; - - if (optlen <= 1) - return -ENODATA; - if (optval[optlen - 1] != '\0') - return -EINVAL; - - while (optlen > 0) { - _cleanup_free_ char *ret = NULL; - - r = parse_domain(&optval, &optlen, &ret); - if (r < 0) - return r; - if (r == 0) - continue; - - r = strv_extend(&names, ret); - if (r < 0) - return r; - - idx++; - } - - *str_arr = TAKE_PTR(names); - - return idx; -} - -static sd_dhcp6_option* dhcp6_option_free(sd_dhcp6_option *i) { - if (!i) - return NULL; - - free(i->data); - return mfree(i); -} - -int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, uint32_t enterprise_identifier, sd_dhcp6_option **ret) { - assert_return(ret, -EINVAL); - assert_return(length == 0 || data, -EINVAL); - - _cleanup_free_ void *q = memdup(data, length); - if (!q) - return -ENOMEM; - - sd_dhcp6_option *p = new(sd_dhcp6_option, 1); - if (!p) - return -ENOMEM; - - *p = (sd_dhcp6_option) { - .n_ref = 1, - .option = option, - .enterprise_identifier = enterprise_identifier, - .length = length, - .data = TAKE_PTR(q), - }; - - *ret = p; - return 0; -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_option, sd_dhcp6_option, dhcp6_option_free); -DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( - dhcp6_option_hash_ops, - void, - trivial_hash_func, - trivial_compare_func, - sd_dhcp6_option, - sd_dhcp6_option_unref); diff --git a/src/core/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/core/systemd/src/libsystemd-network/dhcp6-protocol.h deleted file mode 100644 index c7003638..00000000 --- a/src/core/systemd/src/libsystemd-network/dhcp6-protocol.h +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -/*** - Copyright © 2014 Intel Corporation. All rights reserved. -***/ - -#include -#include - -#include "macro.h" -#include "sparse-endian.h" - -struct DHCP6Message { - union { - struct { - uint8_t type; - uint8_t _pad[3]; - } _packed_; - be32_t transaction_id; - }; - uint8_t options[]; -} _packed_; - -typedef struct DHCP6Message DHCP6Message; - -#define DHCP6_MIN_OPTIONS_SIZE \ - 1280 - sizeof(struct ip6_hdr) - sizeof(struct udphdr) - -#define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \ - { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } } - -enum { - DHCP6_PORT_SERVER = 547, - DHCP6_PORT_CLIENT = 546, -}; - -#define DHCP6_INF_TIMEOUT 1 * USEC_PER_SEC -#define DHCP6_INF_MAX_RT 120 * USEC_PER_SEC -#define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC -#define DHCP6_SOL_TIMEOUT 1 * USEC_PER_SEC -#define DHCP6_SOL_MAX_RT 120 * USEC_PER_SEC -#define DHCP6_REQ_TIMEOUT 1 * USEC_PER_SEC -#define DHCP6_REQ_MAX_RT 120 * USEC_PER_SEC -#define DHCP6_REQ_MAX_RC 10 -#define DHCP6_REN_TIMEOUT 10 * USEC_PER_SEC -#define DHCP6_REN_MAX_RT 600 * USEC_PER_SEC -#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC -#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC - -enum DHCP6State { - DHCP6_STATE_STOPPED = 0, - DHCP6_STATE_INFORMATION_REQUEST = 1, - DHCP6_STATE_SOLICITATION = 2, - DHCP6_STATE_REQUEST = 3, - DHCP6_STATE_BOUND = 4, - DHCP6_STATE_RENEW = 5, - DHCP6_STATE_REBIND = 6, -}; - -enum { - DHCP6_SOLICIT = 1, - DHCP6_ADVERTISE = 2, - DHCP6_REQUEST = 3, - DHCP6_CONFIRM = 4, - DHCP6_RENEW = 5, - DHCP6_REBIND = 6, - DHCP6_REPLY = 7, - DHCP6_RELEASE = 8, - DHCP6_DECLINE = 9, - DHCP6_RECONFIGURE = 10, - DHCP6_INFORMATION_REQUEST = 11, - DHCP6_RELAY_FORW = 12, - DHCP6_RELAY_REPL = 13, - _DHCP6_MESSAGE_MAX = 14, -}; - -enum { - DHCP6_NTP_SUBOPTION_SRV_ADDR = 1, - DHCP6_NTP_SUBOPTION_MC_ADDR = 2, - DHCP6_NTP_SUBOPTION_SRV_FQDN = 3, -}; - -/* - * RFC 8415, RFC 5007 and RFC 7653 status codes: - * https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-5 - */ -enum { - DHCP6_STATUS_SUCCESS = 0, - DHCP6_STATUS_UNSPEC_FAIL = 1, - DHCP6_STATUS_NO_ADDRS_AVAIL = 2, - DHCP6_STATUS_NO_BINDING = 3, - DHCP6_STATUS_NOT_ON_LINK = 4, - DHCP6_STATUS_USE_MULTICAST = 5, - DHCP6_STATUS_NO_PREFIX_AVAIL = 6, - DHCP6_STATUS_UNKNOWN_QUERY_TYPE = 7, - DHCP6_STATUS_MALFORMED_QUERY = 8, - DHCP6_STATUS_NOT_CONFIGURED = 9, - DHCP6_STATUS_NOT_ALLOWED = 10, - DHCP6_STATUS_QUERY_TERMINATED = 11, - DHCP6_STATUS_DATA_MISSING = 12, - DHCP6_STATUS_CATCHUP_COMPLETE = 13, - DHCP6_STATUS_NOT_SUPPORTED = 14, - DHCP6_STATUS_TLS_CONNECTION_REFUSED = 15, - DHCP6_STATUS_ADDRESS_IN_USE = 16, - DHCP6_STATUS_CONFIGURATION_CONFLICT = 17, - DHCP6_STATUS_MISSING_BINDING_INFORMATION = 18, - DHCP6_STATUS_OUTDATED_BINDING_INFORMATION = 19, - DHCP6_STATUS_SERVER_SHUTTING_DOWN = 20, - DHCP6_STATUS_DNS_UPDATE_NOT_SUPPORTED = 21, - DHCP6_STATUS_EXCESSIVE_TIME_SKEW = 22, - _DHCP6_STATUS_MAX = 23, -}; - -enum { - DHCP6_FQDN_FLAG_S = (1 << 0), - DHCP6_FQDN_FLAG_O = (1 << 1), - DHCP6_FQDN_FLAG_N = (1 << 2), -}; diff --git a/src/core/systemd/src/libsystemd-network/lldp-internal.h b/src/core/systemd/src/libsystemd-network/lldp-internal.h deleted file mode 100644 index f23695f9..00000000 --- a/src/core/systemd/src/libsystemd-network/lldp-internal.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "sd-event.h" -#include "sd-lldp.h" - -#include "hashmap.h" -#include "log.h" -#include "prioq.h" - -struct sd_lldp { - unsigned n_ref; - - int ifindex; - int fd; - - sd_event *event; - int64_t event_priority; - sd_event_source *io_event_source; - sd_event_source *timer_event_source; - - Prioq *neighbor_by_expiry; - Hashmap *neighbor_by_id; - - uint64_t neighbors_max; - - sd_lldp_callback_t callback; - void *userdata; - - uint16_t capability_mask; - - struct ether_addr filter_address; -}; - -#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) -#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__) - -const char* lldp_event_to_string(sd_lldp_event e) _const_; -sd_lldp_event lldp_event_from_string(const char *s) _pure_; diff --git a/src/core/systemd/src/libsystemd-network/lldp-neighbor.c b/src/core/systemd/src/libsystemd-network/lldp-neighbor.c deleted file mode 100644 index 58ff0e0f..00000000 --- a/src/core/systemd/src/libsystemd-network/lldp-neighbor.c +++ /dev/null @@ -1,794 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include "alloc-util.h" -#include "escape.h" -#include "ether-addr-util.h" -#include "hexdecoct.h" -#include "in-addr-util.h" -#include "lldp-internal.h" -#include "lldp-neighbor.h" -#include "memory-util.h" -#include "missing_network.h" -#include "unaligned.h" - -static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) { - siphash24_compress(id->chassis_id, id->chassis_id_size, state); - siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state); - siphash24_compress(id->port_id, id->port_id_size, state); - siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state); -} - -int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) { - return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size) - ?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size); -} - -DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(lldp_neighbor_hash_ops, LLDPNeighborID, lldp_neighbor_id_hash_func, lldp_neighbor_id_compare_func, - sd_lldp_neighbor, lldp_neighbor_unlink); - -int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { - const sd_lldp_neighbor *x = a, *y = b; - - return CMP(x->until, y->until); -} - -_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { - if (!n) - return NULL; - - assert(n->n_ref > 0 || n->lldp); - n->n_ref++; - - return n; -} - -static void lldp_neighbor_free(sd_lldp_neighbor *n) { - assert(n); - - free(n->id.port_id); - free(n->id.chassis_id); - free(n->port_description); - free(n->system_name); - free(n->system_description); - free(n->mud_url); - free(n->chassis_id_as_string); - free(n->port_id_as_string); - free(n); -} - -_public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { - - /* Drops one reference from the neighbor. Note that the object is not freed unless it is already unlinked from - * the sd_lldp object. */ - - if (!n) - return NULL; - - assert(n->n_ref > 0); - n->n_ref--; - - if (n->n_ref <= 0 && !n->lldp) - lldp_neighbor_free(n); - - return NULL; -} - -sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) { - - /* Removes the neighbor object from the LLDP object, and frees it if it also has no other reference. */ - - if (!n) - return NULL; - - if (!n->lldp) - return NULL; - - /* Only remove the neighbor object from the hash table if it's in there, don't complain if it isn't. This is - * because we are used as destructor call for hashmap_clear() and thus sometimes are called to de-register - * ourselves from the hashtable and sometimes are called after we already are de-registered. */ - - (void) hashmap_remove_value(n->lldp->neighbor_by_id, &n->id, n); - - assert_se(prioq_remove(n->lldp->neighbor_by_expiry, n, &n->prioq_idx) >= 0); - - n->lldp = NULL; - - if (n->n_ref <= 0) - lldp_neighbor_free(n); - - return NULL; -} - -sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) { - sd_lldp_neighbor *n; - - n = malloc0(ALIGN(sizeof(sd_lldp_neighbor)) + raw_size); - if (!n) - return NULL; - - n->raw_size = raw_size; - n->n_ref = 1; - - return n; -} - -static int parse_string(char **s, const void *q, size_t n) { - const char *p = q; - char *k; - - assert(s); - assert(p || n == 0); - - if (*s) { - log_lldp("Found duplicate string, ignoring field."); - return 0; - } - - /* Strip trailing NULs, just to be nice */ - while (n > 0 && p[n-1] == 0) - n--; - - if (n <= 0) /* Ignore empty strings */ - return 0; - - /* Look for inner NULs */ - if (memchr(p, 0, n)) { - log_lldp("Found inner NUL in string, ignoring field."); - return 0; - } - - /* Let's escape weird chars, for security reasons */ - k = cescape_length(p, n); - if (!k) - return -ENOMEM; - - free(*s); - *s = k; - - return 1; -} - -int lldp_neighbor_parse(sd_lldp_neighbor *n) { - struct ether_header h; - const uint8_t *p; - size_t left; - int r; - - assert(n); - - if (n->raw_size < sizeof(struct ether_header)) { - log_lldp("Received truncated packet, ignoring."); - return -EBADMSG; - } - - memcpy(&h, LLDP_NEIGHBOR_RAW(n), sizeof(h)); - - if (h.ether_type != htobe16(ETHERTYPE_LLDP)) { - log_lldp("Received packet with wrong type, ignoring."); - return -EBADMSG; - } - - if (h.ether_dhost[0] != 0x01 || - h.ether_dhost[1] != 0x80 || - h.ether_dhost[2] != 0xc2 || - h.ether_dhost[3] != 0x00 || - h.ether_dhost[4] != 0x00 || - !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) { - log_lldp("Received packet with wrong destination address, ignoring."); - return -EBADMSG; - } - - memcpy(&n->source_address, h.ether_shost, sizeof(struct ether_addr)); - memcpy(&n->destination_address, h.ether_dhost, sizeof(struct ether_addr)); - - p = (const uint8_t*) LLDP_NEIGHBOR_RAW(n) + sizeof(struct ether_header); - left = n->raw_size - sizeof(struct ether_header); - - for (;;) { - uint8_t type; - uint16_t length; - - if (left < 2) { - log_lldp("TLV lacks header, ignoring."); - return -EBADMSG; - } - - type = p[0] >> 1; - length = p[1] + (((uint16_t) (p[0] & 1)) << 8); - p += 2, left -= 2; - - if (left < length) { - log_lldp("TLV truncated, ignoring datagram."); - return -EBADMSG; - } - - switch (type) { - - case SD_LLDP_TYPE_END: - if (length != 0) { - log_lldp("End marker TLV not zero-sized, ignoring datagram."); - return -EBADMSG; - } - - /* Note that after processing the SD_LLDP_TYPE_END left could still be > 0 - * as the message may contain padding (see IEEE 802.1AB-2016, sec. 8.5.12) */ - - goto end_marker; - - case SD_LLDP_TYPE_CHASSIS_ID: - if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */ - log_lldp("Chassis ID field size out of range, ignoring datagram."); - return -EBADMSG; - } - if (n->id.chassis_id) { - log_lldp("Duplicate chassis ID field, ignoring datagram."); - return -EBADMSG; - } - - n->id.chassis_id = memdup(p, length); - if (!n->id.chassis_id) - return -ENOMEM; - - n->id.chassis_id_size = length; - break; - - case SD_LLDP_TYPE_PORT_ID: - if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */ - log_lldp("Port ID field size out of range, ignoring datagram."); - return -EBADMSG; - } - if (n->id.port_id) { - log_lldp("Duplicate port ID field, ignoring datagram."); - return -EBADMSG; - } - - n->id.port_id = memdup(p, length); - if (!n->id.port_id) - return -ENOMEM; - - n->id.port_id_size = length; - break; - - case SD_LLDP_TYPE_TTL: - if (length != 2) { - log_lldp("TTL field has wrong size, ignoring datagram."); - return -EBADMSG; - } - - if (n->has_ttl) { - log_lldp("Duplicate TTL field, ignoring datagram."); - return -EBADMSG; - } - - n->ttl = unaligned_read_be16(p); - n->has_ttl = true; - break; - - case SD_LLDP_TYPE_PORT_DESCRIPTION: - r = parse_string(&n->port_description, p, length); - if (r < 0) - return r; - break; - - case SD_LLDP_TYPE_SYSTEM_NAME: - r = parse_string(&n->system_name, p, length); - if (r < 0) - return r; - break; - - case SD_LLDP_TYPE_SYSTEM_DESCRIPTION: - r = parse_string(&n->system_description, p, length); - if (r < 0) - return r; - break; - - case SD_LLDP_TYPE_SYSTEM_CAPABILITIES: - if (length != 4) - log_lldp("System capabilities field has wrong size, ignoring."); - else { - n->system_capabilities = unaligned_read_be16(p); - n->enabled_capabilities = unaligned_read_be16(p + 2); - n->has_capabilities = true; - } - - break; - - case SD_LLDP_TYPE_PRIVATE: { - if (length < 4) - log_lldp("Found private TLV that is too short, ignoring."); - else { - /* RFC 8520: MUD URL */ - if (memcmp(p, SD_LLDP_OUI_MUD, sizeof(SD_LLDP_OUI_MUD)) == 0 && - p[sizeof(SD_LLDP_OUI_MUD)] == SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION) { - r = parse_string(&n->mud_url, p + sizeof(SD_LLDP_OUI_MUD) + 1, - length - 1 - sizeof(SD_LLDP_OUI_MUD)); - if (r < 0) - return r; - } - } - } - - break; - } - - p += length, left -= length; - } - -end_marker: - if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) { - log_lldp("One or more mandatory TLV missing in datagram. Ignoring."); - return -EBADMSG; - - } - - n->rindex = sizeof(struct ether_header); - - return 0; -} - -void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) { - assert(n); - - if (n->ttl > 0) { - usec_t base; - - /* Use the packet's timestamp if there is one known */ - base = triple_timestamp_by_clock(&n->timestamp, clock_boottime_or_monotonic()); - if (base <= 0 || base == USEC_INFINITY) - base = now(clock_boottime_or_monotonic()); /* Otherwise, take the current time */ - - n->until = usec_add(base, n->ttl * USEC_PER_SEC); - } else - n->until = 0; - - if (n->lldp) - prioq_reshuffle(n->lldp->neighbor_by_expiry, n, &n->prioq_idx); -} - -bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b) { - if (a == b) - return true; - - if (!a || !b) - return false; - - if (a->raw_size != b->raw_size) - return false; - - return memcmp(LLDP_NEIGHBOR_RAW(a), LLDP_NEIGHBOR_RAW(b), a->raw_size) == 0; -} - -_public_ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) { - assert_return(n, -EINVAL); - assert_return(address, -EINVAL); - - *address = n->source_address; - return 0; -} - -_public_ int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) { - assert_return(n, -EINVAL); - assert_return(address, -EINVAL); - - *address = n->destination_address; - return 0; -} - -_public_ int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - *ret = LLDP_NEIGHBOR_RAW(n); - *size = n->raw_size; - - return 0; -} - -_public_ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { - assert_return(n, -EINVAL); - assert_return(type, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - assert(n->id.chassis_id_size > 0); - - *type = *(uint8_t*) n->id.chassis_id; - *ret = (uint8_t*) n->id.chassis_id + 1; - *size = n->id.chassis_id_size - 1; - - return 0; -} - -static int format_mac_address(const void *data, size_t sz, char **ret) { - struct ether_addr a; - char *k; - - assert(data || sz <= 0); - - if (sz != 7) - return 0; - - memcpy(&a, (uint8_t*) data + 1, sizeof(a)); - - k = new(char, ETHER_ADDR_TO_STRING_MAX); - if (!k) - return -ENOMEM; - - *ret = ether_addr_to_string(&a, k); - return 1; -} - -static int format_network_address(const void *data, size_t sz, char **ret) { - union in_addr_union a; - int family, r; - - if (sz == 6 && ((uint8_t*) data)[1] == 1) { - memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in)); - family = AF_INET; - } else if (sz == 18 && ((uint8_t*) data)[1] == 2) { - memcpy(&a.in6, (uint8_t*) data + 2, sizeof(a.in6)); - family = AF_INET6; - } else - return 0; - - r = in_addr_to_string(family, &a, ret); - if (r < 0) - return r; - return 1; -} - -_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) { - char *k; - int r; - - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (n->chassis_id_as_string) { - *ret = n->chassis_id_as_string; - return 0; - } - - assert(n->id.chassis_id_size > 0); - - switch (*(uint8_t*) n->id.chassis_id) { - - case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: - case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: - case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT: - case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: - case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: - k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1); - if (!k) - return -ENOMEM; - - goto done; - - case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: - r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - - case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS: - r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - } - - /* Generic fallback */ - k = hexmem(n->id.chassis_id, n->id.chassis_id_size); - if (!k) - return -ENOMEM; - -done: - *ret = n->chassis_id_as_string = k; - return 0; -} - -_public_ int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { - assert_return(n, -EINVAL); - assert_return(type, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - assert(n->id.port_id_size > 0); - - *type = *(uint8_t*) n->id.port_id; - *ret = (uint8_t*) n->id.port_id + 1; - *size = n->id.port_id_size - 1; - - return 0; -} - -_public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) { - char *k; - int r; - - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (n->port_id_as_string) { - *ret = n->port_id_as_string; - return 0; - } - - assert(n->id.port_id_size > 0); - - switch (*(uint8_t*) n->id.port_id) { - - case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: - case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT: - case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME: - case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: - k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1); - if (!k) - return -ENOMEM; - - goto done; - - case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS: - r = format_mac_address(n->id.port_id, n->id.port_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - - case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS: - r = format_network_address(n->id.port_id, n->id.port_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - } - - /* Generic fallback */ - k = hexmem(n->id.port_id, n->id.port_id_size); - if (!k) - return -ENOMEM; - -done: - *ret = n->port_id_as_string = k; - return 0; -} - -_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) { - assert_return(n, -EINVAL); - assert_return(ret_sec, -EINVAL); - - *ret_sec = n->ttl; - return 0; -} - -_public_ int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->system_name) - return -ENODATA; - - *ret = n->system_name; - return 0; -} - -_public_ int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->system_description) - return -ENODATA; - - *ret = n->system_description; - return 0; -} - -_public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->port_description) - return -ENODATA; - - *ret = n->port_description; - return 0; -} - -_public_ int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->mud_url) - return -ENODATA; - - *ret = n->mud_url; - return 0; -} - -_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->has_capabilities) - return -ENODATA; - - *ret = n->system_capabilities; - return 0; -} - -_public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->has_capabilities) - return -ENODATA; - - *ret = n->enabled_capabilities; - return 0; -} - -_public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) { - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - int r; - - assert_return(ret, -EINVAL); - assert_return(raw || raw_size <= 0, -EINVAL); - - n = lldp_neighbor_new(raw_size); - if (!n) - return -ENOMEM; - - memcpy(LLDP_NEIGHBOR_RAW(n), raw, raw_size); - r = lldp_neighbor_parse(n); - if (r < 0) - return r; - - *ret = TAKE_PTR(n); - - return r; -} - -_public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { - assert_return(n, -EINVAL); - - assert(n->raw_size >= sizeof(struct ether_header)); - n->rindex = sizeof(struct ether_header); - - return n->rindex < n->raw_size; -} - -_public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { - size_t length; - - assert_return(n, -EINVAL); - - if (n->rindex == n->raw_size) /* EOF */ - return -ESPIPE; - - if (n->rindex + 2 > n->raw_size) /* Truncated message */ - return -EBADMSG; - - length = LLDP_NEIGHBOR_TLV_LENGTH(n); - if (n->rindex + 2 + length > n->raw_size) - return -EBADMSG; - - n->rindex += 2 + length; - return n->rindex < n->raw_size; -} - -_public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { - assert_return(n, -EINVAL); - assert_return(type, -EINVAL); - - if (n->rindex == n->raw_size) /* EOF */ - return -ESPIPE; - - if (n->rindex + 2 > n->raw_size) - return -EBADMSG; - - *type = LLDP_NEIGHBOR_TLV_TYPE(n); - return 0; -} - -_public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { - uint8_t k; - int r; - - assert_return(n, -EINVAL); - - r = sd_lldp_neighbor_tlv_get_type(n, &k); - if (r < 0) - return r; - - return type == k; -} - -_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype) { - const uint8_t *d; - size_t length; - int r; - - assert_return(n, -EINVAL); - assert_return(oui, -EINVAL); - assert_return(subtype, -EINVAL); - - r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE); - if (r < 0) - return r; - if (r == 0) - return -ENXIO; - - length = LLDP_NEIGHBOR_TLV_LENGTH(n); - if (length < 4) - return -EBADMSG; - - if (n->rindex + 2 + length > n->raw_size) - return -EBADMSG; - - d = LLDP_NEIGHBOR_TLV_DATA(n); - memcpy(oui, d, 3); - *subtype = d[3]; - - return 0; -} - -_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype) { - uint8_t k[3], st; - int r; - - r = sd_lldp_neighbor_tlv_get_oui(n, k, &st); - if (r == -ENXIO) - return 0; - if (r < 0) - return r; - - return memcmp(k, oui, 3) == 0 && st == subtype; -} - -_public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { - size_t length; - - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - /* Note that this returns the full TLV, including the TLV header */ - - if (n->rindex + 2 > n->raw_size) - return -EBADMSG; - - length = LLDP_NEIGHBOR_TLV_LENGTH(n); - if (n->rindex + 2 + length > n->raw_size) - return -EBADMSG; - - *ret = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; - *size = length + 2; - - return 0; -} - -_public_ int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) { - assert_return(n, -EINVAL); - assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); - assert_return(clock_supported(clock), -EOPNOTSUPP); - assert_return(ret, -EINVAL); - - if (!triple_timestamp_is_set(&n->timestamp)) - return -ENODATA; - - *ret = triple_timestamp_by_clock(&n->timestamp, clock); - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/lldp-neighbor.h b/src/core/systemd/src/libsystemd-network/lldp-neighbor.h deleted file mode 100644 index a5718c8c..00000000 --- a/src/core/systemd/src/libsystemd-network/lldp-neighbor.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include -#include -#include - -#include "sd-lldp.h" - -#include "hash-funcs.h" -#include "lldp-internal.h" -#include "time-util.h" - -typedef struct LLDPNeighborID { - /* The spec calls this an "MSAP identifier" */ - void *chassis_id; - size_t chassis_id_size; - - void *port_id; - size_t port_id_size; -} LLDPNeighborID; - -struct sd_lldp_neighbor { - /* Neighbor objects stay around as long as they are linked into an "sd_lldp" object or n_ref > 0. */ - sd_lldp *lldp; - unsigned n_ref; - - triple_timestamp timestamp; - - usec_t until; - unsigned prioq_idx; - - struct ether_addr source_address; - struct ether_addr destination_address; - - LLDPNeighborID id; - - /* The raw packet size. The data is appended to the object, accessible via LLDP_NEIGHBOR_RAW() */ - size_t raw_size; - - /* The current read index for the iterative TLV interface */ - size_t rindex; - - /* And a couple of fields parsed out. */ - bool has_ttl:1; - bool has_capabilities:1; - bool has_port_vlan_id:1; - - uint16_t ttl; - - uint16_t system_capabilities; - uint16_t enabled_capabilities; - - char *port_description; - char *system_name; - char *system_description; - char *mud_url; - - uint16_t port_vlan_id; - - char *chassis_id_as_string; - char *port_id_as_string; -}; - -static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) { - return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor)); -} - -static inline uint8_t LLDP_NEIGHBOR_TLV_TYPE(const sd_lldp_neighbor *n) { - return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1; -} - -static inline size_t LLDP_NEIGHBOR_TLV_LENGTH(const sd_lldp_neighbor *n) { - uint8_t *p; - - p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; - return p[1] + (((size_t) (p[0] & 1)) << 8); -} - -static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) { - return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2; -} - -extern const struct hash_ops lldp_neighbor_hash_ops; -int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y); -int lldp_neighbor_prioq_compare_func(const void *a, const void *b); - -sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n); -sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size); -int lldp_neighbor_parse(sd_lldp_neighbor *n); -void lldp_neighbor_start_ttl(sd_lldp_neighbor *n); -bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b); diff --git a/src/core/systemd/src/libsystemd-network/lldp-network.c b/src/core/systemd/src/libsystemd-network/lldp-network.c deleted file mode 100644 index 75dce58c..00000000 --- a/src/core/systemd/src/libsystemd-network/lldp-network.c +++ /dev/null @@ -1,80 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include - -#include "fd-util.h" -#include "lldp-network.h" -#include "missing_network.h" -#include "socket-util.h" - -int lldp_network_bind_raw_socket(int ifindex) { - - static const struct sock_filter filter[] = { - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ - BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */ - BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)), /* A <- protocol */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */ - BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1), /* accept packet */ - }; - - static const struct sock_fprog fprog = { - .len = ELEMENTSOF(filter), - .filter = (struct sock_filter*) filter, - }; - - struct packet_mreq mreq = { - .mr_ifindex = ifindex, - .mr_type = PACKET_MR_MULTICAST, - .mr_alen = ETH_ALEN, - .mr_address = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 } - }; - - union sockaddr_union saddrll = { - .ll.sll_family = AF_PACKET, - .ll.sll_ifindex = ifindex, - }; - - _cleanup_close_ int fd = -1; - int r; - - assert(ifindex > 0); - - fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, - htobe16(ETHERTYPE_LLDP)); - if (fd < 0) - return -errno; - - r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); - if (r < 0) - return -errno; - - r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - if (r < 0) - return -errno; - - mreq.mr_address[ETH_ALEN - 1] = 0x03; - r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - if (r < 0) - return -errno; - - mreq.mr_address[ETH_ALEN - 1] = 0x0E; - r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - if (r < 0) - return -errno; - - r = bind(fd, &saddrll.sa, sizeof(saddrll.ll)); - if (r < 0) - return -errno; - - return TAKE_FD(fd); -} diff --git a/src/core/systemd/src/libsystemd-network/lldp-network.h b/src/core/systemd/src/libsystemd-network/lldp-network.h deleted file mode 100644 index bc69b324..00000000 --- a/src/core/systemd/src/libsystemd-network/lldp-network.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "sd-event.h" - -int lldp_network_bind_raw_socket(int ifindex); diff --git a/src/core/systemd/src/libsystemd-network/network-internal.c b/src/core/systemd/src/libsystemd-network/network-internal.c deleted file mode 100644 index efa3dcfa..00000000 --- a/src/core/systemd/src/libsystemd-network/network-internal.c +++ /dev/null @@ -1,245 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "sd-ndisc.h" - -#include "alloc-util.h" -#include "dhcp-lease-internal.h" -#include "extract-word.h" -#include "hexdecoct.h" -#include "log.h" -#include "network-internal.h" -#include "parse-util.h" - -size_t serialize_in_addrs(FILE *f, - const struct in_addr *addresses, - size_t size, - bool *with_leading_space, - bool (*predicate)(const struct in_addr *addr)) { - assert(f); - assert(addresses); - - size_t count = 0; - bool _space = false; - if (!with_leading_space) - with_leading_space = &_space; - - for (size_t i = 0; i < size; i++) { - char sbuf[INET_ADDRSTRLEN]; - - if (predicate && !predicate(&addresses[i])) - continue; - - if (*with_leading_space) - fputc(' ', f); - fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f); - count++; - *with_leading_space = true; - } - - return count; -} - -int deserialize_in_addrs(struct in_addr **ret, const char *string) { - _cleanup_free_ struct in_addr *addresses = NULL; - int size = 0; - - assert(ret); - assert(string); - - for (;;) { - _cleanup_free_ char *word = NULL; - struct in_addr *new_addresses; - int r; - - r = extract_first_word(&string, &word, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - - new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr)); - if (!new_addresses) - return -ENOMEM; - else - addresses = new_addresses; - - r = inet_pton(AF_INET, word, &(addresses[size])); - if (r <= 0) - continue; - - size++; - } - - *ret = size > 0 ? TAKE_PTR(addresses) : NULL; - - return size; -} - -void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size, bool *with_leading_space) { - assert(f); - assert(addresses); - assert(size); - - bool _space = false; - if (!with_leading_space) - with_leading_space = &_space; - - for (size_t i = 0; i < size; i++) { - char buffer[INET6_ADDRSTRLEN]; - - if (*with_leading_space) - fputc(' ', f); - fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f); - *with_leading_space = true; - } -} - -int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { - _cleanup_free_ struct in6_addr *addresses = NULL; - int size = 0; - - assert(ret); - assert(string); - - for (;;) { - _cleanup_free_ char *word = NULL; - struct in6_addr *new_addresses; - int r; - - r = extract_first_word(&string, &word, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - - new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr)); - if (!new_addresses) - return -ENOMEM; - else - addresses = new_addresses; - - r = inet_pton(AF_INET6, word, &(addresses[size])); - if (r <= 0) - continue; - - size++; - } - - *ret = TAKE_PTR(addresses); - - return size; -} - -void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) { - assert(f); - assert(key); - assert(routes); - assert(size); - - fprintf(f, "%s=", key); - - for (size_t i = 0; i < size; i++) { - char sbuf[INET_ADDRSTRLEN]; - struct in_addr dest, gw; - uint8_t length; - - assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0); - assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0); - assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0); - - fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof sbuf), length); - fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof sbuf), i < size - 1 ? " ": ""); - } - - fputs("\n", f); -} - -int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) { - _cleanup_free_ struct sd_dhcp_route *routes = NULL; - size_t size = 0, allocated = 0; - - assert(ret); - assert(ret_size); - assert(ret_allocated); - assert(string); - - /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ - for (;;) { - _cleanup_free_ char *word = NULL; - char *tok, *tok_end; - unsigned n; - int r; - - r = extract_first_word(&string, &word, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - - if (!GREEDY_REALLOC(routes, allocated, size + 1)) - return -ENOMEM; - - tok = word; - - /* get the subnet */ - tok_end = strchr(tok, '/'); - if (!tok_end) - continue; - *tok_end = '\0'; - - r = inet_aton(tok, &routes[size].dst_addr); - if (r == 0) - continue; - - tok = tok_end + 1; - - /* get the prefixlen */ - tok_end = strchr(tok, ','); - if (!tok_end) - continue; - - *tok_end = '\0'; - - r = safe_atou(tok, &n); - if (r < 0 || n > 32) - continue; - - routes[size].dst_prefixlen = (uint8_t) n; - tok = tok_end + 1; - - /* get the gateway */ - r = inet_aton(tok, &routes[size].gw_addr); - if (r == 0) - continue; - - size++; - } - - *ret_size = size; - *ret_allocated = allocated; - *ret = TAKE_PTR(routes); - - return 0; -} - -int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) { - _cleanup_free_ char *hex_buf = NULL; - - assert(f); - assert(key); - assert(data); - - hex_buf = hexmem(data, size); - if (!hex_buf) - return -ENOMEM; - - fprintf(f, "%s=%s\n", key, hex_buf); - - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/network-internal.h b/src/core/systemd/src/libsystemd-network/network-internal.h deleted file mode 100644 index e5b853c0..00000000 --- a/src/core/systemd/src/libsystemd-network/network-internal.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include -#include - -#include "sd-dhcp-lease.h" - -size_t serialize_in_addrs(FILE *f, - const struct in_addr *addresses, - size_t size, - bool *with_leading_space, - bool (*predicate)(const struct in_addr *addr)); -int deserialize_in_addrs(struct in_addr **addresses, const char *string); -void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, - size_t size, - bool *with_leading_space); -int deserialize_in6_addrs(struct in6_addr **addresses, const char *string); - -/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */ -struct sd_dhcp_route; -struct sd_dhcp_lease; - -void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size); -int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); - -/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ -int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); - -int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); -int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); diff --git a/src/core/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/core/systemd/src/libsystemd-network/sd-dhcp-client.c deleted file mode 100644 index 27a3476f..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-dhcp-client.c +++ /dev/null @@ -1,2258 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "sd-dhcp-client.h" - -#include "alloc-util.h" -#include "dhcp-identifier.h" -#include "dhcp-internal.h" -#include "dhcp-lease-internal.h" -#include "dhcp-protocol.h" -#include "dns-domain.h" -#include "event-util.h" -#include "fd-util.h" -#include "hostname-util.h" -#include "io-util.h" -#include "memory-util.h" -#include "random-util.h" -#include "set.h" -#include "sort-util.h" -#include "string-util.h" -#include "strv.h" -#include "time-util.h" -#include "utf8.h" -#include "web-util.h" - -#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */ -#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN) - -#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC) -#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE) - -#define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report - * transient failure. */ - -typedef struct sd_dhcp_client_id { - uint8_t type; - union { - struct { - /* 0: Generic (non-LL) (RFC 2132) */ - uint8_t data[MAX_CLIENT_ID_LEN]; - } _packed_ gen; - struct { - /* 1: Ethernet Link-Layer (RFC 2132) */ - uint8_t haddr[ETH_ALEN]; - } _packed_ eth; - struct { - /* 2 - 254: ARP/Link-Layer (RFC 2132) */ - uint8_t haddr[0]; - } _packed_ ll; - struct { - /* 255: Node-specific (RFC 4361) */ - be32_t iaid; - struct duid duid; - } _packed_ ns; - struct { - uint8_t data[MAX_CLIENT_ID_LEN]; - } _packed_ raw; - }; -} _packed_ sd_dhcp_client_id; - -struct sd_dhcp_client { - unsigned n_ref; - - DHCPState state; - sd_event *event; - int event_priority; - sd_event_source *timeout_resend; - int ifindex; - int fd; - uint16_t port; - union sockaddr_union link; - sd_event_source *receive_message; - bool request_broadcast; - Set *req_opts; - bool anonymize; - be32_t last_addr; - uint8_t mac_addr[MAX_MAC_ADDR_LEN]; - size_t mac_addr_len; - uint8_t bcast_addr[MAX_MAC_ADDR_LEN]; - size_t bcast_addr_len; - uint16_t arp_type; - sd_dhcp_client_id client_id; - size_t client_id_len; - char *hostname; - char *vendor_class_identifier; - char *mudurl; - char **user_class; - uint32_t mtu; - uint32_t fallback_lease_lifetime; - uint32_t xid; - usec_t start_time; - usec_t t1_time; - usec_t t2_time; - usec_t expire_time; - uint64_t attempt; - uint64_t max_attempts; - OrderedHashmap *extra_options; - OrderedHashmap *vendor_options; - usec_t request_sent; - sd_event_source *timeout_t1; - sd_event_source *timeout_t2; - sd_event_source *timeout_expire; - sd_dhcp_client_callback_t callback; - void *userdata; - sd_dhcp_lease *lease; - usec_t start_delay; - int ip_service_type; -}; - -static const uint8_t default_req_opts[] = { - SD_DHCP_OPTION_SUBNET_MASK, - SD_DHCP_OPTION_ROUTER, - SD_DHCP_OPTION_HOST_NAME, - SD_DHCP_OPTION_DOMAIN_NAME, - SD_DHCP_OPTION_DOMAIN_NAME_SERVER, -}; - -/* RFC7844 section 3: - MAY contain the Parameter Request List option. - RFC7844 section 3.6: - The client intending to protect its privacy SHOULD only request a - minimal number of options in the PRL and SHOULD also randomly shuffle - the ordering of option codes in the PRL. If this random ordering - cannot be implemented, the client MAY order the option codes in the - PRL by option code number (lowest to highest). -*/ -/* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */ -static const uint8_t default_req_opts_anonymize[] = { - SD_DHCP_OPTION_SUBNET_MASK, /* 1 */ - SD_DHCP_OPTION_ROUTER, /* 3 */ - SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */ - SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */ - SD_DHCP_OPTION_ROUTER_DISCOVER, /* 31 */ - SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */ - SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */ - SD_DHCP_OPTION_NETBIOS_NAMESERVER, /* 44 */ - SD_DHCP_OPTION_NETBIOS_NODETYPE, /* 46 */ - SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */ - SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */ - SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */ - SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, /* 252 */ -}; - -static int client_receive_message_raw( - sd_event_source *s, - int fd, - uint32_t revents, - void *userdata); -static int client_receive_message_udp( - sd_event_source *s, - int fd, - uint32_t revents, - void *userdata); -static void client_stop(sd_dhcp_client *client, int error); - -int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret) { - const sd_dhcp_client_id *client_id = data; - _cleanup_free_ char *t = NULL; - int r = 0; - - assert_return(data, -EINVAL); - assert_return(len >= 1, -EINVAL); - assert_return(ret, -EINVAL); - - len -= 1; - if (len > MAX_CLIENT_ID_LEN) - return -EINVAL; - - switch (client_id->type) { - case 0: - if (utf8_is_printable((char *) client_id->gen.data, len)) - r = asprintf(&t, "%.*s", (int) len, client_id->gen.data); - else - r = asprintf(&t, "DATA"); - break; - case 1: - if (len != sizeof_field(sd_dhcp_client_id, eth)) - return -EINVAL; - - r = asprintf(&t, "%x:%x:%x:%x:%x:%x", - client_id->eth.haddr[0], - client_id->eth.haddr[1], - client_id->eth.haddr[2], - client_id->eth.haddr[3], - client_id->eth.haddr[4], - client_id->eth.haddr[5]); - break; - case 2 ... 254: - r = asprintf(&t, "ARP/LL"); - break; - case 255: - if (len < 6) - return -EINVAL; - - uint32_t iaid = be32toh(client_id->ns.iaid); - uint16_t duid_type = be16toh(client_id->ns.duid.type); - if (dhcp_validate_duid_len(duid_type, len - 6, true) < 0) - return -EINVAL; - - r = asprintf(&t, "IAID:0x%x/DUID", iaid); - break; - } - - if (r < 0) - return -ENOMEM; - *ret = TAKE_PTR(t); - return 0; -} - -int sd_dhcp_client_set_callback( - sd_dhcp_client *client, - sd_dhcp_client_callback_t cb, - void *userdata) { - - assert_return(client, -EINVAL); - - client->callback = cb; - client->userdata = userdata; - - return 0; -} - -int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) { - assert_return(client, -EINVAL); - - client->request_broadcast = !!broadcast; - - return 0; -} - -int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { - assert_return(client, -EINVAL); - assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); - - switch(option) { - - case SD_DHCP_OPTION_PAD: - case SD_DHCP_OPTION_OVERLOAD: - case SD_DHCP_OPTION_MESSAGE_TYPE: - case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST: - case SD_DHCP_OPTION_END: - return -EINVAL; - - default: - break; - } - - return set_ensure_put(&client->req_opts, NULL, UINT8_TO_PTR(option)); -} - -int sd_dhcp_client_set_request_address( - sd_dhcp_client *client, - const struct in_addr *last_addr) { - - assert_return(client, -EINVAL); - assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); - - if (last_addr) - client->last_addr = last_addr->s_addr; - else - client->last_addr = INADDR_ANY; - - return 0; -} - -int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) { - - assert_return(client, -EINVAL); - assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); - assert_return(ifindex > 0, -EINVAL); - - client->ifindex = ifindex; - return 0; -} - -int sd_dhcp_client_set_mac( - sd_dhcp_client *client, - const uint8_t *addr, - const uint8_t *bcast_addr, - size_t addr_len, - uint16_t arp_type) { - - DHCP_CLIENT_DONT_DESTROY(client); - bool need_restart = false; - int r; - - assert_return(client, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); - assert_return(arp_type > 0, -EINVAL); - - if (arp_type == ARPHRD_ETHER) - assert_return(addr_len == ETH_ALEN, -EINVAL); - else if (arp_type == ARPHRD_INFINIBAND) - assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); - else - return -EINVAL; - - if (client->mac_addr_len == addr_len && - memcmp(&client->mac_addr, addr, addr_len) == 0 && - (client->bcast_addr_len > 0) == !!bcast_addr && - (!bcast_addr || memcmp(&client->bcast_addr, bcast_addr, addr_len) == 0)) - return 0; - - if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { - log_dhcp_client(client, "Changing MAC address on running DHCP client, restarting"); - need_restart = true; - client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - } - - memcpy(&client->mac_addr, addr, addr_len); - client->mac_addr_len = addr_len; - client->arp_type = arp_type; - client->bcast_addr_len = 0; - - if (bcast_addr) { - memcpy(&client->bcast_addr, bcast_addr, addr_len); - client->bcast_addr_len = addr_len; - } - - if (need_restart && client->state != DHCP_STATE_STOPPED) { - r = sd_dhcp_client_start(client); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); - } - - return 0; -} - -int sd_dhcp_client_get_client_id( - sd_dhcp_client *client, - uint8_t *type, - const uint8_t **data, - size_t *data_len) { - - assert_return(client, -EINVAL); - assert_return(type, -EINVAL); - assert_return(data, -EINVAL); - assert_return(data_len, -EINVAL); - - *type = 0; - *data = NULL; - *data_len = 0; - if (client->client_id_len) { - *type = client->client_id.type; - *data = client->client_id.raw.data; - *data_len = client->client_id_len - sizeof(client->client_id.type); - } - - return 0; -} - -int sd_dhcp_client_set_client_id( - sd_dhcp_client *client, - uint8_t type, - const uint8_t *data, - size_t data_len) { - - DHCP_CLIENT_DONT_DESTROY(client); - bool need_restart = false; - int r; - - assert_return(client, -EINVAL); - assert_return(data, -EINVAL); - assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL); - G_STATIC_ASSERT_EXPR (_NM_SD_MAX_CLIENT_ID_LEN == MAX_CLIENT_ID_LEN); - - if (client->client_id_len == data_len + sizeof(client->client_id.type) && - client->client_id.type == type && - memcmp(&client->client_id.raw.data, data, data_len) == 0) - return 0; - - /* For hardware types, log debug message about unexpected data length. - * - * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only - * the last 8 bytes of the address are stable and suitable to put into - * the client-id. The caller is advised to account for that. */ - if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) || - (type == ARPHRD_INFINIBAND && data_len != 8)) - log_dhcp_client(client, "Changing client ID to hardware type %u with " - "unexpected address length %zu", - type, data_len); - - if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { - log_dhcp_client(client, "Changing client ID on running DHCP " - "client, restarting"); - need_restart = true; - client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - } - - client->client_id.type = type; - memcpy(&client->client_id.raw.data, data, data_len); - client->client_id_len = data_len + sizeof (client->client_id.type); - - if (need_restart && client->state != DHCP_STATE_STOPPED) { - r = sd_dhcp_client_start(client); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); - } - - return 0; -} - -#if 0 /* NM_IGNORED */ -/** - * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid - * without further modification. Otherwise, if duid_type is supported, DUID - * is set based on that type. Otherwise, an error is returned. - */ -static int dhcp_client_set_iaid_duid_internal( - sd_dhcp_client *client, - bool iaid_append, - bool iaid_set, - uint32_t iaid, - uint16_t duid_type, - const void *duid, - size_t duid_len, - usec_t llt_time) { - - DHCP_CLIENT_DONT_DESTROY(client); - int r; - size_t len; - - assert_return(client, -EINVAL); - assert_return(duid_len == 0 || duid, -EINVAL); - - if (duid) { - r = dhcp_validate_duid_len(duid_type, duid_len, true); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to validate length of DUID: %m"); - } - - zero(client->client_id); - client->client_id.type = 255; - - if (iaid_append) { - if (iaid_set) - client->client_id.ns.iaid = htobe32(iaid); - else { - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, - client->mac_addr_len, - true, - &client->client_id.ns.iaid); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set IAID: %m"); - } - } - - if (duid) { - client->client_id.ns.duid.type = htobe16(duid_type); - memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len); - len = sizeof(client->client_id.ns.duid.type) + duid_len; - } else - switch (duid_type) { - case DUID_TYPE_LLT: - if (client->mac_addr_len == 0) - return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); - - r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m"); - break; - case DUID_TYPE_EN: - r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m"); - break; - case DUID_TYPE_LL: - if (client->mac_addr_len == 0) - return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); - - r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m"); - break; - case DUID_TYPE_UUID: - r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-UUID: %m"); - break; - default: - return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); - } - - client->client_id_len = sizeof(client->client_id.type) + len + - (iaid_append ? sizeof(client->client_id.ns.iaid) : 0); - - if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { - log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : ""); - client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - r = sd_dhcp_client_start(client); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); - } - - return 0; -} - -int sd_dhcp_client_set_iaid_duid( - sd_dhcp_client *client, - bool iaid_set, - uint32_t iaid, - uint16_t duid_type, - const void *duid, - size_t duid_len) { - return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, duid_type, duid, duid_len, 0); -} - -int sd_dhcp_client_set_iaid_duid_llt( - sd_dhcp_client *client, - bool iaid_set, - uint32_t iaid, - usec_t llt_time) { - return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, DUID_TYPE_LLT, NULL, 0, llt_time); -} - -int sd_dhcp_client_set_duid( - sd_dhcp_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len) { - return dhcp_client_set_iaid_duid_internal(client, false, false, 0, duid_type, duid, duid_len, 0); -} - -int sd_dhcp_client_set_duid_llt( - sd_dhcp_client *client, - usec_t llt_time) { - return dhcp_client_set_iaid_duid_internal(client, false, false, 0, DUID_TYPE_LLT, NULL, 0, llt_time); -} -#endif /* NM_IGNORED */ - -int sd_dhcp_client_set_hostname( - sd_dhcp_client *client, - const char *hostname) { - - assert_return(client, -EINVAL); - - /* Make sure hostnames qualify as DNS and as Linux hostnames */ - if (hostname && - !(hostname_is_valid(hostname, 0) && dns_name_is_valid(hostname) > 0)) - return -EINVAL; - - return free_and_strdup(&client->hostname, hostname); -} - -int sd_dhcp_client_set_vendor_class_identifier( - sd_dhcp_client *client, - const char *vci) { - - assert_return(client, -EINVAL); - - return free_and_strdup(&client->vendor_class_identifier, vci); -} - -int sd_dhcp_client_set_mud_url( - sd_dhcp_client *client, - const char *mudurl) { - - assert_return(client, -EINVAL); - assert_return(mudurl, -EINVAL); - assert_return(strlen(mudurl) <= 255, -EINVAL); - assert_return(http_url_is_valid(mudurl), -EINVAL); - - return free_and_strdup(&client->mudurl, mudurl); -} - -int sd_dhcp_client_set_user_class( - sd_dhcp_client *client, - const char* const* user_class) { - - _cleanup_strv_free_ char **s = NULL; - char **p; - - STRV_FOREACH(p, (char **) user_class) - if (strlen(*p) > 255) - return -ENAMETOOLONG; - - s = strv_copy((char **) user_class); - if (!s) - return -ENOMEM; - - client->user_class = TAKE_PTR(s); - - return 0; -} - -int sd_dhcp_client_set_client_port( - sd_dhcp_client *client, - uint16_t port) { - - assert_return(client, -EINVAL); - - client->port = port; - - return 0; -} - -int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) { - assert_return(client, -EINVAL); - assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE); - - client->mtu = mtu; - - return 0; -} - -int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) { - assert_return(client, -EINVAL); - - client->max_attempts = max_attempts; - - return 0; -} - -int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v) { - int r; - - assert_return(client, -EINVAL); - assert_return(v, -EINVAL); - - r = ordered_hashmap_ensure_allocated(&client->extra_options, &dhcp_option_hash_ops); - if (r < 0) - return r; - - r = ordered_hashmap_put(client->extra_options, UINT_TO_PTR(v->option), v); - if (r < 0) - return r; - - sd_dhcp_option_ref(v); - return 0; -} - -int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v) { - int r; - - assert_return(client, -EINVAL); - assert_return(v, -EINVAL); - - r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp_option_hash_ops); - if (r < 0) - return -ENOMEM; - - r = ordered_hashmap_put(client->vendor_options, v, v); - if (r < 0) - return r; - - sd_dhcp_option_ref(v); - - return 1; -} - -int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { - assert_return(client, -EINVAL); - - if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING)) - return -EADDRNOTAVAIL; - - if (ret) - *ret = client->lease; - - return 0; -} - -int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { - assert_return(client, -EINVAL); - - client->ip_service_type = type; - - return 0; -} - -int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) { - assert_return(client, -EINVAL); - assert_return(fallback_lease_lifetime > 0, -EINVAL); - - client->fallback_lease_lifetime = fallback_lease_lifetime; - - return 0; -} - -static int client_notify(sd_dhcp_client *client, int event) { - assert(client); - - if (client->callback) - return client->callback(client, event, client->userdata); - - return 0; -} - -static int client_initialize(sd_dhcp_client *client) { - assert_return(client, -EINVAL); - - client->receive_message = sd_event_source_unref(client->receive_message); - - client->fd = safe_close(client->fd); - - (void) event_source_disable(client->timeout_resend); - (void) event_source_disable(client->timeout_t1); - (void) event_source_disable(client->timeout_t2); - (void) event_source_disable(client->timeout_expire); - - client->attempt = 0; - - client->state = DHCP_STATE_INIT; - client->xid = 0; - - client->lease = sd_dhcp_lease_unref(client->lease); - - return 0; -} - -static void client_stop(sd_dhcp_client *client, int error) { - assert(client); - - if (error < 0) - log_dhcp_client_errno(client, error, "STOPPED: %m"); - else if (error == SD_DHCP_CLIENT_EVENT_STOP) - log_dhcp_client(client, "STOPPED"); - else - log_dhcp_client(client, "STOPPED: Unknown event"); - - client_notify(client, error); - - client_initialize(client); -} - -/* RFC2131 section 4.1: - * retransmission delays should include -1 to +1 sec of random 'fuzz'. */ -#define RFC2131_RANDOM_FUZZ \ - ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC) - -/* RFC2131 section 4.1: - * for retransmission delays, timeout should start at 4s then double - * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added. - * This assumes the first call will be using attempt 1. */ -static usec_t client_compute_request_timeout(usec_t now, uint64_t attempt) { - usec_t timeout = (UINT64_C(1) << MIN(attempt + 1, UINT64_C(6))) * USEC_PER_SEC; - - return usec_sub_signed(usec_add(now, timeout), RFC2131_RANDOM_FUZZ); -} - -/* RFC2131 section 4.4.5: - * T1 defaults to (0.5 * duration_of_lease). - * T2 defaults to (0.875 * duration_of_lease). */ -#define T1_DEFAULT(lifetime) ((lifetime) / 2) -#define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8) - -/* RFC2131 section 4.4.5: - * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state) - * and one-half of the remaining lease time (in REBINDING state), down to a minimum - * of 60 seconds. - * Note that while the default T1/T2 initial times do have random 'fuzz' applied, - * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */ -static usec_t client_compute_reacquisition_timeout(usec_t now, usec_t expire) { - return now + MAX(usec_sub_unsigned(expire, now) / 2, 60 * USEC_PER_SEC); -} - -static int cmp_uint8(const uint8_t *a, const uint8_t *b) { - return CMP(*a, *b); -} - -static int client_message_init( - sd_dhcp_client *client, - DHCPPacket **ret, - uint8_t type, - size_t *_optlen, - size_t *_optoffset) { - - _cleanup_free_ DHCPPacket *packet = NULL; - size_t optlen, optoffset, size; - be16_t max_size; - usec_t time_now; - uint16_t secs; - int r; - - assert(client); - assert(client->start_time); - assert(ret); - assert(_optlen); - assert(_optoffset); - assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE, DHCP_DECLINE)); - - optlen = DHCP_MIN_OPTIONS_SIZE; - size = sizeof(DHCPPacket) + optlen; - - packet = malloc0(size); - if (!packet) - return -ENOMEM; - - r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type, - client->arp_type, optlen, &optoffset); - if (r < 0) - return r; - - /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers - refuse to issue an DHCP lease if 'secs' is set to zero */ - r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return r; - assert(time_now >= client->start_time); - - /* seconds between sending first and last DISCOVER - * must always be strictly positive to deal with broken servers */ - secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1; - packet->dhcp.secs = htobe16(secs); - - /* RFC2132 section 4.1 - A client that cannot receive unicast IP datagrams until its protocol - software has been configured with an IP address SHOULD set the - BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or - DHCPREQUEST messages that client sends. The BROADCAST bit will - provide a hint to the DHCP server and BOOTP relay agent to broadcast - any messages to the client on the client's subnet. - - Note: some interfaces needs this to be enabled, but some networks - needs this to be disabled as broadcasts are filteretd, so this - needs to be configurable */ - if (client->request_broadcast || client->arp_type != ARPHRD_ETHER) - packet->dhcp.flags = htobe16(0x8000); - - /* RFC2132 section 4.1.1: - The client MUST include its hardware address in the ’chaddr’ field, if - necessary for delivery of DHCP reply messages. Non-Ethernet - interfaces will leave 'chaddr' empty and use the client identifier - instead (eg, RFC 4390 section 2.1). - */ - if (client->arp_type == ARPHRD_ETHER) - memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN); - - /* If no client identifier exists, construct an RFC 4361-compliant one */ - if (client->client_id_len == 0) { - size_t duid_len; - - client->client_id.type = 255; - - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, - true, &client->client_id.ns.iaid); - if (r < 0) - return r; - - r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len); - if (r < 0) - return r; - - client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len; - } - - /* Some DHCP servers will refuse to issue an DHCP lease if the Client - Identifier option is not set */ - if (client->client_id_len) { - r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_CLIENT_IDENTIFIER, - client->client_id_len, - &client->client_id); - if (r < 0) - return r; - } - - /* RFC2131 section 3.5: - in its initial DHCPDISCOVER or DHCPREQUEST message, a - client may provide the server with a list of specific - parameters the client is interested in. If the client - includes a list of parameters in a DHCPDISCOVER message, - it MUST include that list in any subsequent DHCPREQUEST - messages. - */ - - /* RFC7844 section 3: - MAY contain the Parameter Request List option. */ - /* NOTE: in case that there would be an option to do not send - * any PRL at all, the size should be checked before sending */ - if (!set_isempty(client->req_opts) && type != DHCP_RELEASE) { - _cleanup_free_ uint8_t *opts = NULL; - size_t n_opts, i = 0; - void *val; - - n_opts = set_size(client->req_opts); - opts = new(uint8_t, n_opts); - if (!opts) - return -ENOMEM; - - SET_FOREACH(val, client->req_opts) - opts[i++] = PTR_TO_UINT8(val); - assert(i == n_opts); - - /* For anonymizing the request, let's sort the options. */ - typesafe_qsort(opts, n_opts, cmp_uint8); - - r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, - n_opts, opts); - if (r < 0) - return r; - } - - /* RFC2131 section 3.5: - The client SHOULD include the ’maximum DHCP message size’ option to - let the server know how large the server may make its DHCP messages. - - Note (from ConnMan): Some DHCP servers will send bigger DHCP packets - than the defined default size unless the Maximum Message Size option - is explicitly set - - RFC3442 "Requirements to Avoid Sizing Constraints": - Because a full routing table can be quite large, the standard 576 - octet maximum size for a DHCP message may be too short to contain - some legitimate Classless Static Route options. Because of this, - clients implementing the Classless Static Route option SHOULD send a - Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP - stack is capable of receiving larger IP datagrams. In this case, the - client SHOULD set the value of this option to at least the MTU of the - interface that the client is configuring. The client MAY set the - value of this option higher, up to the size of the largest UDP packet - it is prepared to accept. (Note that the value specified in the - Maximum DHCP Message Size option is the total maximum packet size, - including IP and UDP headers.) - */ - /* RFC7844 section 3: - SHOULD NOT contain any other option. */ - if (!client->anonymize && type != DHCP_RELEASE) { - max_size = htobe16(size); - r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0, - SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, - 2, &max_size); - if (r < 0) - return r; - } - - *_optlen = optlen; - *_optoffset = optoffset; - *ret = TAKE_PTR(packet); - - return 0; -} - -static int client_append_fqdn_option( - DHCPMessage *message, - size_t optlen, - size_t *optoffset, - const char *fqdn) { - - uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; - int r; - - buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */ - DHCP_FQDN_FLAG_E; /* Canonical wire format */ - buffer[1] = 0; /* RCODE1 (deprecated) */ - buffer[2] = 0; /* RCODE2 (deprecated) */ - - r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false); - if (r > 0) - r = dhcp_option_append(message, optlen, optoffset, 0, - SD_DHCP_OPTION_FQDN, 3 + r, buffer); - - return r; -} - -static int dhcp_client_send_raw( - sd_dhcp_client *client, - DHCPPacket *packet, - size_t len) { - - dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port, - INADDR_BROADCAST, DHCP_PORT_SERVER, len, client->ip_service_type); - - return dhcp_network_send_raw_socket(client->fd, &client->link, - packet, len); -} - -static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) { - sd_dhcp_option *j; - int r; - - assert(client); - - if (client->hostname) { - /* According to RFC 4702 "clients that send the Client FQDN option in - their messages MUST NOT also send the Host Name option". Just send - one of the two depending on the hostname type. - */ - if (dns_name_is_single_label(client->hostname)) { - /* it is unclear from RFC 2131 if client should send hostname in - DHCPDISCOVER but dhclient does and so we do as well - */ - r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, - SD_DHCP_OPTION_HOST_NAME, - strlen(client->hostname), client->hostname); - } else - r = client_append_fqdn_option(&packet->dhcp, optlen, optoffset, - client->hostname); - if (r < 0) - return r; - } - - if (client->vendor_class_identifier) { - r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, - SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, - strlen(client->vendor_class_identifier), - client->vendor_class_identifier); - if (r < 0) - return r; - } - - if (client->mudurl) { - r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, - SD_DHCP_OPTION_MUD_URL, - strlen(client->mudurl), - client->mudurl); - if (r < 0) - return r; - } - - if (client->user_class) { - r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, - SD_DHCP_OPTION_USER_CLASS, - strv_length(client->user_class), - client->user_class); - if (r < 0) - return r; - } - - ORDERED_HASHMAP_FOREACH(j, client->extra_options) { - r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, - j->option, j->length, j->data); - if (r < 0) - return r; - } - - if (!ordered_hashmap_isempty(client->vendor_options)) { - r = dhcp_option_append( - &packet->dhcp, optlen, optoffset, 0, - SD_DHCP_OPTION_VENDOR_SPECIFIC, - ordered_hashmap_size(client->vendor_options), client->vendor_options); - if (r < 0) - return r; - } - - - return 0; -} - -static int client_send_discover(sd_dhcp_client *client) { - _cleanup_free_ DHCPPacket *discover = NULL; - size_t optoffset, optlen; - int r; - - assert(client); - assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING)); - - r = client_message_init(client, &discover, DHCP_DISCOVER, - &optlen, &optoffset); - if (r < 0) - return r; - - /* the client may suggest values for the network address - and lease time in the DHCPDISCOVER message. The client may include - the ’requested IP address’ option to suggest that a particular IP - address be assigned, and may include the ’IP address lease time’ - option to suggest the lease time it would like. - */ - /* RFC7844 section 3: - SHOULD NOT contain any other option. */ - if (!client->anonymize && client->last_addr != INADDR_ANY) { - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, - 4, &client->last_addr); - if (r < 0) - return r; - } - - r = client_append_common_discover_request_options(client, discover, &optoffset, optlen); - if (r < 0) - return r; - - r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - /* We currently ignore: - The client SHOULD wait a random time between one and ten seconds to - desynchronize the use of DHCP at startup. - */ - r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset); - if (r < 0) - return r; - - log_dhcp_client(client, "DISCOVER"); - - return 0; -} - -static int client_send_request(sd_dhcp_client *client) { - _cleanup_free_ DHCPPacket *request = NULL; - size_t optoffset, optlen; - int r; - - assert(client); - - r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset); - if (r < 0) - return r; - - switch (client->state) { - /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC, - SELECTING should be REQUESTING) - */ - - case DHCP_STATE_REQUESTING: - /* Client inserts the address of the selected server in ’server - identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be - filled in with the yiaddr value from the chosen DHCPOFFER. - */ - - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_SERVER_IDENTIFIER, - 4, &client->lease->server_address); - if (r < 0) - return r; - - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, - 4, &client->lease->address); - if (r < 0) - return r; - - break; - - case DHCP_STATE_INIT_REBOOT: - /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ - option MUST be filled in with client’s notion of its previously - assigned address. ’ciaddr’ MUST be zero. - */ - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, - 4, &client->last_addr); - if (r < 0) - return r; - break; - - case DHCP_STATE_RENEWING: - /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ - option MUST NOT be filled in, ’ciaddr’ MUST be filled in with - client’s IP address. - */ - - case DHCP_STATE_REBINDING: - /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ - option MUST NOT be filled in, ’ciaddr’ MUST be filled in with - client’s IP address. - - This message MUST be broadcast to the 0xffffffff IP broadcast address. - */ - request->dhcp.ciaddr = client->lease->address; - - break; - - case DHCP_STATE_INIT: - case DHCP_STATE_SELECTING: - case DHCP_STATE_REBOOTING: - case DHCP_STATE_BOUND: - case DHCP_STATE_STOPPED: - return -EINVAL; - } - - r = client_append_common_discover_request_options(client, request, &optoffset, optlen); - if (r < 0) - return r; - - r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - if (client->state == DHCP_STATE_RENEWING) - r = dhcp_network_send_udp_socket(client->fd, - client->lease->server_address, - DHCP_PORT_SERVER, - &request->dhcp, - sizeof(DHCPMessage) + optoffset); - else - r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset); - if (r < 0) - return r; - - switch (client->state) { - - case DHCP_STATE_REQUESTING: - log_dhcp_client(client, "REQUEST (requesting)"); - break; - - case DHCP_STATE_INIT_REBOOT: - log_dhcp_client(client, "REQUEST (init-reboot)"); - break; - - case DHCP_STATE_RENEWING: - log_dhcp_client(client, "REQUEST (renewing)"); - break; - - case DHCP_STATE_REBINDING: - log_dhcp_client(client, "REQUEST (rebinding)"); - break; - - default: - log_dhcp_client(client, "REQUEST (invalid)"); - break; - } - - return 0; -} - -static int client_start(sd_dhcp_client *client); - -static int client_timeout_resend( - sd_event_source *s, - uint64_t usec, - void *userdata) { - - sd_dhcp_client *client = userdata; - DHCP_CLIENT_DONT_DESTROY(client); - usec_t next_timeout; - uint64_t time_now; - int r; - - assert(s); - assert(client); - assert(client->event); - - r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - goto error; - - switch (client->state) { - - case DHCP_STATE_RENEWING: - next_timeout = client_compute_reacquisition_timeout(time_now, client->t2_time); - break; - - case DHCP_STATE_REBINDING: - next_timeout = client_compute_reacquisition_timeout(time_now, client->expire_time); - break; - - case DHCP_STATE_REBOOTING: - /* start over as we did not receive a timely ack or nak */ - r = client_initialize(client); - if (r < 0) - goto error; - - r = client_start(client); - if (r < 0) - goto error; - - log_dhcp_client(client, "REBOOTED"); - return 0; - - case DHCP_STATE_INIT: - case DHCP_STATE_INIT_REBOOT: - case DHCP_STATE_SELECTING: - case DHCP_STATE_REQUESTING: - case DHCP_STATE_BOUND: - if (client->attempt >= client->max_attempts) - goto error; - - client->attempt++; - next_timeout = client_compute_request_timeout(time_now, client->attempt); - break; - - case DHCP_STATE_STOPPED: - r = -EINVAL; - goto error; - - default: - assert_not_reached("Unhandled choice"); - } - - r = event_reset_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), - next_timeout, 10 * USEC_PER_MSEC, - client_timeout_resend, client, - client->event_priority, "dhcp4-resend-timer", true); - if (r < 0) - goto error; - - switch (client->state) { - case DHCP_STATE_INIT: - r = client_send_discover(client); - if (r >= 0) { - client->state = DHCP_STATE_SELECTING; - client->attempt = 0; - } else if (client->attempt >= client->max_attempts) - goto error; - - break; - - case DHCP_STATE_SELECTING: - r = client_send_discover(client); - if (r < 0 && client->attempt >= client->max_attempts) - goto error; - - break; - - case DHCP_STATE_INIT_REBOOT: - case DHCP_STATE_REQUESTING: - case DHCP_STATE_RENEWING: - case DHCP_STATE_REBINDING: - r = client_send_request(client); - if (r < 0 && client->attempt >= client->max_attempts) - goto error; - - if (client->state == DHCP_STATE_INIT_REBOOT) - client->state = DHCP_STATE_REBOOTING; - - client->request_sent = time_now; - break; - - case DHCP_STATE_REBOOTING: - case DHCP_STATE_BOUND: - break; - - case DHCP_STATE_STOPPED: - r = -EINVAL; - goto error; - } - - if (client->attempt >= TRANSIENT_FAILURE_ATTEMPTS) - client_notify(client, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE); - - return 0; - -error: - client_stop(client, r); - - /* Errors were dealt with when stopping the client, don't spill - errors into the event loop handler */ - return 0; -} - -static int client_initialize_io_events( - sd_dhcp_client *client, - sd_event_io_handler_t io_callback) { - - int r; - - assert(client); - assert(client->event); - - r = sd_event_add_io(client->event, &client->receive_message, - client->fd, EPOLLIN, io_callback, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->receive_message, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message"); - if (r < 0) - goto error; - -error: - if (r < 0) - client_stop(client, r); - - return 0; -} - -static int client_initialize_time_events(sd_dhcp_client *client) { - uint64_t usec = 0; - int r; - - assert(client); - assert(client->event); - - if (client->start_delay > 0) { - assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); - usec += client->start_delay; - } - - r = event_reset_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), - usec, 0, - client_timeout_resend, client, - client->event_priority, "dhcp4-resend-timer", true); - if (r < 0) - client_stop(client, r); - - return 0; - -} - -static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) { - client_initialize_io_events(client, io_callback); - client_initialize_time_events(client); - - return 0; -} - -static int client_start_delayed(sd_dhcp_client *client) { - int r; - - assert_return(client, -EINVAL); - assert_return(client->event, -EINVAL); - assert_return(client->ifindex > 0, -EINVAL); - assert_return(client->fd < 0, -EBUSY); - assert_return(client->xid == 0, -EINVAL); - assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT), -EBUSY); - - client->xid = random_u32(); - - r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, - client->mac_addr, client->mac_addr_len, - client->bcast_addr, client->bcast_addr_len, - client->arp_type, client->port); - if (r < 0) { - client_stop(client, r); - return r; - } - client->fd = r; - - if (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT)) - client->start_time = now(clock_boottime_or_monotonic()); - - return client_initialize_events(client, client_receive_message_raw); -} - -static int client_start(sd_dhcp_client *client) { - client->start_delay = 0; - return client_start_delayed(client); -} - -static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { - sd_dhcp_client *client = userdata; - DHCP_CLIENT_DONT_DESTROY(client); - - log_dhcp_client(client, "EXPIRED"); - - client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); - - /* lease was lost, start over if not freed or stopped in callback */ - if (client->state != DHCP_STATE_STOPPED) { - client_initialize(client); - client_start(client); - } - - return 0; -} - -static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { - sd_dhcp_client *client = userdata; - DHCP_CLIENT_DONT_DESTROY(client); - int r; - - assert(client); - - client->receive_message = sd_event_source_unref(client->receive_message); - client->fd = safe_close(client->fd); - - client->state = DHCP_STATE_REBINDING; - client->attempt = 0; - - r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, - client->mac_addr, client->mac_addr_len, - client->bcast_addr, client->bcast_addr_len, - client->arp_type, client->port); - if (r < 0) { - client_stop(client, r); - return 0; - } - client->fd = r; - - return client_initialize_events(client, client_receive_message_raw); -} - -static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { - sd_dhcp_client *client = userdata; - DHCP_CLIENT_DONT_DESTROY(client); - - if (client->lease) - client->state = DHCP_STATE_RENEWING; - else if (client->state != DHCP_STATE_INIT) - client->state = DHCP_STATE_INIT_REBOOT; - client->attempt = 0; - - return client_initialize_time_events(client); -} - -static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) { - _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; - int r; - - r = dhcp_lease_new(&lease); - if (r < 0) - return r; - - if (client->client_id_len) { - r = dhcp_lease_set_client_id(lease, - (uint8_t *) &client->client_id, - client->client_id_len); - if (r < 0) - return r; - } - - r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL); - if (r != DHCP_OFFER) { - log_dhcp_client(client, "received message was not an OFFER, ignoring"); - return -ENOMSG; - } - - lease->next_server = offer->siaddr; - lease->address = offer->yiaddr; - - if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0) - lease->lifetime = client->fallback_lease_lifetime; - - if (lease->address == 0 || - lease->server_address == 0 || - lease->lifetime == 0) { - log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring"); - return -ENOMSG; - } - - if (!lease->have_subnet_mask) { - r = dhcp_lease_set_default_subnet_mask(lease); - if (r < 0) { - log_dhcp_client(client, - "received lease lacks subnet mask, " - "and a fallback one cannot be generated, ignoring"); - return -ENOMSG; - } - } - - sd_dhcp_lease_unref(client->lease); - client->lease = TAKE_PTR(lease); - - if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0) - return -ENOMSG; - - log_dhcp_client(client, "OFFER"); - - return 0; -} - -static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) { - int r; - - r = dhcp_option_parse(force, len, NULL, NULL, NULL); - if (r != DHCP_FORCERENEW) - return -ENOMSG; - - log_dhcp_client(client, "FORCERENEW"); - - return 0; -} - -static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) { - if (a->address != b->address) - return false; - - if (a->subnet_mask != b->subnet_mask) - return false; - - if (a->router_size != b->router_size) - return false; - - for (size_t i = 0; i < a->router_size; i++) - if (a->router[i].s_addr != b->router[i].s_addr) - return false; - - return true; -} - -static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) { - _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; - _cleanup_free_ char *error_message = NULL; - int r; - - r = dhcp_lease_new(&lease); - if (r < 0) - return r; - - if (client->client_id_len) { - r = dhcp_lease_set_client_id(lease, - (uint8_t *) &client->client_id, - client->client_id_len); - if (r < 0) - return r; - } - - r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message); - if (r == DHCP_NAK) { - log_dhcp_client(client, "NAK: %s", strna(error_message)); - return -EADDRNOTAVAIL; - } - - if (r != DHCP_ACK) { - log_dhcp_client(client, "received message was not an ACK, ignoring"); - return -ENOMSG; - } - - lease->next_server = ack->siaddr; - - lease->address = ack->yiaddr; - - if (lease->address == INADDR_ANY || - lease->server_address == INADDR_ANY || - lease->lifetime == 0) { - log_dhcp_client(client, "received lease lacks address, server " - "address or lease lifetime, ignoring"); - return -ENOMSG; - } - - if (lease->subnet_mask == INADDR_ANY) { - r = dhcp_lease_set_default_subnet_mask(lease); - if (r < 0) { - log_dhcp_client(client, - "received lease lacks subnet mask, " - "and a fallback one cannot be generated, ignoring"); - return -ENOMSG; - } - } - - r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; - if (client->lease) { - if (lease_equal(client->lease, lease)) - r = SD_DHCP_CLIENT_EVENT_RENEW; - else - r = SD_DHCP_CLIENT_EVENT_IP_CHANGE; - - client->lease = sd_dhcp_lease_unref(client->lease); - } - - client->lease = TAKE_PTR(lease); - - log_dhcp_client(client, "ACK"); - - return r; -} - -static int client_set_lease_timeouts(sd_dhcp_client *client) { - usec_t time_now; - char time_string[FORMAT_TIMESPAN_MAX]; - int r; - - assert(client); - assert(client->event); - assert(client->lease); - assert(client->lease->lifetime); - - /* don't set timers for infinite leases */ - if (client->lease->lifetime == 0xffffffff) { - (void) event_source_disable(client->timeout_t1); - (void) event_source_disable(client->timeout_t2); - (void) event_source_disable(client->timeout_expire); - - return 0; - } - - r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return r; - assert(client->request_sent <= time_now); - - /* verify that 0 < t2 < lifetime */ - if (client->lease->t2 == 0 || client->lease->t2 >= client->lease->lifetime) - client->lease->t2 = T2_DEFAULT(client->lease->lifetime); - /* verify that 0 < t1 < lifetime */ - if (client->lease->t1 == 0 || client->lease->t1 >= client->lease->t2) - client->lease->t1 = T1_DEFAULT(client->lease->lifetime); - /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check - * could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT - * guarantees t1 < t2. */ - if (client->lease->t1 >= client->lease->t2) - client->lease->t2 = T2_DEFAULT(client->lease->lifetime); - - client->expire_time = client->request_sent + client->lease->lifetime * USEC_PER_SEC; - client->t1_time = client->request_sent + client->lease->t1 * USEC_PER_SEC; - client->t2_time = client->request_sent + client->lease->t2 * USEC_PER_SEC; - - /* RFC2131 section 4.4.5: - * Times T1 and T2 SHOULD be chosen with some random "fuzz". - * Since the RFC doesn't specify here the exact 'fuzz' to use, - * we use the range from section 4.1: -1 to +1 sec. */ - client->t1_time = usec_sub_signed(client->t1_time, RFC2131_RANDOM_FUZZ); - client->t2_time = usec_sub_signed(client->t2_time, RFC2131_RANDOM_FUZZ); - - /* after fuzzing, ensure t2 is still >= t1 */ - client->t2_time = MAX(client->t1_time, client->t2_time); - - /* arm lifetime timeout */ - r = event_reset_time(client->event, &client->timeout_expire, - clock_boottime_or_monotonic(), - client->expire_time, 10 * USEC_PER_MSEC, - client_timeout_expire, client, - client->event_priority, "dhcp4-lifetime", true); - if (r < 0) - return r; - - /* don't arm earlier timeouts if this has already expired */ - if (client->expire_time <= time_now) - return 0; - - log_dhcp_client(client, "lease expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->expire_time - time_now, USEC_PER_SEC)); - - /* arm T2 timeout */ - r = event_reset_time(client->event, &client->timeout_t2, - clock_boottime_or_monotonic(), - client->t2_time, 10 * USEC_PER_MSEC, - client_timeout_t2, client, - client->event_priority, "dhcp4-t2-timeout", true); - if (r < 0) - return r; - - /* don't arm earlier timeout if this has already expired */ - if (client->t2_time <= time_now) - return 0; - - log_dhcp_client(client, "T2 expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->t2_time - time_now, USEC_PER_SEC)); - - /* arm T1 timeout */ - r = event_reset_time(client->event, &client->timeout_t1, - clock_boottime_or_monotonic(), - client->t1_time, 10 * USEC_PER_MSEC, - client_timeout_t1, client, - client->event_priority, "dhcp4-t1-timer", true); - if (r < 0) - return r; - - if (client->t1_time > time_now) - log_dhcp_client(client, "T1 expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->t1_time - time_now, USEC_PER_SEC)); - - return 0; -} - -static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) { - DHCP_CLIENT_DONT_DESTROY(client); - char time_string[FORMAT_TIMESPAN_MAX]; - int r = 0, notify_event = 0; - - assert(client); - assert(client->event); - assert(message); - - switch (client->state) { - case DHCP_STATE_SELECTING: - - r = client_handle_offer(client, message, len); - if (r >= 0) { - - client->state = DHCP_STATE_REQUESTING; - client->attempt = 0; - - r = event_reset_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), - 0, 0, - client_timeout_resend, client, - client->event_priority, "dhcp4-resend-timer", true); - if (r < 0) - goto error; - } else if (r == -ENOMSG) - /* invalid message, let's ignore it */ - return 0; - - break; - - case DHCP_STATE_REBOOTING: - case DHCP_STATE_REQUESTING: - case DHCP_STATE_RENEWING: - case DHCP_STATE_REBINDING: - - r = client_handle_ack(client, message, len); - if (r >= 0) { - client->start_delay = 0; - (void) event_source_disable(client->timeout_resend); - client->receive_message = - sd_event_source_unref(client->receive_message); - client->fd = safe_close(client->fd); - - if (IN_SET(client->state, DHCP_STATE_REQUESTING, - DHCP_STATE_REBOOTING)) - notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; - else if (r != SD_DHCP_CLIENT_EVENT_IP_ACQUIRE) - notify_event = r; - - client->state = DHCP_STATE_BOUND; - client->attempt = 0; - - client->last_addr = client->lease->address; - - r = client_set_lease_timeouts(client); - if (r < 0) { - log_dhcp_client(client, "could not set lease timeouts"); - goto error; - } - - r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port, client->ip_service_type); - if (r < 0) { - log_dhcp_client(client, "could not bind UDP socket"); - goto error; - } - - client->fd = r; - - client_initialize_io_events(client, client_receive_message_udp); - - if (notify_event) { - client_notify(client, notify_event); - if (client->state == DHCP_STATE_STOPPED) - return 0; - } - - } else if (r == -EADDRNOTAVAIL) { - /* got a NAK, let's restart the client */ - client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); - - r = client_initialize(client); - if (r < 0) - goto error; - - r = client_start_delayed(client); - if (r < 0) - goto error; - - log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, - client->start_delay, USEC_PER_SEC)); - - client->start_delay = CLAMP(client->start_delay * 2, - RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC); - - return 0; - } else if (r == -ENOMSG) - /* invalid message, let's ignore it */ - return 0; - - break; - - case DHCP_STATE_BOUND: - r = client_handle_forcerenew(client, message, len); - if (r >= 0) { - r = client_timeout_t1(NULL, 0, client); - if (r < 0) - goto error; - } else if (r == -ENOMSG) - /* invalid message, let's ignore it */ - return 0; - - break; - - case DHCP_STATE_INIT: - case DHCP_STATE_INIT_REBOOT: - - break; - - case DHCP_STATE_STOPPED: - r = -EINVAL; - goto error; - } - -error: - if (r < 0) - client_stop(client, r); - - return r; -} - -static int client_receive_message_udp( - sd_event_source *s, - int fd, - uint32_t revents, - void *userdata) { - - sd_dhcp_client *client = userdata; - _cleanup_free_ DHCPMessage *message = NULL; - const uint8_t *expected_chaddr = NULL; - uint8_t expected_hlen = 0; - ssize_t len, buflen; - - assert(s); - assert(client); - - buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - /* the link is down. Don't return an error or the I/O event - source will be disconnected and we won't be able to receive - packets again when the link comes back. */ - return 0; - if (buflen < 0) - return buflen; - - message = malloc0(buflen); - if (!message) - return -ENOMEM; - - len = recv(fd, message, buflen, 0); - if (len < 0) { - /* see comment above for why we shouldn't error out on ENETDOWN. */ - if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) - return 0; - - return log_dhcp_client_errno(client, errno, - "Could not receive message from UDP socket: %m"); - } - if ((size_t) len < sizeof(DHCPMessage)) { - log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); - return 0; - } - - if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) { - log_dhcp_client(client, "Not a DHCP message: ignoring"); - return 0; - } - - if (message->op != BOOTREPLY) { - log_dhcp_client(client, "Not a BOOTREPLY message: ignoring"); - return 0; - } - - if (message->htype != client->arp_type) { - log_dhcp_client(client, "Packet type does not match client type"); - return 0; - } - - if (client->arp_type == ARPHRD_ETHER) { - expected_hlen = ETH_ALEN; - expected_chaddr = &client->mac_addr[0]; - } - - if (message->hlen != expected_hlen) { - log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen); - return 0; - } - - if (expected_hlen > 0 && memcmp(&message->chaddr[0], expected_chaddr, expected_hlen)) { - log_dhcp_client(client, "Received chaddr does not match expected: ignoring"); - return 0; - } - - if (client->state != DHCP_STATE_BOUND && - be32toh(message->xid) != client->xid) { - /* in BOUND state, we may receive FORCERENEW with xid set by server, - so ignore the xid in this case */ - log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring", - be32toh(message->xid), client->xid); - return 0; - } - - return client_handle_message(client, message, len); -} - -static int client_receive_message_raw( - sd_event_source *s, - int fd, - uint32_t revents, - void *userdata) { - - sd_dhcp_client *client = userdata; - _cleanup_free_ DHCPPacket *packet = NULL; - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata))) control; - struct iovec iov = {}; - struct msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg; - bool checksum = true; - ssize_t buflen, len; - int r; - - assert(s); - assert(client); - - buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - return 0; - if (buflen < 0) - return buflen; - - packet = malloc0(buflen); - if (!packet) - return -ENOMEM; - - iov = IOVEC_MAKE(packet, buflen); - - len = recvmsg_safe(fd, &msg, 0); - if (IN_SET(len, -EAGAIN, -EINTR, -ENETDOWN)) - return 0; - if (len < 0) - return log_dhcp_client_errno(client, len, - "Could not receive message from raw socket: %m"); - - if ((size_t) len < sizeof(DHCPPacket)) - return 0; - - cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata))); - if (cmsg) { - struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg); - checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); - } - - r = dhcp_packet_verify_headers(packet, len, checksum, client->port); - if (r < 0) - return 0; - - len -= DHCP_IP_UDP_SIZE; - - return client_handle_message(client, &packet->dhcp, len); -} - -int sd_dhcp_client_send_renew(sd_dhcp_client *client) { - assert_return(client, -EINVAL); - assert_return(client->fd >= 0, -EINVAL); - - if (!client->lease) - return 0; - - client->start_delay = 0; - client->attempt = 1; - client->state = DHCP_STATE_RENEWING; - - return client_initialize_time_events(client); -} - -int sd_dhcp_client_start(sd_dhcp_client *client) { - int r; - - assert_return(client, -EINVAL); - - r = client_initialize(client); - if (r < 0) - return r; - - /* RFC7844 section 3.3: - SHOULD perform a complete four-way handshake, starting with a - DHCPDISCOVER, to obtain a new address lease. If the client can - ascertain that this is exactly the same network to which it was - previously connected, and if the link-layer address did not change, - the client MAY issue a DHCPREQUEST to try to reclaim the current - address. */ - if (client->last_addr && !client->anonymize) - client->state = DHCP_STATE_INIT_REBOOT; - - r = client_start(client); - if (r >= 0) - log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex); - - return r; -} - -int sd_dhcp_client_send_release(sd_dhcp_client *client) { - assert_return(client, -EINVAL); - assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE); - assert_return(client->lease, -EUNATCH); - - _cleanup_free_ DHCPPacket *release = NULL; - size_t optoffset, optlen; - int r; - - r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset); - if (r < 0) - return r; - - /* Fill up release IP and MAC */ - release->dhcp.ciaddr = client->lease->address; - memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); - - r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - r = dhcp_network_send_udp_socket(client->fd, - client->lease->server_address, - DHCP_PORT_SERVER, - &release->dhcp, - sizeof(DHCPMessage) + optoffset); - if (r < 0) - return r; - - log_dhcp_client(client, "RELEASE"); - - return 0; -} - -int sd_dhcp_client_send_decline(sd_dhcp_client *client) { - assert_return(client, -EINVAL); - assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE); - assert_return(client->lease, -EUNATCH); - - _cleanup_free_ DHCPPacket *release = NULL; - size_t optoffset, optlen; - int r; - - r = client_message_init(client, &release, DHCP_DECLINE, &optlen, &optoffset); - if (r < 0) - return r; - - release->dhcp.ciaddr = client->lease->address; - memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); - - r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - r = dhcp_network_send_udp_socket(client->fd, - client->lease->server_address, - DHCP_PORT_SERVER, - &release->dhcp, - sizeof(DHCPMessage) + optoffset); - if (r < 0) - return r; - - log_dhcp_client(client, "DECLINE"); - - client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - - if (client->state != DHCP_STATE_STOPPED) { - r = sd_dhcp_client_start(client); - if (r < 0) - return r; - } - - return 0; -} - -int sd_dhcp_client_stop(sd_dhcp_client *client) { - if (!client) - return 0; - - DHCP_CLIENT_DONT_DESTROY(client); - - client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - client->state = DHCP_STATE_STOPPED; - - return 0; -} - -int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) { - int r; - - assert_return(client, -EINVAL); - assert_return(!client->event, -EBUSY); - - if (event) - client->event = sd_event_ref(event); - else { - r = sd_event_default(&client->event); - if (r < 0) - return 0; - } - - client->event_priority = priority; - - return 0; -} - -int sd_dhcp_client_detach_event(sd_dhcp_client *client) { - assert_return(client, -EINVAL); - - client->event = sd_event_unref(client->event); - - return 0; -} - -sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { - assert_return(client, NULL); - - return client->event; -} - -static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { - if (!client) - return NULL; - - log_dhcp_client(client, "FREE"); - - client->timeout_resend = sd_event_source_unref(client->timeout_resend); - client->timeout_t1 = sd_event_source_unref(client->timeout_t1); - client->timeout_t2 = sd_event_source_unref(client->timeout_t2); - client->timeout_expire = sd_event_source_unref(client->timeout_expire); - - client_initialize(client); - - sd_dhcp_client_detach_event(client); - - sd_dhcp_lease_unref(client->lease); - - set_free(client->req_opts); - free(client->hostname); - free(client->vendor_class_identifier); - free(client->mudurl); - client->user_class = strv_free(client->user_class); - ordered_hashmap_free(client->extra_options); - ordered_hashmap_free(client->vendor_options); - return mfree(client); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free); - -int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { - const uint8_t *opts; - size_t n_opts; - int r; - - assert_return(ret, -EINVAL); - - _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1); - if (!client) - return -ENOMEM; - - *client = (sd_dhcp_client) { - .n_ref = 1, - .state = DHCP_STATE_INIT, - .ifindex = -1, - .fd = -1, - .mtu = DHCP_DEFAULT_MIN_SIZE, - .port = DHCP_PORT_CLIENT, - .anonymize = !!anonymize, - .max_attempts = (uint64_t) -1, - .ip_service_type = -1, - }; - /* NOTE: this could be moved to a function. */ - if (anonymize) { - n_opts = ELEMENTSOF(default_req_opts_anonymize); - opts = default_req_opts_anonymize; - } else { - n_opts = ELEMENTSOF(default_req_opts); - opts = default_req_opts; - } - - for (size_t i = 0; i < n_opts; i++) { - r = sd_dhcp_client_set_request_option(client, opts[i]); - if (r < 0) - return r; - } - - *ret = TAKE_PTR(client); - - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c deleted file mode 100644 index 94b0d35c..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2013 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include -#include -#include - -#include "sd-dhcp-lease.h" - -#include "alloc-util.h" -#include "dhcp-lease-internal.h" -#include "dhcp-protocol.h" -#include "dns-domain.h" -#include "env-file.h" -#include "fd-util.h" -#include "fileio.h" -#include "hexdecoct.h" -#include "hostname-util.h" -#include "in-addr-util.h" -#include "network-internal.h" -#include "parse-util.h" -#include "stdio-util.h" -#include "string-util.h" -#include "strv.h" -#include "tmpfile-util.h" -#include "unaligned.h" - -int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->address == 0) - return -ENODATA; - - addr->s_addr = lease->address; - return 0; -} - -int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (!lease->have_broadcast) - return -ENODATA; - - addr->s_addr = lease->broadcast; - return 0; -} - -int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) { - assert_return(lease, -EINVAL); - assert_return(lifetime, -EINVAL); - - if (lease->lifetime <= 0) - return -ENODATA; - - *lifetime = lease->lifetime; - return 0; -} - -int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) { - assert_return(lease, -EINVAL); - assert_return(t1, -EINVAL); - - if (lease->t1 <= 0) - return -ENODATA; - - *t1 = lease->t1; - return 0; -} - -int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) { - assert_return(lease, -EINVAL); - assert_return(t2, -EINVAL); - - if (lease->t2 <= 0) - return -ENODATA; - - *t2 = lease->t2; - return 0; -} - -int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) { - assert_return(lease, -EINVAL); - assert_return(mtu, -EINVAL); - - if (lease->mtu <= 0) - return -ENODATA; - - *mtu = lease->mtu; - return 0; -} - -int sd_dhcp_lease_get_servers( - sd_dhcp_lease *lease, - sd_dhcp_lease_server_type what, - const struct in_addr **addr) { - - assert_return(lease, -EINVAL); - assert_return(what >= 0, -EINVAL); - assert_return(what < _SD_DHCP_LEASE_SERVER_TYPE_MAX, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->servers[what].size <= 0) - return -ENODATA; - - *addr = lease->servers[what].addr; - return (int) lease->servers[what].size; -} - -int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { - return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr); -} -int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { - return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr); -} -int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { - return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr); -} -int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr) { - return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr); -} -int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr) { - return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr); -} -int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr) { - return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr); -} - -int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { - assert_return(lease, -EINVAL); - assert_return(domainname, -EINVAL); - - if (!lease->domainname) - return -ENODATA; - - *domainname = lease->domainname; - return 0; -} - -int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) { - assert_return(lease, -EINVAL); - assert_return(hostname, -EINVAL); - - if (!lease->hostname) - return -ENODATA; - - *hostname = lease->hostname; - return 0; -} - -int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) { - assert_return(lease, -EINVAL); - assert_return(root_path, -EINVAL); - - if (!lease->root_path) - return -ENODATA; - - *root_path = lease->root_path; - return 0; -} - -int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->router_size <= 0) - return -ENODATA; - - *addr = lease->router; - return (int) lease->router_size; -} - -int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (!lease->have_subnet_mask) - return -ENODATA; - - addr->s_addr = lease->subnet_mask; - return 0; -} - -int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->server_address == 0) - return -ENODATA; - - addr->s_addr = lease->server_address; - return 0; -} - -int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - - if (lease->next_server == 0) - return -ENODATA; - - addr->s_addr = lease->next_server; - return 0; -} - -/* - * The returned routes array must be freed by the caller. - * Route objects have the same lifetime of the lease and must not be freed. - */ -int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) { - sd_dhcp_route **ret; - unsigned i; - - assert_return(lease, -EINVAL); - assert_return(routes, -EINVAL); - - if (lease->static_route_size <= 0) - return -ENODATA; - - ret = new(sd_dhcp_route *, lease->static_route_size); - if (!ret) - return -ENOMEM; - - for (i = 0; i < lease->static_route_size; i++) - ret[i] = &lease->static_route[i]; - - *routes = ret; - return (int) lease->static_route_size; -} - -int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) { - size_t r; - - assert_return(lease, -EINVAL); - assert_return(domains, -EINVAL); - - r = strv_length(lease->search_domains); - if (r > 0) { - *domains = lease->search_domains; - return (int) r; - } - - return -ENODATA; -} - -int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) { - assert_return(lease, -EINVAL); - assert_return(data, -EINVAL); - assert_return(data_len, -EINVAL); - - if (lease->vendor_specific_len <= 0) - return -ENODATA; - - *data = lease->vendor_specific; - *data_len = lease->vendor_specific_len; - return 0; -} - -static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { - assert(lease); - - while (lease->private_options) { - struct sd_dhcp_raw_option *option = lease->private_options; - - LIST_REMOVE(options, lease->private_options, option); - - free(option->data); - free(option); - } - - free(lease->root_path); - free(lease->router); - free(lease->timezone); - free(lease->hostname); - free(lease->domainname); - - for (sd_dhcp_lease_server_type i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++) - free(lease->servers[i].addr); - - free(lease->static_route); - free(lease->client_id); - free(lease->vendor_specific); - strv_free(lease->search_domains); - return mfree(lease); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_lease, sd_dhcp_lease, dhcp_lease_free); - -static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { - assert(option); - assert(ret); - - if (len != 4) - return -EINVAL; - - *ret = unaligned_read_be32((be32_t*) option); - if (*ret < min) - *ret = min; - - return 0; -} - -static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { - assert(option); - assert(ret); - - if (len != 2) - return -EINVAL; - - *ret = unaligned_read_be16((be16_t*) option); - if (*ret < min) - *ret = min; - - return 0; -} - -static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) { - assert(option); - assert(ret); - - if (len != 4) - return -EINVAL; - - memcpy(ret, option, 4); - return 0; -} - -static int lease_parse_string(const uint8_t *option, size_t len, char **ret) { - assert(option); - assert(ret); - - if (len <= 0) - *ret = mfree(*ret); - else { - char *string; - - /* - * One trailing NUL byte is OK, we don't mind. See: - * https://github.com/systemd/systemd/issues/1337 - */ - if (memchr(option, 0, len - 1)) - return -EINVAL; - - string = memdup_suffix0((const char *) option, len); - if (!string) - return -ENOMEM; - - free_and_replace(*ret, string); - } - - return 0; -} - -static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) { - _cleanup_free_ char *name = NULL, *normalized = NULL; - int r; - - assert(option); - assert(ret); - - r = lease_parse_string(option, len, &name); - if (r < 0) - return r; - if (!name) { - *ret = mfree(*ret); - return 0; - } - - r = dns_name_normalize(name, 0, &normalized); - if (r < 0) - return r; - - if (is_localhost(normalized)) - return -EINVAL; - - if (dns_name_is_root(normalized)) - return -EINVAL; - - free_and_replace(*ret, normalized); - - return 0; -} - -static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { - assert(option || len == 0); - assert(ret); - assert(n_ret); - - if (len <= 0) { - *ret = mfree(*ret); - *n_ret = 0; - } else { - size_t n_addresses; - struct in_addr *addresses; - - if (len % 4 != 0) - return -EINVAL; - - n_addresses = len / 4; - - addresses = newdup(struct in_addr, option, n_addresses); - if (!addresses) - return -ENOMEM; - - free(*ret); - *ret = addresses; - *n_ret = n_addresses; - } - - return 0; -} - -static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { - assert(option || len == 0); - assert(ret); - assert(n_ret); - - if (len <= 0) - return -EINVAL; - - /* The SIP record is like the other, regular server records, but prefixed with a single "encoding" - * byte that is either 0 or 1. We only support it to be 1 for now. Let's drop it and parse it like - * the other fields */ - - if (option[0] != 1) { /* We only support IP address encoding for now */ - *ret = mfree(*ret); - *n_ret = 0; - return 0; - } - - return lease_parse_in_addrs(option + 1, len - 1, ret, n_ret); -} - -static int lease_parse_routes( - const uint8_t *option, size_t len, - struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { - - struct in_addr addr; - - assert(option || len <= 0); - assert(routes); - assert(routes_size); - assert(routes_allocated); - - if (len <= 0) - return 0; - - if (len % 8 != 0) - return -EINVAL; - - if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8))) - return -ENOMEM; - - while (len >= 8) { - struct sd_dhcp_route *route = *routes + *routes_size; - int r; - - route->option = SD_DHCP_OPTION_STATIC_ROUTE; - r = in4_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen); - if (r < 0) { - log_debug("Failed to determine destination prefix length from class based IP, ignoring"); - continue; - } - - assert_se(lease_parse_be32(option, 4, &addr.s_addr) >= 0); - route->dst_addr = inet_makeaddr(inet_netof(addr), 0); - option += 4; - - assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0); - option += 4; - - len -= 8; - (*routes_size)++; - } - - return 0; -} - -/* parses RFC3442 Classless Static Route Option */ -static int lease_parse_classless_routes( - const uint8_t *option, size_t len, - struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { - - assert(option || len <= 0); - assert(routes); - assert(routes_size); - assert(routes_allocated); - - if (len <= 0) - return 0; - - /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */ - - while (len > 0) { - uint8_t dst_octets; - struct sd_dhcp_route *route; - - if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1)) - return -ENOMEM; - - route = *routes + *routes_size; - route->option = SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE; - - dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1); - route->dst_prefixlen = *option; - option++; - len--; - - /* can't have more than 4 octets in IPv4 */ - if (dst_octets > 4 || len < dst_octets) - return -EINVAL; - - route->dst_addr.s_addr = 0; - memcpy(&route->dst_addr.s_addr, option, dst_octets); - option += dst_octets; - len -= dst_octets; - - if (len < 4) - return -EINVAL; - - assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0); - option += 4; - len -= 4; - - (*routes_size)++; - } - - return 0; -} - -int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) { - sd_dhcp_lease *lease = userdata; - int r; - - assert(lease); - - switch(code) { - - case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME: - r = lease_parse_u32(option, len, &lease->lifetime, 1); - if (r < 0) - log_debug_errno(r, "Failed to parse lease time, ignoring: %m"); - - break; - - case SD_DHCP_OPTION_SERVER_IDENTIFIER: - r = lease_parse_be32(option, len, &lease->server_address); - if (r < 0) - log_debug_errno(r, "Failed to parse server identifier, ignoring: %m"); - - break; - - case SD_DHCP_OPTION_SUBNET_MASK: - r = lease_parse_be32(option, len, &lease->subnet_mask); - if (r < 0) - log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m"); - else - lease->have_subnet_mask = true; - break; - - case SD_DHCP_OPTION_BROADCAST: - r = lease_parse_be32(option, len, &lease->broadcast); - if (r < 0) - log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m"); - else - lease->have_broadcast = true; - break; - - case SD_DHCP_OPTION_ROUTER: - r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size); - if (r < 0) - log_debug_errno(r, "Failed to parse router addresses, ignoring: %m"); - break; - - case SD_DHCP_OPTION_DOMAIN_NAME_SERVER: - r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_DNS].addr, &lease->servers[SD_DHCP_LEASE_DNS].size); - if (r < 0) - log_debug_errno(r, "Failed to parse DNS server, ignoring: %m"); - break; - - case SD_DHCP_OPTION_NTP_SERVER: - r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_NTP].addr, &lease->servers[SD_DHCP_LEASE_NTP].size); - if (r < 0) - log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); - break; - - case SD_DHCP_OPTION_SIP_SERVER: - r = lease_parse_sip_server(option, len, &lease->servers[SD_DHCP_LEASE_SIP].addr, &lease->servers[SD_DHCP_LEASE_SIP].size); - if (r < 0) - log_debug_errno(r, "Failed to parse SIP server, ignoring: %m"); - break; - - case SD_DHCP_OPTION_POP3_SERVER: - r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_POP3].addr, &lease->servers[SD_DHCP_LEASE_POP3].size); - if (r < 0) - log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m"); - break; - - case SD_DHCP_OPTION_SMTP_SERVER: - r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_SMTP].addr, &lease->servers[SD_DHCP_LEASE_SMTP].size); - if (r < 0) - log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m"); - break; - - case SD_DHCP_OPTION_LPR_SERVER: - r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_LPR].addr, &lease->servers[SD_DHCP_LEASE_LPR].size); - if (r < 0) - log_debug_errno(r, "Failed to parse LPR server, ignoring: %m"); - break; - - case SD_DHCP_OPTION_STATIC_ROUTE: - r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); - if (r < 0) - log_debug_errno(r, "Failed to parse static routes, ignoring: %m"); - break; - - case SD_DHCP_OPTION_INTERFACE_MTU: - r = lease_parse_u16(option, len, &lease->mtu, 68); - if (r < 0) - log_debug_errno(r, "Failed to parse MTU, ignoring: %m"); - if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) { - log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE); - lease->mtu = DHCP_DEFAULT_MIN_SIZE; - } - - break; - - case SD_DHCP_OPTION_DOMAIN_NAME: - r = lease_parse_domain(option, len, &lease->domainname); - if (r < 0) { - log_debug_errno(r, "Failed to parse domain name, ignoring: %m"); - return 0; - } - - break; - - case SD_DHCP_OPTION_DOMAIN_SEARCH_LIST: - r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains); - if (r < 0) - log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m"); - break; - - case SD_DHCP_OPTION_HOST_NAME: - r = lease_parse_domain(option, len, &lease->hostname); - if (r < 0) { - log_debug_errno(r, "Failed to parse hostname, ignoring: %m"); - return 0; - } - - break; - - case SD_DHCP_OPTION_ROOT_PATH: - r = lease_parse_string(option, len, &lease->root_path); - if (r < 0) - log_debug_errno(r, "Failed to parse root path, ignoring: %m"); - break; - - case SD_DHCP_OPTION_RENEWAL_T1_TIME: - r = lease_parse_u32(option, len, &lease->t1, 1); - if (r < 0) - log_debug_errno(r, "Failed to parse T1 time, ignoring: %m"); - break; - - case SD_DHCP_OPTION_REBINDING_T2_TIME: - r = lease_parse_u32(option, len, &lease->t2, 1); - if (r < 0) - log_debug_errno(r, "Failed to parse T2 time, ignoring: %m"); - break; - - case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: - r = lease_parse_classless_routes( - option, len, - &lease->static_route, - &lease->static_route_size, - &lease->static_route_allocated); - if (r < 0) - log_debug_errno(r, "Failed to parse classless routes, ignoring: %m"); - break; - - case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: { - _cleanup_free_ char *tz = NULL; - - r = lease_parse_string(option, len, &tz); - if (r < 0) { - log_debug_errno(r, "Failed to parse timezone option, ignoring: %m"); - return 0; - } - - if (!timezone_is_valid(tz, LOG_DEBUG)) { - log_debug_errno(r, "Timezone is not valid, ignoring: %m"); - return 0; - } - - free_and_replace(lease->timezone, tz); - - break; - } - - case SD_DHCP_OPTION_VENDOR_SPECIFIC: - - if (len <= 0) - lease->vendor_specific = mfree(lease->vendor_specific); - else { - void *p; - - p = memdup(option, len); - if (!p) - return -ENOMEM; - - free(lease->vendor_specific); - lease->vendor_specific = p; - } - - lease->vendor_specific_len = len; - break; - - case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST: - r = dhcp_lease_insert_private_option(lease, code, option, len); - if (r < 0) - return r; - - break; - - default: - log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code); - break; - } - - return 0; -} - -/* Parses compressed domain names. */ -int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains) { - _cleanup_strv_free_ char **names = NULL; - size_t pos = 0, cnt = 0; - int r; - - assert(domains); - assert_return(option && len > 0, -ENODATA); - - while (pos < len) { - _cleanup_free_ char *name = NULL; - size_t n = 0, allocated = 0; - size_t jump_barrier = pos, next_chunk = 0; - bool first = true; - - for (;;) { - uint8_t c; - c = option[pos++]; - - if (c == 0) { - /* End of name */ - break; - } else if (c <= 63) { - const char *label; - - /* Literal label */ - label = (const char*) (option + pos); - pos += c; - if (pos >= len) - return -EBADMSG; - - if (!GREEDY_REALLOC(name, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) - return -ENOMEM; - - if (first) - first = false; - else - name[n++] = '.'; - - r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX); - if (r < 0) - return r; - - n += r; - } else if (FLAGS_SET(c, 0xc0)) { - /* Pointer */ - - uint8_t d; - uint16_t ptr; - - if (pos >= len) - return -EBADMSG; - - d = option[pos++]; - ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d; - - /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */ - if (ptr >= jump_barrier) - return -EBADMSG; - jump_barrier = ptr; - - /* Save current location so we don't end up re-parsing what's parsed so far. */ - if (next_chunk == 0) - next_chunk = pos; - - pos = ptr; - } else - return -EBADMSG; - } - - if (!GREEDY_REALLOC(name, allocated, n + 1)) - return -ENOMEM; - name[n] = 0; - - r = strv_extend(&names, name); - if (r < 0) - return r; - - cnt++; - - if (next_chunk != 0) - pos = next_chunk; - } - - *domains = TAKE_PTR(names); - - return cnt; -} - -int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) { - struct sd_dhcp_raw_option *cur, *option; - - assert(lease); - - LIST_FOREACH(options, cur, lease->private_options) { - if (tag < cur->tag) - break; - if (tag == cur->tag) { - log_debug("Ignoring duplicate option, tagged %i.", tag); - return 0; - } - } - - option = new(struct sd_dhcp_raw_option, 1); - if (!option) - return -ENOMEM; - - option->tag = tag; - option->length = len; - option->data = memdup(data, len); - if (!option->data) { - free(option); - return -ENOMEM; - } - - LIST_INSERT_BEFORE(options, lease->private_options, cur, option); - return 0; -} - -int dhcp_lease_new(sd_dhcp_lease **ret) { - sd_dhcp_lease *lease; - - lease = new0(sd_dhcp_lease, 1); - if (!lease) - return -ENOMEM; - - lease->n_ref = 1; - - *ret = lease; - return 0; -} - -int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { - _cleanup_free_ char *temp_path = NULL; - _cleanup_fclose_ FILE *f = NULL; - struct sd_dhcp_raw_option *option; - struct in_addr address; - const struct in_addr *addresses; - const void *client_id, *data; - size_t client_id_len, data_len; - char sbuf[INET_ADDRSTRLEN]; - const char *string; - uint16_t mtu; - _cleanup_free_ sd_dhcp_route **routes = NULL; - char **search_domains = NULL; - uint32_t t1, t2, lifetime; - int r; - - assert(lease); - assert(lease_file); - - r = fopen_temporary(lease_file, &f, &temp_path); - if (r < 0) - goto fail; - - (void) fchmod(fileno(f), 0644); - - fprintf(f, - "# This is private data. Do not parse.\n"); - - r = sd_dhcp_lease_get_address(lease, &address); - if (r >= 0) - fprintf(f, "ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); - - r = sd_dhcp_lease_get_netmask(lease, &address); - if (r >= 0) - fprintf(f, "NETMASK=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); - - r = sd_dhcp_lease_get_router(lease, &addresses); - if (r > 0) { - fputs("ROUTER=", f); - serialize_in_addrs(f, addresses, r, false, NULL); - fputc('\n', f); - } - - r = sd_dhcp_lease_get_server_identifier(lease, &address); - if (r >= 0) - fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); - - r = sd_dhcp_lease_get_next_server(lease, &address); - if (r >= 0) - fprintf(f, "NEXT_SERVER=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); - - r = sd_dhcp_lease_get_broadcast(lease, &address); - if (r >= 0) - fprintf(f, "BROADCAST=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); - - r = sd_dhcp_lease_get_mtu(lease, &mtu); - if (r >= 0) - fprintf(f, "MTU=%" PRIu16 "\n", mtu); - - r = sd_dhcp_lease_get_t1(lease, &t1); - if (r >= 0) - fprintf(f, "T1=%" PRIu32 "\n", t1); - - r = sd_dhcp_lease_get_t2(lease, &t2); - if (r >= 0) - fprintf(f, "T2=%" PRIu32 "\n", t2); - - r = sd_dhcp_lease_get_lifetime(lease, &lifetime); - if (r >= 0) - fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime); - - r = sd_dhcp_lease_get_dns(lease, &addresses); - if (r > 0) { - fputs("DNS=", f); - serialize_in_addrs(f, addresses, r, false, NULL); - fputc('\n', f); - } - - r = sd_dhcp_lease_get_ntp(lease, &addresses); - if (r > 0) { - fputs("NTP=", f); - serialize_in_addrs(f, addresses, r, false, NULL); - fputc('\n', f); - } - - r = sd_dhcp_lease_get_sip(lease, &addresses); - if (r > 0) { - fputs("SIP=", f); - serialize_in_addrs(f, addresses, r, false, NULL); - fputc('\n', f); - } - - r = sd_dhcp_lease_get_domainname(lease, &string); - if (r >= 0) - fprintf(f, "DOMAINNAME=%s\n", string); - - r = sd_dhcp_lease_get_search_domains(lease, &search_domains); - if (r > 0) { - fputs("DOMAIN_SEARCH_LIST=", f); - fputstrv(f, search_domains, NULL, NULL); - fputc('\n', f); - } - - r = sd_dhcp_lease_get_hostname(lease, &string); - if (r >= 0) - fprintf(f, "HOSTNAME=%s\n", string); - - r = sd_dhcp_lease_get_root_path(lease, &string); - if (r >= 0) - fprintf(f, "ROOT_PATH=%s\n", string); - - r = sd_dhcp_lease_get_routes(lease, &routes); - if (r > 0) - serialize_dhcp_routes(f, "ROUTES", routes, r); - - r = sd_dhcp_lease_get_timezone(lease, &string); - if (r >= 0) - fprintf(f, "TIMEZONE=%s\n", string); - - r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len); - if (r >= 0) { - _cleanup_free_ char *client_id_hex = NULL; - - client_id_hex = hexmem(client_id, client_id_len); - if (!client_id_hex) { - r = -ENOMEM; - goto fail; - } - fprintf(f, "CLIENTID=%s\n", client_id_hex); - } - - r = sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len); - if (r >= 0) { - _cleanup_free_ char *option_hex = NULL; - - option_hex = hexmem(data, data_len); - if (!option_hex) { - r = -ENOMEM; - goto fail; - } - fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex); - } - - LIST_FOREACH(options, option, lease->private_options) { - char key[STRLEN("OPTION_000")+1]; - - xsprintf(key, "OPTION_%" PRIu8, option->tag); - r = serialize_dhcp_option(f, key, option->data, option->length); - if (r < 0) - goto fail; - } - - r = fflush_and_check(f); - if (r < 0) - goto fail; - - if (rename(temp_path, lease_file) < 0) { - r = -errno; - goto fail; - } - - return 0; - -fail: - if (temp_path) - (void) unlink(temp_path); - - return log_error_errno(r, "Failed to save lease data %s: %m", lease_file); -} - -int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { - - _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; - _cleanup_free_ char - *address = NULL, - *router = NULL, - *netmask = NULL, - *server_address = NULL, - *next_server = NULL, - *broadcast = NULL, - *dns = NULL, - *ntp = NULL, - *sip = NULL, - *pop3 = NULL, - *smtp = NULL, - *lpr = NULL, - *mtu = NULL, - *routes = NULL, - *domains = NULL, - *client_id_hex = NULL, - *vendor_specific_hex = NULL, - *lifetime = NULL, - *t1 = NULL, - *t2 = NULL, - *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {}; - - int r, i; - - assert(lease_file); - assert(ret); - - r = dhcp_lease_new(&lease); - if (r < 0) - return r; - - r = parse_env_file(NULL, lease_file, - "ADDRESS", &address, - "ROUTER", &router, - "NETMASK", &netmask, - "SERVER_ADDRESS", &server_address, - "NEXT_SERVER", &next_server, - "BROADCAST", &broadcast, - "DNS", &dns, - "NTP", &ntp, - "SIP", &sip, - "POP3", &pop3, - "SMTP", &smtp, - "LPR", &lpr, - "MTU", &mtu, - "DOMAINNAME", &lease->domainname, - "HOSTNAME", &lease->hostname, - "DOMAIN_SEARCH_LIST", &domains, - "ROOT_PATH", &lease->root_path, - "ROUTES", &routes, - "CLIENTID", &client_id_hex, - "TIMEZONE", &lease->timezone, - "VENDOR_SPECIFIC", &vendor_specific_hex, - "LIFETIME", &lifetime, - "T1", &t1, - "T2", &t2, - "OPTION_224", &options[0], - "OPTION_225", &options[1], - "OPTION_226", &options[2], - "OPTION_227", &options[3], - "OPTION_228", &options[4], - "OPTION_229", &options[5], - "OPTION_230", &options[6], - "OPTION_231", &options[7], - "OPTION_232", &options[8], - "OPTION_233", &options[9], - "OPTION_234", &options[10], - "OPTION_235", &options[11], - "OPTION_236", &options[12], - "OPTION_237", &options[13], - "OPTION_238", &options[14], - "OPTION_239", &options[15], - "OPTION_240", &options[16], - "OPTION_241", &options[17], - "OPTION_242", &options[18], - "OPTION_243", &options[19], - "OPTION_244", &options[20], - "OPTION_245", &options[21], - "OPTION_246", &options[22], - "OPTION_247", &options[23], - "OPTION_248", &options[24], - "OPTION_249", &options[25], - "OPTION_250", &options[26], - "OPTION_251", &options[27], - "OPTION_252", &options[28], - "OPTION_253", &options[29], - "OPTION_254", &options[30]); - if (r < 0) - return r; - - if (address) { - r = inet_pton(AF_INET, address, &lease->address); - if (r <= 0) - log_debug("Failed to parse address %s, ignoring.", address); - } - - if (router) { - r = deserialize_in_addrs(&lease->router, router); - if (r < 0) - log_debug_errno(r, "Failed to deserialize router addresses %s, ignoring: %m", router); - else - lease->router_size = r; - } - - if (netmask) { - r = inet_pton(AF_INET, netmask, &lease->subnet_mask); - if (r <= 0) - log_debug("Failed to parse netmask %s, ignoring.", netmask); - else - lease->have_subnet_mask = true; - } - - if (server_address) { - r = inet_pton(AF_INET, server_address, &lease->server_address); - if (r <= 0) - log_debug("Failed to parse server address %s, ignoring.", server_address); - } - - if (next_server) { - r = inet_pton(AF_INET, next_server, &lease->next_server); - if (r <= 0) - log_debug("Failed to parse next server %s, ignoring.", next_server); - } - - if (broadcast) { - r = inet_pton(AF_INET, broadcast, &lease->broadcast); - if (r <= 0) - log_debug("Failed to parse broadcast address %s, ignoring.", broadcast); - else - lease->have_broadcast = true; - } - - if (dns) { - r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_DNS].addr, dns); - if (r < 0) - log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns); - else - lease->servers[SD_DHCP_LEASE_DNS].size = r; - } - - if (ntp) { - r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_NTP].addr, ntp); - if (r < 0) - log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp); - else - lease->servers[SD_DHCP_LEASE_NTP].size = r; - } - - if (sip) { - r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SIP].addr, sip); - if (r < 0) - log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip); - else - lease->servers[SD_DHCP_LEASE_SIP].size = r; - } - - if (pop3) { - r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_POP3].addr, pop3); - if (r < 0) - log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3); - else - lease->servers[SD_DHCP_LEASE_POP3].size = r; - } - - if (smtp) { - r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SMTP].addr, smtp); - if (r < 0) - log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp); - else - lease->servers[SD_DHCP_LEASE_SMTP].size = r; - } - - if (lpr) { - r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_LPR].addr, lpr); - if (r < 0) - log_debug_errno(r, "Failed to deserialize LPR server %s, ignoring: %m", lpr); - else - lease->servers[SD_DHCP_LEASE_LPR].size = r; - } - - if (mtu) { - r = safe_atou16(mtu, &lease->mtu); - if (r < 0) - log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu); - } - - if (domains) { - _cleanup_strv_free_ char **a = NULL; - a = strv_split(domains, " "); - if (!a) - return -ENOMEM; - - if (!strv_isempty(a)) - lease->search_domains = TAKE_PTR(a); - } - - if (routes) { - r = deserialize_dhcp_routes( - &lease->static_route, - &lease->static_route_size, - &lease->static_route_allocated, - routes); - if (r < 0) - log_debug_errno(r, "Failed to parse DHCP routes %s, ignoring: %m", routes); - } - - if (lifetime) { - r = safe_atou32(lifetime, &lease->lifetime); - if (r < 0) - log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime); - } - - if (t1) { - r = safe_atou32(t1, &lease->t1); - if (r < 0) - log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1); - } - - if (t2) { - r = safe_atou32(t2, &lease->t2); - if (r < 0) - log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2); - } - - if (client_id_hex) { - r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len); - if (r < 0) - log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex); - } - - if (vendor_specific_hex) { - r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len); - if (r < 0) - log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex); - } - - for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) { - _cleanup_free_ void *data = NULL; - size_t len; - - if (!options[i]) - continue; - - r = unhexmem(options[i], (size_t) -1, &data, &len); - if (r < 0) { - log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]); - continue; - } - - r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len); - if (r < 0) - return r; - } - - *ret = TAKE_PTR(lease); - - return 0; -} - -int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) { - struct in_addr address, mask; - int r; - - assert(lease); - - if (lease->address == 0) - return -ENODATA; - - address.s_addr = lease->address; - - /* fall back to the default subnet masks based on address class */ - r = in4_addr_default_subnet_mask(&address, &mask); - if (r < 0) - return r; - - lease->subnet_mask = mask.s_addr; - lease->have_subnet_mask = true; - - return 0; -} - -int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) { - assert_return(lease, -EINVAL); - assert_return(client_id, -EINVAL); - assert_return(client_id_len, -EINVAL); - - if (!lease->client_id) - return -ENODATA; - - *client_id = lease->client_id; - *client_id_len = lease->client_id_len; - - return 0; -} - -int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) { - assert_return(lease, -EINVAL); - assert_return(client_id || client_id_len <= 0, -EINVAL); - - if (client_id_len <= 0) - lease->client_id = mfree(lease->client_id); - else { - void *p; - - p = memdup(client_id, client_id_len); - if (!p) - return -ENOMEM; - - free(lease->client_id); - lease->client_id = p; - lease->client_id_len = client_id_len; - } - - return 0; -} - -int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) { - assert_return(lease, -EINVAL); - assert_return(tz, -EINVAL); - - if (!lease->timezone) - return -ENODATA; - - *tz = lease->timezone; - return 0; -} - -int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) { - assert_return(route, -EINVAL); - assert_return(destination, -EINVAL); - - *destination = route->dst_addr; - return 0; -} - -int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) { - assert_return(route, -EINVAL); - assert_return(length, -EINVAL); - - *length = route->dst_prefixlen; - return 0; -} - -int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) { - assert_return(route, -EINVAL); - assert_return(gateway, -EINVAL); - - *gateway = route->gw_addr; - return 0; -} - -int sd_dhcp_route_get_option(sd_dhcp_route *route) { - assert_return(route, -EINVAL); - - return route->option; -} diff --git a/src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c deleted file mode 100644 index 3fafd3c0..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ /dev/null @@ -1,1857 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014-2015 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#if 0 /* NM_IGNORED */ -#include -#else /* NM_IGNORED */ -#include -#endif /* NM_IGNORED */ -#include - -#include "sd-dhcp6-client.h" - -#include "alloc-util.h" -#include "dhcp-identifier.h" -#include "dhcp6-internal.h" -#include "dhcp6-lease-internal.h" -#include "dhcp6-protocol.h" -#include "dns-domain.h" -#include "event-util.h" -#include "fd-util.h" -#include "hexdecoct.h" -#include "hostname-util.h" -#include "in-addr-util.h" -#include "random-util.h" -#include "socket-util.h" -#include "string-table.h" -#include "strv.h" -#include "util.h" -#include "web-util.h" - -#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN - -#define IRT_DEFAULT (1 * USEC_PER_DAY) -#define IRT_MINIMUM (600 * USEC_PER_SEC) - -/* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */ -enum { - DHCP6_REQUEST_IA_NA = 1, - DHCP6_REQUEST_IA_TA = 2, /* currently not used */ - DHCP6_REQUEST_IA_PD = 4, -}; - -struct sd_dhcp6_client { - unsigned n_ref; - - enum DHCP6State state; - sd_event *event; - int event_priority; - int ifindex; - DHCP6Address hint_pd_prefix; - struct in6_addr local_address; - uint8_t mac_addr[MAX_MAC_ADDR_LEN]; - size_t mac_addr_len; - uint16_t arp_type; - DHCP6IA ia_na; - DHCP6IA ia_pd; - sd_event_source *timeout_t1; - sd_event_source *timeout_t2; - unsigned request; - be32_t transaction_id; - usec_t transaction_start; - struct sd_dhcp6_lease *lease; - int fd; - bool information_request; - bool iaid_set; - be16_t *req_opts; - size_t req_opts_allocated; - size_t req_opts_len; - char *fqdn; - char *mudurl; - char **user_class; - char **vendor_class; - sd_event_source *receive_message; - usec_t retransmit_time; - uint8_t retransmit_count; - sd_event_source *timeout_resend; - sd_event_source *timeout_resend_expire; - sd_dhcp6_client_callback_t callback; - void *userdata; - struct duid duid; - size_t duid_len; - usec_t information_request_time_usec; - usec_t information_refresh_time_usec; - OrderedHashmap *extra_options; - OrderedHashmap *vendor_options; -}; - -static const uint16_t default_req_opts[] = { - SD_DHCP6_OPTION_DNS_SERVERS, - SD_DHCP6_OPTION_DOMAIN_LIST, - SD_DHCP6_OPTION_NTP_SERVER, - SD_DHCP6_OPTION_SNTP_SERVERS, -}; - -const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = { - [DHCP6_SOLICIT] = "SOLICIT", - [DHCP6_ADVERTISE] = "ADVERTISE", - [DHCP6_REQUEST] = "REQUEST", - [DHCP6_CONFIRM] = "CONFIRM", - [DHCP6_RENEW] = "RENEW", - [DHCP6_REBIND] = "REBIND", - [DHCP6_REPLY] = "REPLY", - [DHCP6_RELEASE] = "RELEASE", - [DHCP6_DECLINE] = "DECLINE", - [DHCP6_RECONFIGURE] = "RECONFIGURE", - [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST", - [DHCP6_RELAY_FORW] = "RELAY-FORW", - [DHCP6_RELAY_REPL] = "RELAY-REPL", -}; - -DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int); - -const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = { - [DHCP6_STATUS_SUCCESS] = "Success", - [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure", - [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available", - [DHCP6_STATUS_NO_BINDING] = "Binding unavailable", - [DHCP6_STATUS_NOT_ON_LINK] = "Not on link", - [DHCP6_STATUS_USE_MULTICAST] = "Use multicast", - [DHCP6_STATUS_NO_PREFIX_AVAIL] = "No prefix available", - [DHCP6_STATUS_UNKNOWN_QUERY_TYPE] = "Unknown query type", - [DHCP6_STATUS_MALFORMED_QUERY] = "Malformed query", - [DHCP6_STATUS_NOT_CONFIGURED] = "Not configured", - [DHCP6_STATUS_NOT_ALLOWED] = "Not allowed", - [DHCP6_STATUS_QUERY_TERMINATED] = "Query terminated", - [DHCP6_STATUS_DATA_MISSING] = "Data missing", - [DHCP6_STATUS_CATCHUP_COMPLETE] = "Catch up complete", - [DHCP6_STATUS_NOT_SUPPORTED] = "Not supported", - [DHCP6_STATUS_TLS_CONNECTION_REFUSED] = "TLS connection refused", - [DHCP6_STATUS_ADDRESS_IN_USE] = "Address in use", - [DHCP6_STATUS_CONFIGURATION_CONFLICT] = "Configuration conflict", - [DHCP6_STATUS_MISSING_BINDING_INFORMATION] = "Missing binding information", - [DHCP6_STATUS_OUTDATED_BINDING_INFORMATION] = "Outdated binding information", - [DHCP6_STATUS_SERVER_SHUTTING_DOWN] = "Server shutting down", - [DHCP6_STATUS_DNS_UPDATE_NOT_SUPPORTED] = "DNS update not supported", - [DHCP6_STATUS_EXCESSIVE_TIME_SKEW] = "Excessive time skew", -}; - -DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); - -#define DHCP6_CLIENT_DONT_DESTROY(client) \ - _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client) - -static int client_start(sd_dhcp6_client *client, enum DHCP6State state); - -int sd_dhcp6_client_set_callback( - sd_dhcp6_client *client, - sd_dhcp6_client_callback_t cb, - void *userdata) { - - assert_return(client, -EINVAL); - - client->callback = cb; - client->userdata = userdata; - - return 0; -} - -int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) { - - assert_return(client, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - client->ifindex = ifindex; - return 0; -} - -int sd_dhcp6_client_set_local_address( - sd_dhcp6_client *client, - const struct in6_addr *local_address) { - - assert_return(client, -EINVAL); - assert_return(local_address, -EINVAL); - assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL); - - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - client->local_address = *local_address; - - return 0; -} - -int sd_dhcp6_client_set_mac( - sd_dhcp6_client *client, - const uint8_t *addr, size_t addr_len, - uint16_t arp_type) { - - assert_return(client, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); - - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - if (arp_type == ARPHRD_ETHER) - assert_return(addr_len == ETH_ALEN, -EINVAL); - else if (arp_type == ARPHRD_INFINIBAND) - assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); - else { - client->arp_type = ARPHRD_NONE; - client->mac_addr_len = 0; - return 0; - } - - if (client->mac_addr_len == addr_len && - memcmp(&client->mac_addr, addr, addr_len) == 0) - return 0; - - memcpy(&client->mac_addr, addr, addr_len); - client->mac_addr_len = addr_len; - client->arp_type = arp_type; - - return 0; -} - -int sd_dhcp6_client_set_prefix_delegation_hint( - sd_dhcp6_client *client, - uint8_t prefixlen, - const struct in6_addr *pd_address) { - - assert_return(client, -EINVAL); - assert_return(pd_address, -EINVAL); - - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - client->hint_pd_prefix.iapdprefix.address = *pd_address; - client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen; - - return 0; -} - -int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client, sd_dhcp6_option *v) { - int r; - - assert_return(client, -EINVAL); - assert_return(v, -EINVAL); - - r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp6_option_hash_ops); - if (r < 0) - return r; - - r = ordered_hashmap_put(client->vendor_options, v, v); - if (r < 0) - return r; - - sd_dhcp6_option_ref(v); - - return 1; -} - -static int client_ensure_duid(sd_dhcp6_client *client) { - if (client->duid_len != 0) - return 0; - - return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); -} - -/** - * Sets DUID. If duid is non-null, the DUID is set to duid_type + duid - * without further modification. Otherwise, if duid_type is supported, DUID - * is set based on that type. Otherwise, an error is returned. - */ -static int dhcp6_client_set_duid_internal( - sd_dhcp6_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len, - usec_t llt_time) { - int r; - - assert_return(client, -EINVAL); - assert_return(duid_len == 0 || duid != NULL, -EINVAL); - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - if (duid) { - r = dhcp_validate_duid_len(duid_type, duid_len, true); - if (r < 0) { - r = dhcp_validate_duid_len(duid_type, duid_len, false); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m"); - - log_dhcp6_client(client, "Using DUID of type %u of incorrect length, proceeding.", duid_type); - } - - client->duid.type = htobe16(duid_type); - memcpy(&client->duid.raw.data, duid, duid_len); - client->duid_len = sizeof(client->duid.type) + duid_len; - } else -#if 0 /* NM_IGNORED */ - switch (duid_type) { - case DUID_TYPE_LLT: - if (client->mac_addr_len == 0) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); - - r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-LLT: %m"); - break; - case DUID_TYPE_EN: - r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-EN: %m"); - break; - case DUID_TYPE_LL: - if (client->mac_addr_len == 0) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); - - r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-LL: %m"); - break; - case DUID_TYPE_UUID: - r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-UUID: %m"); - break; - default: - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); - } -#else /* NM_IGNORED */ - g_return_val_if_reached (-EINVAL); -#endif /* NM_IGNORED */ - - return 0; -} - -int sd_dhcp6_client_set_duid( - sd_dhcp6_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len) { - return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0); -} - -int sd_dhcp6_client_set_duid_llt( - sd_dhcp6_client *client, - usec_t llt_time) { - return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time); -} - -static const char* const dhcp6_duid_type_table[_DUID_TYPE_MAX] = { - [DUID_TYPE_LLT] = "DUID-LLT", - [DUID_TYPE_EN] = "DUID-EN/Vendor", - [DUID_TYPE_LL] = "DUID-LL", - [DUID_TYPE_UUID] = "UUID", -}; -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(dhcp6_duid_type, DUIDType); - -int sd_dhcp6_client_duid_as_string( - sd_dhcp6_client *client, - char **duid) { - _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; - const char *v; - int r; - - assert_return(client, -EINVAL); - assert_return(client->duid_len > 0, -ENODATA); - - v = dhcp6_duid_type_to_string(be16toh(client->duid.type)); - if (v) { - s = strdup(v); - if (!s) - return -ENOMEM; - } else { - r = asprintf(&s, "%0x", client->duid.type); - if (r < 0) - return -ENOMEM; - } - - t = hexmem(&client->duid.raw.data, client->duid_len); - if (!t) - return -ENOMEM; - - p = strjoin(s, ":", t); - if (!p) - return -ENOMEM; - - *duid = TAKE_PTR(p); - - return 0; -} - -int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) { - assert_return(client, -EINVAL); - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - client->ia_na.ia_na.id = htobe32(iaid); - client->ia_pd.ia_pd.id = htobe32(iaid); - client->iaid_set = true; - - return 0; -} - -int sd_dhcp6_client_get_iaid(sd_dhcp6_client *client, uint32_t *iaid) { - assert_return(client, -EINVAL); - assert_return(iaid, -EINVAL); - - if (!client->iaid_set) - return -ENODATA; - - *iaid = be32toh(client->ia_na.ia_na.id); - - return 0; -} - -int sd_dhcp6_client_set_fqdn( - sd_dhcp6_client *client, - const char *fqdn) { - - assert_return(client, -EINVAL); - - /* Make sure FQDN qualifies as DNS and as Linux hostname */ - if (fqdn && - !(hostname_is_valid(fqdn, 0) && dns_name_is_valid(fqdn) > 0)) - return -EINVAL; - - return free_and_strdup(&client->fqdn, fqdn); -} - -int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) { - assert_return(client, -EINVAL); - assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - - client->information_request = enabled; - - return 0; -} - -int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled) { - assert_return(client, -EINVAL); - assert_return(enabled, -EINVAL); - - *enabled = client->information_request; - - return 0; -} - -int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) { - size_t t; - - assert_return(client, -EINVAL); - assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); - - if (option <= 0 || option >= UINT8_MAX) - return -EINVAL; - - for (t = 0; t < client->req_opts_len; t++) - if (client->req_opts[t] == htobe16(option)) - return -EEXIST; - - if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated, - client->req_opts_len + 1)) - return -ENOMEM; - - client->req_opts[client->req_opts_len++] = htobe16(option); - - return 0; -} - -int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mudurl) { - - assert_return(client, -EINVAL); - assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); - assert_return(mudurl, -EINVAL); - assert_return(strlen(mudurl) <= UINT8_MAX, -EINVAL); - assert_return(http_url_is_valid(mudurl), -EINVAL); - - return free_and_strdup(&client->mudurl, mudurl); -} - -int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) { - _cleanup_strv_free_ char **s = NULL; - char **p; - - assert_return(client, -EINVAL); - assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); - - assert_return(user_class, -EINVAL); - - STRV_FOREACH(p, user_class) - if (strlen(*p) > UINT16_MAX) - return -ENAMETOOLONG; - - s = strv_copy(user_class); - if (!s) - return -ENOMEM; - - client->user_class = TAKE_PTR(s); - - return 0; -} - -int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char **vendor_class) { - _cleanup_strv_free_ char **s = NULL; - char **p; - - assert_return(client, -EINVAL); - assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); - assert_return(vendor_class, -EINVAL); - - STRV_FOREACH(p, vendor_class) - if (strlen(*p) > UINT8_MAX) - return -ENAMETOOLONG; - - s = strv_copy(vendor_class); - if (!s) - return -ENOMEM; - - client->vendor_class = TAKE_PTR(s); - - return 0; -} - -int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) { - assert_return(client, -EINVAL); - assert_return(delegation, -EINVAL); - - *delegation = FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD); - - return 0; -} - -int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, int delegation) { - assert_return(client, -EINVAL); - - SET_FLAG(client->request, DHCP6_REQUEST_IA_PD, delegation); - - return 0; -} - -int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request) { - assert_return(client, -EINVAL); - assert_return(request, -EINVAL); - - *request = FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA); - - return 0; -} - -int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, int request) { - assert_return(client, -EINVAL); - - SET_FLAG(client->request, DHCP6_REQUEST_IA_NA, request); - - return 0; -} - -int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id) { - assert_return(client, -EINVAL); - - client->transaction_id = transaction_id; - - return 0; -} - -int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) { - assert_return(client, -EINVAL); - - if (!client->lease) - return -ENOMSG; - - if (ret) - *ret = client->lease; - - return 0; -} - -int sd_dhcp6_client_add_option(sd_dhcp6_client *client, sd_dhcp6_option *v) { - int r; - - assert_return(client, -EINVAL); - assert_return(v, -EINVAL); - - r = ordered_hashmap_ensure_allocated(&client->extra_options, &dhcp6_option_hash_ops); - if (r < 0) - return r; - - r = ordered_hashmap_put(client->extra_options, UINT_TO_PTR(v->option), v); - if (r < 0) - return r; - - sd_dhcp6_option_ref(v); - return 0; -} - -static void client_notify(sd_dhcp6_client *client, int event) { - assert(client); - - if (client->callback) - client->callback(client, event, client->userdata); -} - -static int client_reset(sd_dhcp6_client *client) { - assert(client); - - client->lease = sd_dhcp6_lease_unref(client->lease); - - client->receive_message = - sd_event_source_unref(client->receive_message); - - client->transaction_id = 0; - client->transaction_start = 0; - - client->retransmit_time = 0; - client->retransmit_count = 0; - - (void) event_source_disable(client->timeout_resend); - (void) event_source_disable(client->timeout_resend_expire); - (void) event_source_disable(client->timeout_t1); - (void) event_source_disable(client->timeout_t2); - - client->state = DHCP6_STATE_STOPPED; - - return 0; -} - -static void client_stop(sd_dhcp6_client *client, int error) { - DHCP6_CLIENT_DONT_DESTROY(client); - - assert(client); - - client_notify(client, error); - - client_reset(client); -} - -static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { - _cleanup_free_ DHCP6Message *message = NULL; - struct in6_addr all_servers = - IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; - struct sd_dhcp6_option *j; - size_t len, optlen = 512; - uint8_t *opt; - int r; - usec_t elapsed_usec; - be16_t elapsed_time; - - assert(client); - - len = sizeof(DHCP6Message) + optlen; - - message = malloc0(len); - if (!message) - return -ENOMEM; - - opt = (uint8_t *)(message + 1); - - message->transaction_id = client->transaction_id; - - switch(client->state) { - case DHCP6_STATE_INFORMATION_REQUEST: - message->type = DHCP6_INFORMATION_REQUEST; - - if (client->mudurl) { - r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), - client->mudurl); - if (r < 0) - return r; - } - - break; - - case DHCP6_STATE_SOLICITATION: - message->type = DHCP6_SOLICIT; - - r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL); - if (r < 0) - return r; - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { - r = dhcp6_option_append_ia(&opt, &optlen, - &client->ia_na); - if (r < 0) - return r; - } - - if (client->fqdn) { - r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); - if (r < 0) - return r; - } - - if (client->mudurl) { - r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), - client->mudurl); - if (r < 0) - return r; - } - - if (client->user_class) { - r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class); - if (r < 0) - return r; - } - - if (client->vendor_class) { - r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class); - if (r < 0) - return r; - } - - if (!ordered_hashmap_isempty(client->vendor_options)) { - r = dhcp6_option_append_vendor_option(&opt, &optlen, - client->vendor_options); - if (r < 0) - return r; - } - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix); - if (r < 0) - return r; - - opt += r; - optlen -= r; - } - - break; - - case DHCP6_STATE_REQUEST: - case DHCP6_STATE_RENEW: - - if (client->state == DHCP6_STATE_REQUEST) - message->type = DHCP6_REQUEST; - else - message->type = DHCP6_RENEW; - - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID, - client->lease->serverid_len, - client->lease->serverid); - if (r < 0) - return r; - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) { - r = dhcp6_option_append_ia(&opt, &optlen, - &client->lease->ia); - if (r < 0) - return r; - } - - if (client->fqdn) { - r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); - if (r < 0) - return r; - } - - if (client->mudurl) { - r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), - client->mudurl); - if (r < 0) - return r; - } - - if (client->user_class) { - r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class); - if (r < 0) - return r; - } - - if (client->vendor_class) { - r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class); - if (r < 0) - return r; - } - - if (!ordered_hashmap_isempty(client->vendor_options)) { - r = dhcp6_option_append_vendor_option(&opt, &optlen, client->vendor_options); - if (r < 0) - return r; - } - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); - if (r < 0) - return r; - - opt += r; - optlen -= r; - } - - break; - - case DHCP6_STATE_REBIND: - message->type = DHCP6_REBIND; - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { - r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); - if (r < 0) - return r; - } - - if (client->fqdn) { - r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); - if (r < 0) - return r; - } - - if (client->mudurl) { - r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), - client->mudurl); - if (r < 0) - return r; - } - - if (client->user_class) { - r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class); - if (r < 0) - return r; - } - - if (client->vendor_class) { - r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class); - if (r < 0) - return r; - } - - if (!ordered_hashmap_isempty(client->vendor_options)) { - r = dhcp6_option_append_vendor_option(&opt, &optlen, client->vendor_options); - if (r < 0) - return r; - } - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); - if (r < 0) - return r; - - opt += r; - optlen -= r; - } - - break; - - case DHCP6_STATE_STOPPED: - case DHCP6_STATE_BOUND: - return -EINVAL; - } - - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO, - client->req_opts_len * sizeof(be16_t), - client->req_opts); - if (r < 0) - return r; - - assert(client->duid_len); - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID, - client->duid_len, &client->duid); - if (r < 0) - return r; - - elapsed_usec = time_now - client->transaction_start; - if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10) - elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10); - else - elapsed_time = 0xffff; - - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, - sizeof(elapsed_time), &elapsed_time); - if (r < 0) - return r; - - ORDERED_HASHMAP_FOREACH(j, client->extra_options) { - r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data); - if (r < 0) - return r; - } - - r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message, - len - optlen); - if (r < 0) - return r; - - log_dhcp6_client(client, "Sent %s", - dhcp6_message_type_to_string(message->type)); - - return 0; -} - -static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { - sd_dhcp6_client *client = userdata; - - assert(s); - assert(client); - assert(client->lease); - - (void) event_source_disable(client->timeout_t2); - - log_dhcp6_client(client, "Timeout T2"); - - client_start(client, DHCP6_STATE_REBIND); - - return 0; -} - -static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { - sd_dhcp6_client *client = userdata; - - assert(s); - assert(client); - assert(client->lease); - - (void) event_source_disable(client->timeout_t1); - - log_dhcp6_client(client, "Timeout T1"); - - client_start(client, DHCP6_STATE_RENEW); - - return 0; -} - -static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) { - sd_dhcp6_client *client = userdata; - DHCP6_CLIENT_DONT_DESTROY(client); - enum DHCP6State state; - - assert(s); - assert(client); - assert(client->event); - - state = client->state; - - client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE); - - /* RFC 3315, section 18.1.4., says that "...the client may choose to - use a Solicit message to locate a new DHCP server..." */ - if (state == DHCP6_STATE_REBIND) - client_start(client, DHCP6_STATE_SOLICITATION); - - return 0; -} - -static usec_t client_timeout_compute_random(usec_t val) { - return val - (random_u32() % USEC_PER_SEC) * val / 10 / USEC_PER_SEC; -} - -static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) { - int r = 0; - sd_dhcp6_client *client = userdata; - usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0; - usec_t max_retransmit_duration = 0; - uint8_t max_retransmit_count = 0; - char time_string[FORMAT_TIMESPAN_MAX]; - - assert(s); - assert(client); - assert(client->event); - - (void) event_source_disable(client->timeout_resend); - - switch (client->state) { - case DHCP6_STATE_INFORMATION_REQUEST: - init_retransmit_time = DHCP6_INF_TIMEOUT; - max_retransmit_time = DHCP6_INF_MAX_RT; - - break; - - case DHCP6_STATE_SOLICITATION: - - if (client->retransmit_count && client->lease) { - client_start(client, DHCP6_STATE_REQUEST); - return 0; - } - - init_retransmit_time = DHCP6_SOL_TIMEOUT; - max_retransmit_time = DHCP6_SOL_MAX_RT; - - break; - - case DHCP6_STATE_REQUEST: - init_retransmit_time = DHCP6_REQ_TIMEOUT; - max_retransmit_time = DHCP6_REQ_MAX_RT; - max_retransmit_count = DHCP6_REQ_MAX_RC; - - break; - - case DHCP6_STATE_RENEW: - init_retransmit_time = DHCP6_REN_TIMEOUT; - max_retransmit_time = DHCP6_REN_MAX_RT; - - /* RFC 3315, section 18.1.3. says max retransmit duration will - be the remaining time until T2. Instead of setting MRD, - wait for T2 to trigger with the same end result */ - - break; - - case DHCP6_STATE_REBIND: - init_retransmit_time = DHCP6_REB_TIMEOUT; - max_retransmit_time = DHCP6_REB_MAX_RT; - - if (event_source_is_enabled(client->timeout_resend_expire) <= 0) { - uint32_t expire = 0; - - r = dhcp6_lease_ia_rebind_expire(&client->lease->ia, &expire); - if (r < 0) { - client_stop(client, r); - return 0; - } - max_retransmit_duration = expire * USEC_PER_SEC; - } - - break; - - case DHCP6_STATE_STOPPED: - case DHCP6_STATE_BOUND: - return 0; - } - - if (max_retransmit_count > 0 && - client->retransmit_count >= max_retransmit_count) { - client_stop(client, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX); - return 0; - } - - r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - goto error; - - r = client_send_message(client, time_now); - if (r >= 0) - client->retransmit_count++; - - if (client->retransmit_time == 0) { - client->retransmit_time = - client_timeout_compute_random(init_retransmit_time); - - if (client->state == DHCP6_STATE_SOLICITATION) - client->retransmit_time += init_retransmit_time / 10; - - } else { - if (max_retransmit_time > 0 && - client->retransmit_time > max_retransmit_time / 2) - client->retransmit_time = client_timeout_compute_random(max_retransmit_time); - else - client->retransmit_time += client_timeout_compute_random(client->retransmit_time); - } - - log_dhcp6_client(client, "Next retransmission in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC)); - - r = event_reset_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), - time_now + client->retransmit_time, 10 * USEC_PER_MSEC, - client_timeout_resend, client, - client->event_priority, "dhcp6-resend-timer", true); - if (r < 0) - goto error; - - if (max_retransmit_duration > 0 && event_source_is_enabled(client->timeout_resend_expire) <= 0) { - - log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs", - max_retransmit_duration / USEC_PER_SEC); - - r = event_reset_time(client->event, &client->timeout_resend_expire, - clock_boottime_or_monotonic(), - time_now + max_retransmit_duration, USEC_PER_SEC, - client_timeout_resend_expire, client, - client->event_priority, "dhcp6-resend-expire-timer", true); - if (r < 0) - goto error; - } - -error: - if (r < 0) - client_stop(client, r); - - return 0; -} - -static int client_ensure_iaid(sd_dhcp6_client *client) { - int r; - uint32_t iaid; - - assert(client); - - if (client->iaid_set) - return 0; - - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid); - if (r < 0) - return r; - - client->ia_na.ia_na.id = iaid; - client->ia_pd.ia_pd.id = iaid; - client->iaid_set = true; - - return 0; -} - -static int client_parse_message( - sd_dhcp6_client *client, - DHCP6Message *message, - size_t len, - sd_dhcp6_lease *lease) { - - uint16_t ia_na_status = 0, ia_pd_status = 0; - uint32_t lt_t1 = ~0, lt_t2 = ~0; - usec_t irt = IRT_DEFAULT; - bool clientid = false; - size_t pos = 0; - int r; - - assert(client); - assert(message); - assert(len >= sizeof(DHCP6Message)); - assert(lease); - - len -= sizeof(DHCP6Message); - - while (pos < len) { - DHCP6Option *option = (DHCP6Option *) &message->options[pos]; - uint16_t optcode, optlen; - be32_t iaid_lease; - int status; - uint8_t *optval; - - if (len < pos + offsetof(DHCP6Option, data)) - return -ENOBUFS; - - optcode = be16toh(option->code); - optlen = be16toh(option->len); - optval = option->data; - - if (len < pos + offsetof(DHCP6Option, data) + optlen) - return -ENOBUFS; - - switch (optcode) { - case SD_DHCP6_OPTION_CLIENTID: - if (clientid) { - log_dhcp6_client(client, "%s contains multiple clientids", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - if (optlen != client->duid_len || - memcmp(&client->duid, optval, optlen) != 0) { - log_dhcp6_client(client, "%s DUID does not match", - dhcp6_message_type_to_string(message->type)); - - return -EINVAL; - } - clientid = true; - - break; - - case SD_DHCP6_OPTION_SERVERID: - r = dhcp6_lease_get_serverid(lease, NULL, NULL); - if (r >= 0) { - log_dhcp6_client(client, "%s contains multiple serverids", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - r = dhcp6_lease_set_serverid(lease, optval, optlen); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_PREFERENCE: - if (optlen != 1) - return -EINVAL; - - r = dhcp6_lease_set_preference(lease, optval[0]); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_STATUS_CODE: - status = dhcp6_option_parse_status(option, optlen + sizeof(DHCP6Option)); - if (status < 0) - return status; - - if (status > 0) { - log_dhcp6_client(client, "%s Status %s", - dhcp6_message_type_to_string(message->type), - dhcp6_message_status_to_string(status)); - - return -EINVAL; - } - - break; - - case SD_DHCP6_OPTION_IA_NA: - if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { - log_dhcp6_client(client, "Information request ignoring IA NA option"); - - break; - } - - r = dhcp6_option_parse_ia(option, &lease->ia, &ia_na_status); - if (r < 0 && r != -ENOMSG) - return r; - - if (ia_na_status == DHCP6_STATUS_NO_ADDRS_AVAIL) { - pos += offsetof(DHCP6Option, data) + optlen; - continue; - } - - r = dhcp6_lease_get_iaid(lease, &iaid_lease); - if (r < 0) - return r; - - if (client->ia_na.ia_na.id != iaid_lease) { - log_dhcp6_client(client, "%s has wrong IAID for IA NA", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - if (lease->ia.addresses) { - lt_t1 = MIN(lt_t1, be32toh(lease->ia.ia_na.lifetime_t1)); - lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t1)); - } - - break; - - case SD_DHCP6_OPTION_IA_PD: - if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { - log_dhcp6_client(client, "Information request ignoring IA PD option"); - - break; - } - - r = dhcp6_option_parse_ia(option, &lease->pd, &ia_pd_status); - if (r < 0 && r != -ENOMSG) - return r; - - if (ia_pd_status == DHCP6_STATUS_NO_PREFIX_AVAIL) { - pos += offsetof(DHCP6Option, data) + optlen; - continue; - } - - r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease); - if (r < 0) - return r; - - if (client->ia_pd.ia_pd.id != iaid_lease) { - log_dhcp6_client(client, "%s has wrong IAID for IA PD", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - if (lease->pd.addresses) { - lt_t1 = MIN(lt_t1, be32toh(lease->pd.ia_pd.lifetime_t1)); - lt_t2 = MIN(lt_t2, be32toh(lease->pd.ia_pd.lifetime_t2)); - } - - break; - - case SD_DHCP6_OPTION_RAPID_COMMIT: - r = dhcp6_lease_set_rapid_commit(lease); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_DNS_SERVERS: - r = dhcp6_lease_set_dns(lease, optval, optlen); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_DOMAIN_LIST: - r = dhcp6_lease_set_domains(lease, optval, optlen); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_NTP_SERVER: - r = dhcp6_lease_set_ntp(lease, optval, optlen); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_SNTP_SERVERS: - r = dhcp6_lease_set_sntp(lease, optval, optlen); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_FQDN: - r = dhcp6_lease_set_fqdn(lease, optval, optlen); - if (r < 0) - return r; - - break; - - case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: - if (optlen != 4) - return -EINVAL; - - irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC; - break; - } - - pos += offsetof(DHCP6Option, data) + optlen; - } - - if (ia_na_status > 0 && ia_pd_status > 0) { - log_dhcp6_client(client, "No IA_PD prefix or IA_NA address received. Ignoring."); - return -EINVAL; - } - - if (!clientid) { - log_dhcp6_client(client, "%s has incomplete options", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - if (client->state != DHCP6_STATE_INFORMATION_REQUEST) { - r = dhcp6_lease_get_serverid(lease, NULL, NULL); - if (r < 0) { - log_dhcp6_client(client, "%s has no server id", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - - } else { - if (lease->ia.addresses) { - lease->ia.ia_na.lifetime_t1 = htobe32(lt_t1); - lease->ia.ia_na.lifetime_t2 = htobe32(lt_t2); - } - - if (lease->pd.addresses) { - lease->pd.ia_pd.lifetime_t1 = htobe32(lt_t1); - lease->pd.ia_pd.lifetime_t2 = htobe32(lt_t2); - } - } - - client->information_refresh_time_usec = MAX(irt, IRT_MINIMUM); - - return 0; -} - -static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) { - _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; - bool rapid_commit; - int r; - - assert(client); - assert(reply); - - if (reply->type != DHCP6_REPLY) - return 0; - - r = dhcp6_lease_new(&lease); - if (r < 0) - return -ENOMEM; - - r = client_parse_message(client, reply, len, lease); - if (r < 0) - return r; - - if (client->state == DHCP6_STATE_SOLICITATION) { - r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit); - if (r < 0) - return r; - - if (!rapid_commit) - return 0; - } - - sd_dhcp6_lease_unref(client->lease); - client->lease = TAKE_PTR(lease); - - return DHCP6_STATE_BOUND; -} - -static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) { - _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; - uint8_t pref_advertise = 0, pref_lease = 0; - int r; - - if (advertise->type != DHCP6_ADVERTISE) - return 0; - - r = dhcp6_lease_new(&lease); - if (r < 0) - return r; - - r = client_parse_message(client, advertise, len, lease); - if (r < 0) - return r; - - r = dhcp6_lease_get_preference(lease, &pref_advertise); - if (r < 0) - return r; - - r = dhcp6_lease_get_preference(client->lease, &pref_lease); - - if (r < 0 || pref_advertise > pref_lease) { - sd_dhcp6_lease_unref(client->lease); - client->lease = TAKE_PTR(lease); - r = 0; - } - - if (pref_advertise == 255 || client->retransmit_count > 1) - r = DHCP6_STATE_REQUEST; - - return r; -} - -static int client_receive_message( - sd_event_source *s, - int fd, uint32_t - revents, - void *userdata) { - - sd_dhcp6_client *client = userdata; - DHCP6_CLIENT_DONT_DESTROY(client); - _cleanup_free_ DHCP6Message *message = NULL; - ssize_t buflen, len; - int r = 0; - - assert(s); - assert(client); - assert(client->event); - - buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - /* the link is down. Don't return an error or the I/O event - source will be disconnected and we won't be able to receive - packets again when the link comes back. */ - return 0; - if (buflen < 0) - return buflen; - - message = malloc(buflen); - if (!message) - return -ENOMEM; - - len = recv(fd, message, buflen, 0); - if (len < 0) { - /* see comment above for why we shouldn't error out on ENETDOWN. */ - if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) - return 0; - - return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m"); - - } - if ((size_t) len < sizeof(DHCP6Message)) { - log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); - return 0; - } - - switch(message->type) { - case DHCP6_SOLICIT: - case DHCP6_REQUEST: - case DHCP6_CONFIRM: - case DHCP6_RENEW: - case DHCP6_REBIND: - case DHCP6_RELEASE: - case DHCP6_DECLINE: - case DHCP6_INFORMATION_REQUEST: - case DHCP6_RELAY_FORW: - case DHCP6_RELAY_REPL: - return 0; - - case DHCP6_ADVERTISE: - case DHCP6_REPLY: - case DHCP6_RECONFIGURE: - break; - - default: - log_dhcp6_client(client, "Unknown message type %d", message->type); - return 0; - } - - if (client->transaction_id != (message->transaction_id & - htobe32(0x00ffffff))) - return 0; - - switch (client->state) { - case DHCP6_STATE_INFORMATION_REQUEST: - r = client_receive_reply(client, message, len); - if (r < 0) - return 0; - - client_notify(client, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); - - client_start(client, DHCP6_STATE_STOPPED); - - break; - - case DHCP6_STATE_SOLICITATION: - r = client_receive_advertise(client, message, len); - - if (r == DHCP6_STATE_REQUEST) { - client_start(client, r); - - break; - } - - _fallthrough_; /* for Solicitation Rapid Commit option check */ - case DHCP6_STATE_REQUEST: - case DHCP6_STATE_RENEW: - case DHCP6_STATE_REBIND: - - r = client_receive_reply(client, message, len); - if (r < 0) - return 0; - - if (r == DHCP6_STATE_BOUND) { - - r = client_start(client, DHCP6_STATE_BOUND); - if (r < 0) { - client_stop(client, r); - return 0; - } - - client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE); - } - - break; - - case DHCP6_STATE_BOUND: - - break; - - case DHCP6_STATE_STOPPED: - return 0; - } - - log_dhcp6_client(client, "Recv %s", - dhcp6_message_type_to_string(message->type)); - - return 0; -} - -static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1, - uint32_t *lifetime_t2) { - assert_return(client, -EINVAL); - assert_return(client->lease, -EINVAL); - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) { - *lifetime_t1 = be32toh(client->lease->ia.ia_na.lifetime_t1); - *lifetime_t2 = be32toh(client->lease->ia.ia_na.lifetime_t2); - - return 0; - } - - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) { - *lifetime_t1 = be32toh(client->lease->pd.ia_pd.lifetime_t1); - *lifetime_t2 = be32toh(client->lease->pd.ia_pd.lifetime_t2); - - return 0; - } - - return -ENOMSG; -} - -static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { - int r; - usec_t timeout, time_now; - char time_string[FORMAT_TIMESPAN_MAX]; - uint32_t lifetime_t1, lifetime_t2; - - assert_return(client, -EINVAL); - assert_return(client->event, -EINVAL); - assert_return(client->ifindex > 0, -EINVAL); - assert_return(client->state != state, -EINVAL); - - (void) event_source_disable(client->timeout_resend_expire); - (void) event_source_disable(client->timeout_resend); - client->retransmit_time = 0; - client->retransmit_count = 0; - - r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return r; - - if (!client->receive_message) { - r = sd_event_add_io(client->event, &client->receive_message, - client->fd, EPOLLIN, client_receive_message, - client); - if (r < 0) - goto error; - - r = sd_event_source_set_priority(client->receive_message, - client->event_priority); - if (r < 0) - goto error; - - r = sd_event_source_set_description(client->receive_message, - "dhcp6-receive-message"); - if (r < 0) - goto error; - } - - switch (state) { - case DHCP6_STATE_STOPPED: - if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { - client->state = DHCP6_STATE_STOPPED; - - return 0; - } - - _fallthrough_; - case DHCP6_STATE_SOLICITATION: - client->state = DHCP6_STATE_SOLICITATION; - - break; - - case DHCP6_STATE_INFORMATION_REQUEST: - case DHCP6_STATE_REQUEST: - case DHCP6_STATE_RENEW: - case DHCP6_STATE_REBIND: - - client->state = state; - - break; - - case DHCP6_STATE_BOUND: - - r = client_get_lifetime(client, &lifetime_t1, &lifetime_t2); - if (r < 0) - goto error; - - if (lifetime_t1 == 0xffffffff || lifetime_t2 == 0xffffffff) { - log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x", - lifetime_t1, lifetime_t2); - - return 0; - } - - timeout = client_timeout_compute_random(lifetime_t1 * USEC_PER_SEC); - - log_dhcp6_client(client, "T1 expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); - - r = event_reset_time(client->event, &client->timeout_t1, - clock_boottime_or_monotonic(), - time_now + timeout, 10 * USEC_PER_SEC, - client_timeout_t1, client, - client->event_priority, "dhcp6-t1-timeout", true); - if (r < 0) - goto error; - - timeout = client_timeout_compute_random(lifetime_t2 * USEC_PER_SEC); - - log_dhcp6_client(client, "T2 expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); - - r = event_reset_time(client->event, &client->timeout_t2, - clock_boottime_or_monotonic(), - time_now + timeout, 10 * USEC_PER_SEC, - client_timeout_t2, client, - client->event_priority, "dhcp6-t2-timeout", true); - if (r < 0) - goto error; - - client->state = state; - - return 0; - } - - client->transaction_id = random_u32() & htobe32(0x00ffffff); - client->transaction_start = time_now; - - r = event_reset_time(client->event, &client->timeout_resend, - clock_boottime_or_monotonic(), - 0, 0, - client_timeout_resend, client, - client->event_priority, "dhcp6-resend-timeout", true); - if (r < 0) - goto error; - - return 0; - - error: - client_reset(client); - return r; -} - -int sd_dhcp6_client_stop(sd_dhcp6_client *client) { - if (!client) - return 0; - - client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP); - - client->fd = safe_close(client->fd); - - return 0; -} - -int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { - assert_return(client, -EINVAL); - - return client->state != DHCP6_STATE_STOPPED; -} - -int sd_dhcp6_client_start(sd_dhcp6_client *client) { - enum DHCP6State state = DHCP6_STATE_SOLICITATION; - int r; - - assert_return(client, -EINVAL); - assert_return(client->event, -EINVAL); - assert_return(client->ifindex > 0, -EINVAL); - assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL); - - if (!IN_SET(client->state, DHCP6_STATE_STOPPED)) - return -EBUSY; - - if (!client->information_request && !client->request) - return -EINVAL; - - r = client_reset(client); - if (r < 0) - return r; - - r = client_ensure_iaid(client); - if (r < 0) - return r; - - r = client_ensure_duid(client); - if (r < 0) - return r; - - if (client->fd < 0) { - r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address); - if (r < 0) { - _cleanup_free_ char *p = NULL; - - (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p); - return log_dhcp6_client_errno(client, r, - "Failed to bind to UDP socket at address %s: %m", strna(p)); - } - - client->fd = r; - } - - if (client->information_request) { - usec_t t = now(CLOCK_MONOTONIC); - - if (t < usec_add(client->information_request_time_usec, client->information_refresh_time_usec)) - return 0; - - client->information_request_time_usec = t; - state = DHCP6_STATE_INFORMATION_REQUEST; - } - - log_dhcp6_client(client, "Started in %s mode", - client->information_request ? "Information request" : "Managed"); - - return client_start(client, state); -} - -int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority) { - int r; - - assert_return(client, -EINVAL); - assert_return(!client->event, -EBUSY); - - if (event) - client->event = sd_event_ref(event); - else { - r = sd_event_default(&client->event); - if (r < 0) - return 0; - } - - client->event_priority = priority; - - return 0; -} - -int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) { - assert_return(client, -EINVAL); - - client->event = sd_event_unref(client->event); - - return 0; -} - -sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) { - assert_return(client, NULL); - - return client->event; -} - -static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) { - assert(client); - - client->timeout_resend = sd_event_source_unref(client->timeout_resend); - client->timeout_resend_expire = sd_event_source_unref(client->timeout_resend_expire); - client->timeout_t1 = sd_event_source_unref(client->timeout_t1); - client->timeout_t2 = sd_event_source_unref(client->timeout_t2); - - client_reset(client); - - client->fd = safe_close(client->fd); - - sd_dhcp6_client_detach_event(client); - - free(client->req_opts); - free(client->fqdn); - free(client->mudurl); - - ordered_hashmap_free(client->extra_options); - strv_free(client->user_class); - strv_free(client->vendor_class); - - return mfree(client); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_free); - -int sd_dhcp6_client_new(sd_dhcp6_client **ret) { - _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; - _cleanup_free_ be16_t *req_opts = NULL; - size_t t; - - assert_return(ret, -EINVAL); - - req_opts = new(be16_t, ELEMENTSOF(default_req_opts)); - if (!req_opts) - return -ENOMEM; - - for (t = 0; t < ELEMENTSOF(default_req_opts); t++) - req_opts[t] = htobe16(default_req_opts[t]); - - client = new(sd_dhcp6_client, 1); - if (!client) - return -ENOMEM; - - *client = (sd_dhcp6_client) { - .n_ref = 1, - .ia_na.type = SD_DHCP6_OPTION_IA_NA, - .ia_pd.type = SD_DHCP6_OPTION_IA_PD, - .ifindex = -1, - .request = DHCP6_REQUEST_IA_NA, - .fd = -1, - .req_opts_len = ELEMENTSOF(default_req_opts), - .hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1, - .hint_pd_prefix.iapdprefix.lifetime_valid = (be32_t) -1, - .req_opts = TAKE_PTR(req_opts), - }; - - *ret = TAKE_PTR(client); - - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c deleted file mode 100644 index 5792f688..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c +++ /dev/null @@ -1,435 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014-2015 Intel Corporation. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include - -#include "alloc-util.h" -#include "dhcp6-lease-internal.h" -#include "dhcp6-protocol.h" -#include "strv.h" -#include "util.h" - -int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) { - DHCP6Address *addr; - uint32_t valid = 0, t; - - assert_return(ia, -EINVAL); - assert_return(expire, -EINVAL); - - LIST_FOREACH(addresses, addr, ia->addresses) { - t = be32toh(addr->iaaddr.lifetime_valid); - if (valid < t) - valid = t; - } - - t = be32toh(ia->ia_na.lifetime_t2); - if (t > valid) - return -EINVAL; - - *expire = valid - t; - - return 0; -} - -DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) { - DHCP6Address *address; - - if (!ia) - return NULL; - - while (ia->addresses) { - address = ia->addresses; - - LIST_REMOVE(addresses, ia->addresses, address); - - free(address); - } - - return NULL; -} - -int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, - size_t len) { - uint8_t *serverid; - - assert_return(lease, -EINVAL); - assert_return(id, -EINVAL); - - serverid = memdup(id, len); - if (!serverid) - return -ENOMEM; - - free_and_replace(lease->serverid, serverid); - lease->serverid_len = len; - - return 0; -} - -int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) { - assert_return(lease, -EINVAL); - - if (!lease->serverid) - return -ENOMSG; - - if (id) - *id = lease->serverid; - if (len) - *len = lease->serverid_len; - - return 0; -} - -int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) { - assert_return(lease, -EINVAL); - - lease->preference = preference; - - return 0; -} - -int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) { - assert_return(preference, -EINVAL); - - if (!lease) - return -EINVAL; - - *preference = lease->preference; - - return 0; -} - -int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) { - assert_return(lease, -EINVAL); - - lease->rapid_commit = true; - - return 0; -} - -int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) { - assert_return(lease, -EINVAL); - assert_return(rapid_commit, -EINVAL); - - *rapid_commit = lease->rapid_commit; - - return 0; -} - -int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { - assert_return(lease, -EINVAL); - assert_return(iaid, -EINVAL); - - *iaid = lease->ia.ia_na.id; - - return 0; -} - -int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { - assert_return(lease, -EINVAL); - assert_return(iaid, -EINVAL); - - *iaid = lease->pd.ia_pd.id; - - return 0; -} - -int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, - uint32_t *lifetime_preferred, - uint32_t *lifetime_valid) { - assert_return(lease, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(lifetime_preferred, -EINVAL); - assert_return(lifetime_valid, -EINVAL); - - if (!lease->addr_iter) - return -ENOMSG; - - memcpy(addr, &lease->addr_iter->iaaddr.address, - sizeof(struct in6_addr)); - *lifetime_preferred = - be32toh(lease->addr_iter->iaaddr.lifetime_preferred); - *lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid); - - lease->addr_iter = lease->addr_iter->addresses_next; - - return 0; -} - -void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) { - if (lease) - lease->addr_iter = lease->ia.addresses; -} - -int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, - uint8_t *prefix_len, - uint32_t *lifetime_preferred, - uint32_t *lifetime_valid) { - assert_return(lease, -EINVAL); - assert_return(prefix, -EINVAL); - assert_return(prefix_len, -EINVAL); - assert_return(lifetime_preferred, -EINVAL); - assert_return(lifetime_valid, -EINVAL); - - if (!lease->prefix_iter) - return -ENOMSG; - - memcpy(prefix, &lease->prefix_iter->iapdprefix.address, - sizeof(struct in6_addr)); - *prefix_len = lease->prefix_iter->iapdprefix.prefixlen; - *lifetime_preferred = - be32toh(lease->prefix_iter->iapdprefix.lifetime_preferred); - *lifetime_valid = - be32toh(lease->prefix_iter->iapdprefix.lifetime_valid); - - lease->prefix_iter = lease->prefix_iter->addresses_next; - - return 0; -} - -void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease) { - if (lease) - lease->prefix_iter = lease->pd.addresses; -} - -int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { - int r; - - assert_return(lease, -EINVAL); - assert_return(optval, -EINVAL); - - if (!optlen) - return 0; - - r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns, - lease->dns_count, - &lease->dns_allocated); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m"); - - lease->dns_count = r; - - return 0; -} - -int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **addrs) { - assert_return(lease, -EINVAL); - assert_return(addrs, -EINVAL); - - if (lease->dns_count) { - *addrs = lease->dns; - return lease->dns_count; - } - - return -ENOENT; -} - -int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, - size_t optlen) { - int r; - char **domains; - - assert_return(lease, -EINVAL); - assert_return(optval, -EINVAL); - - if (!optlen) - return 0; - - r = dhcp6_option_parse_domainname_list(optval, optlen, &domains); - if (r < 0) - return 0; - - strv_free_and_replace(lease->domains, domains); - lease->domains_count = r; - - return r; -} - -int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) { - assert_return(lease, -EINVAL); - assert_return(domains, -EINVAL); - - if (lease->domains_count) { - *domains = lease->domains; - return lease->domains_count; - } - - return -ENOENT; -} - -int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { - int r; - uint16_t subopt; - size_t sublen; - uint8_t *subval; - - assert_return(lease, -EINVAL); - assert_return(optval, -EINVAL); - - lease->ntp = mfree(lease->ntp); - lease->ntp_count = 0; - lease->ntp_allocated = 0; - - while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen, - &subval)) >= 0) { - int s; - char **servers; - - switch(subopt) { - case DHCP6_NTP_SUBOPTION_SRV_ADDR: - case DHCP6_NTP_SUBOPTION_MC_ADDR: - if (sublen != 16) - return 0; - - s = dhcp6_option_parse_ip6addrs(subval, sublen, - &lease->ntp, - lease->ntp_count, - &lease->ntp_allocated); - if (s < 0) - return s; - - lease->ntp_count = s; - - break; - - case DHCP6_NTP_SUBOPTION_SRV_FQDN: - r = dhcp6_option_parse_domainname_list(subval, sublen, - &servers); - if (r < 0) - return 0; - - strv_free_and_replace(lease->ntp_fqdn, servers); - lease->ntp_fqdn_count = r; - - break; - } - } - - if (r != -ENOMSG) - return r; - - return 0; -} - -int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { - int r; - - assert_return(lease, -EINVAL); - assert_return(optval, -EINVAL); - - if (!optlen) - return 0; - - if (lease->ntp || lease->ntp_fqdn) { - log_dhcp6_client(client, "NTP information already provided"); - - return 0; - } - - log_dhcp6_client(client, "Using deprecated SNTP information"); - - r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp, - lease->ntp_count, - &lease->ntp_allocated); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m"); - - lease->ntp_count = r; - - return 0; -} - -int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, - const struct in6_addr **addrs) { - assert_return(lease, -EINVAL); - assert_return(addrs, -EINVAL); - - if (lease->ntp_count) { - *addrs = lease->ntp; - return lease->ntp_count; - } - - return -ENOENT; -} - -int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) { - assert_return(lease, -EINVAL); - assert_return(ntp_fqdn, -EINVAL); - - if (lease->ntp_fqdn_count) { - *ntp_fqdn = lease->ntp_fqdn; - return lease->ntp_fqdn_count; - } - - return -ENOENT; -} - -int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, - size_t optlen) { - int r; - char *fqdn; - - assert_return(lease, -EINVAL); - assert_return(optval, -EINVAL); - - if (optlen < 2) - return -ENODATA; - - /* Ignore the flags field, it doesn't carry any useful - information for clients. */ - r = dhcp6_option_parse_domainname(optval + 1, optlen - 1, &fqdn); - if (r < 0) - return r; - - return free_and_replace(lease->fqdn, fqdn); -} - -int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **fqdn) { - assert_return(lease, -EINVAL); - assert_return(fqdn, -EINVAL); - - if (lease->fqdn) { - *fqdn = lease->fqdn; - return 0; - } - - return -ENOENT; -} - -static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { - assert(lease); - - free(lease->serverid); - dhcp6_lease_free_ia(&lease->ia); - dhcp6_lease_free_ia(&lease->pd); - - free(lease->dns); - free(lease->fqdn); - - lease->domains = strv_free(lease->domains); - - free(lease->ntp); - - lease->ntp_fqdn = strv_free(lease->ntp_fqdn); - return mfree(lease); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease, sd_dhcp6_lease, dhcp6_lease_free); - -int dhcp6_lease_new(sd_dhcp6_lease **ret) { - sd_dhcp6_lease *lease; - - lease = new0(sd_dhcp6_lease, 1); - if (!lease) - return -ENOMEM; - - lease->n_ref = 1; - - LIST_HEAD_INIT(lease->ia.addresses); - - *ret = lease; - return 0; -} diff --git a/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c deleted file mode 100644 index 096afbd8..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c +++ /dev/null @@ -1,543 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include -#include - -#include "sd-ipv4acd.h" - -#include "alloc-util.h" -#include "arp-util.h" -#include "ether-addr-util.h" -#include "event-util.h" -#include "fd-util.h" -#include "format-util.h" -#include "in-addr-util.h" -#include "log-link.h" -#include "random-util.h" -#include "siphash24.h" -#include "string-table.h" -#include "string-util.h" -#include "time-util.h" - -/* Constants from the RFC */ -#define PROBE_WAIT_USEC (1U * USEC_PER_SEC) -#define PROBE_NUM 3U -#define PROBE_MIN_USEC (1U * USEC_PER_SEC) -#define PROBE_MAX_USEC (2U * USEC_PER_SEC) -#define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC) -#define ANNOUNCE_NUM 2U -#define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC) -#define MAX_CONFLICTS 10U -#define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC) -#define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC) - -typedef enum IPv4ACDState { - IPV4ACD_STATE_INIT, - IPV4ACD_STATE_STARTED, - IPV4ACD_STATE_WAITING_PROBE, - IPV4ACD_STATE_PROBING, - IPV4ACD_STATE_WAITING_ANNOUNCE, - IPV4ACD_STATE_ANNOUNCING, - IPV4ACD_STATE_RUNNING, - _IPV4ACD_STATE_MAX, - _IPV4ACD_STATE_INVALID = -1 -} IPv4ACDState; - -struct sd_ipv4acd { - unsigned n_ref; - - IPv4ACDState state; - int ifindex; - int fd; - - char ifname[IF_NAMESIZE + 1]; - unsigned n_iteration; - unsigned n_conflict; - - sd_event_source *receive_message_event_source; - sd_event_source *timer_event_source; - - usec_t defend_window; - be32_t address; - - /* External */ - struct ether_addr mac_addr; - - sd_event *event; - int event_priority; - sd_ipv4acd_callback_t callback; - void* userdata; -}; - -#define log_ipv4acd_errno(acd, error, fmt, ...) \ - log_interface_full_errno(sd_ipv4acd_get_ifname(acd), LOG_DEBUG, error, "IPV4ACD: " fmt, ##__VA_ARGS__) -#define log_ipv4acd(acd, fmt, ...) \ - log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__) - -static const char * const ipv4acd_state_table[_IPV4ACD_STATE_MAX] = { - [IPV4ACD_STATE_INIT] = "init", - [IPV4ACD_STATE_STARTED] = "started", - [IPV4ACD_STATE_WAITING_PROBE] = "waiting-probe", - [IPV4ACD_STATE_PROBING] = "probing", - [IPV4ACD_STATE_WAITING_ANNOUNCE] = "waiting-announce", - [IPV4ACD_STATE_ANNOUNCING] = "announcing", - [IPV4ACD_STATE_RUNNING] = "running", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ipv4acd_state, IPv4ACDState); - -static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { - assert(acd); - assert(st < _IPV4ACD_STATE_MAX); - - if (st != acd->state) - log_ipv4acd(acd, "%s -> %s", ipv4acd_state_to_string(acd->state), ipv4acd_state_to_string(st)); - - if (st == acd->state && !reset_counter) - acd->n_iteration++; - else { - acd->state = st; - acd->n_iteration = 0; - } -} - -static void ipv4acd_reset(sd_ipv4acd *acd) { - assert(acd); - - (void) event_source_disable(acd->timer_event_source); - acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source); - - acd->fd = safe_close(acd->fd); - - ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true); -} - -static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) { - assert(acd); - - acd->timer_event_source = sd_event_source_unref(acd->timer_event_source); - - ipv4acd_reset(acd); - sd_ipv4acd_detach_event(acd); - - return mfree(acd); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4acd, sd_ipv4acd, ipv4acd_free); - -int sd_ipv4acd_new(sd_ipv4acd **ret) { - _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL; - - assert_return(ret, -EINVAL); - - acd = new(sd_ipv4acd, 1); - if (!acd) - return -ENOMEM; - - *acd = (sd_ipv4acd) { - .n_ref = 1, - .state = IPV4ACD_STATE_INIT, - .ifindex = -1, - .fd = -1, - }; - - *ret = TAKE_PTR(acd); - - return 0; -} - -static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { - assert(acd); - - if (!acd->callback) - return; - - acd->callback(acd, event, acd->userdata); -} - -int sd_ipv4acd_stop(sd_ipv4acd *acd) { - IPv4ACDState old_state; - - if (!acd) - return 0; - - old_state = acd->state; - - ipv4acd_reset(acd); - - if (old_state == IPV4ACD_STATE_INIT) - return 0; - - log_ipv4acd(acd, "STOPPED"); - - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); - - return 0; -} - -static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata); - -static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) { - usec_t next_timeout, time_now; - - assert(acd); - - next_timeout = usec; - - if (random_usec > 0) - next_timeout += (usec_t) random_u64() % random_usec; - - assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0); - - return event_reset_time(acd->event, &acd->timer_event_source, - clock_boottime_or_monotonic(), - time_now + next_timeout, 0, - ipv4acd_on_timeout, acd, - acd->event_priority, "ipv4acd-timer", true); -} - -static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) { - assert(acd); - assert(arp); - - /* see the BPF */ - if (memcmp(arp->arp_spa, &acd->address, sizeof(acd->address)) == 0) - return true; - - /* the TPA matched instead of the SPA, this is not a conflict */ - return false; -} - -static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { - sd_ipv4acd *acd = userdata; - int r = 0; - - assert(acd); - - switch (acd->state) { - - case IPV4ACD_STATE_STARTED: - ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true); - - if (acd->n_conflict >= MAX_CONFLICTS) { - char ts[FORMAT_TIMESPAN_MAX]; - log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0)); - - r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC); - if (r < 0) - goto fail; - } else { - r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC); - if (r < 0) - goto fail; - } - - break; - - case IPV4ACD_STATE_WAITING_PROBE: - case IPV4ACD_STATE_PROBING: - /* Send a probe */ - r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); - if (r < 0) { - log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m"); - goto fail; - } else { - _cleanup_free_ char *address = NULL; - union in_addr_union addr = { .in.s_addr = acd->address }; - - (void) in_addr_to_string(AF_INET, &addr, &address); - log_ipv4acd(acd, "Probing %s", strna(address)); - } - - if (acd->n_iteration < PROBE_NUM - 2) { - ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false); - - r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC)); - if (r < 0) - goto fail; - } else { - ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true); - - r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0); - if (r < 0) - goto fail; - } - - break; - - case IPV4ACD_STATE_ANNOUNCING: - if (acd->n_iteration >= ANNOUNCE_NUM - 1) { - ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false); - break; - } - - _fallthrough_; - case IPV4ACD_STATE_WAITING_ANNOUNCE: - /* Send announcement packet */ - r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); - if (r < 0) { - log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); - goto fail; - } else - log_ipv4acd(acd, "ANNOUNCE"); - - ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false); - - r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0); - if (r < 0) - goto fail; - - if (acd->n_iteration == 0) { - acd->n_conflict = 0; - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND); - } - - break; - - default: - assert_not_reached("Invalid state."); - } - - return 0; - -fail: - sd_ipv4acd_stop(acd); - return 0; -} - -static void ipv4acd_on_conflict(sd_ipv4acd *acd) { - _cleanup_free_ char *address = NULL; - union in_addr_union addr = { .in.s_addr = acd->address }; - - assert(acd); - - acd->n_conflict++; - - (void) in_addr_to_string(AF_INET, &addr, &address); - log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict); - - ipv4acd_reset(acd); - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT); -} - -static int ipv4acd_on_packet( - sd_event_source *s, - int fd, - uint32_t revents, - void *userdata) { - - sd_ipv4acd *acd = userdata; - struct ether_arp packet; - ssize_t n; - int r; - - assert(s); - assert(acd); - assert(fd >= 0); - - n = recv(fd, &packet, sizeof(struct ether_arp), 0); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); - goto fail; - } - if ((size_t) n != sizeof(struct ether_arp)) { - log_ipv4acd(acd, "Ignoring too short ARP packet."); - return 0; - } - - switch (acd->state) { - - case IPV4ACD_STATE_ANNOUNCING: - case IPV4ACD_STATE_RUNNING: - - if (ipv4acd_arp_conflict(acd, &packet)) { - usec_t ts; - - assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0); - - /* Defend address */ - if (ts > acd->defend_window) { - acd->defend_window = ts + DEFEND_INTERVAL_USEC; - r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); - if (r < 0) { - log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); - goto fail; - } else - log_ipv4acd(acd, "DEFEND"); - - } else - ipv4acd_on_conflict(acd); - } - break; - - case IPV4ACD_STATE_WAITING_PROBE: - case IPV4ACD_STATE_PROBING: - case IPV4ACD_STATE_WAITING_ANNOUNCE: - /* BPF ensures this packet indicates a conflict */ - ipv4acd_on_conflict(acd); - break; - - default: - assert_not_reached("Invalid state."); - } - - return 0; - -fail: - sd_ipv4acd_stop(acd); - return 0; -} - -int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) { - char ifname[IF_NAMESIZE + 1]; - - assert_return(acd, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - - if (!format_ifname(ifindex, ifname)) - return -ENODEV; - - strcpy(acd->ifname, ifname); - acd->ifindex = ifindex; - - return 0; -} - -int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) { - if (!acd) - return -EINVAL; - - return acd->ifindex; -} - -const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd) { - if (!acd) - return NULL; - - return empty_to_null(acd->ifname); -} - -int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) { - assert_return(acd, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - - acd->mac_addr = *addr; - - return 0; -} - -int sd_ipv4acd_detach_event(sd_ipv4acd *acd) { - assert_return(acd, -EINVAL); - - acd->event = sd_event_unref(acd->event); - - return 0; -} - -int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) { - int r; - - assert_return(acd, -EINVAL); - assert_return(!acd->event, -EBUSY); - - if (event) - acd->event = sd_event_ref(event); - else { - r = sd_event_default(&acd->event); - if (r < 0) - return r; - } - - acd->event_priority = priority; - - return 0; -} - -int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) { - assert_return(acd, -EINVAL); - - acd->callback = cb; - acd->userdata = userdata; - - return 0; -} - -int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { - assert_return(acd, -EINVAL); - assert_return(address, -EINVAL); - assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - - acd->address = address->s_addr; - - return 0; -} - -int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) { - assert_return(acd, -EINVAL); - assert_return(address, -EINVAL); - - address->s_addr = acd->address; - - return 0; -} - -int sd_ipv4acd_is_running(sd_ipv4acd *acd) { - assert_return(acd, false); - - return acd->state != IPV4ACD_STATE_INIT; -} - -int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) { - int r; - - assert_return(acd, -EINVAL); - assert_return(acd->event, -EINVAL); - assert_return(acd->ifindex > 0, -EINVAL); - assert_return(acd->address != 0, -EINVAL); - assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL); - assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - - r = arp_network_bind_raw_socket(acd->ifindex, acd->address, &acd->mac_addr); - if (r < 0) - return r; - - CLOSE_AND_REPLACE(acd->fd, r); - acd->defend_window = 0; - - if (reset_conflicts) - acd->n_conflict = 0; - - r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd); - if (r < 0) - goto fail; - - r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority); - if (r < 0) - goto fail; - - (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message"); - - r = ipv4acd_set_next_wakeup(acd, 0, 0); - if (r < 0) - goto fail; - - ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); - return 0; - -fail: - ipv4acd_reset(acd); - return r; -} diff --git a/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c deleted file mode 100644 index c5e7a91f..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c +++ /dev/null @@ -1,342 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include -#include - -#include "sd-id128.h" -#include "sd-ipv4acd.h" -#include "sd-ipv4ll.h" - -#include "alloc-util.h" -#include "ether-addr-util.h" -#include "in-addr-util.h" -#include "log-link.h" -#include "random-util.h" -#include "siphash24.h" -#include "sparse-endian.h" -#include "string-util.h" -#include "util.h" - -#define IPV4LL_NETWORK UINT32_C(0xA9FE0000) -#define IPV4LL_NETMASK UINT32_C(0xFFFF0000) - -#define IPV4LL_DONT_DESTROY(ll) \ - _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll) - -struct sd_ipv4ll { - unsigned n_ref; - - sd_ipv4acd *acd; - - be32_t address; /* the address pushed to ACD */ - struct ether_addr mac; - - struct { - le64_t value; - le64_t generation; - } seed; - bool seed_set; - - /* External */ - be32_t claimed_address; - - sd_ipv4ll_callback_t callback; - void* userdata; -}; - -#define log_ipv4ll_errno(ll, error, fmt, ...) \ - log_interface_full_errno(sd_ipv4ll_get_ifname(ll), LOG_DEBUG, error, "IPV4LL: " fmt, ##__VA_ARGS__) -#define log_ipv4ll(ll, fmt, ...) \ - log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__) - -static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); - -static sd_ipv4ll *ipv4ll_free(sd_ipv4ll *ll) { - assert(ll); - - sd_ipv4acd_unref(ll->acd); - return mfree(ll); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4ll, sd_ipv4ll, ipv4ll_free); - -int sd_ipv4ll_new(sd_ipv4ll **ret) { - _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL; - int r; - - assert_return(ret, -EINVAL); - - ll = new0(sd_ipv4ll, 1); - if (!ll) - return -ENOMEM; - - ll->n_ref = 1; - - r = sd_ipv4acd_new(&ll->acd); - if (r < 0) - return r; - - r = sd_ipv4acd_set_callback(ll->acd, ipv4ll_on_acd, ll); - if (r < 0) - return r; - - *ret = TAKE_PTR(ll); - - return 0; -} - -int sd_ipv4ll_stop(sd_ipv4ll *ll) { - if (!ll) - return 0; - - return sd_ipv4acd_stop(ll->acd); -} - -int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) { - assert_return(ll, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - - return sd_ipv4acd_set_ifindex(ll->acd, ifindex); -} - -int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll) { - if (!ll) - return -EINVAL; - - return sd_ipv4acd_get_ifindex(ll->acd); -} - -const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll) { - if (!ll) - return NULL; - - return sd_ipv4acd_get_ifname(ll->acd); -} - -int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) { - int r; - - assert_return(ll, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - - r = sd_ipv4acd_set_mac(ll->acd, addr); - if (r < 0) - return r; - - ll->mac = *addr; - return 0; -} - -int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { - assert_return(ll, -EINVAL); - - return sd_ipv4acd_detach_event(ll->acd); -} - -int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) { - assert_return(ll, -EINVAL); - - return sd_ipv4acd_attach_event(ll->acd, event, priority); -} - -int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) { - assert_return(ll, -EINVAL); - - ll->callback = cb; - ll->userdata = userdata; - - return 0; -} - -int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) { - assert_return(ll, -EINVAL); - assert_return(address, -EINVAL); - - if (ll->claimed_address == 0) - return -ENOENT; - - address->s_addr = ll->claimed_address; - - return 0; -} - -int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed) { - assert_return(ll, -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - - ll->seed.value = htole64(seed); - ll->seed_set = true; - - return 0; -} - -int sd_ipv4ll_is_running(sd_ipv4ll *ll) { - assert_return(ll, false); - - return sd_ipv4acd_is_running(ll->acd); -} - -static bool ipv4ll_address_is_valid(const struct in_addr *address) { - assert(address); - - if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address)) - return false; - - return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U); -} - -int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) { - int r; - - assert_return(ll, -EINVAL); - assert_return(address, -EINVAL); - assert_return(ipv4ll_address_is_valid(address), -EINVAL); - - r = sd_ipv4acd_set_address(ll->acd, address); - if (r < 0) - return r; - - ll->address = address->s_addr; - - return 0; -} - -#define PICK_HASH_KEY SD_ID128_MAKE(15,ac,82,a6,d6,3f,49,78,98,77,5d,0c,69,02,94,0b) - -static int ipv4ll_pick_address(sd_ipv4ll *ll) { - _cleanup_free_ char *address = NULL; - be32_t addr; - - assert(ll); - - do { - uint64_t h; - - h = siphash24(&ll->seed, sizeof(ll->seed), PICK_HASH_KEY.bytes); - - /* Increase the generation counter by one */ - ll->seed.generation = htole64(le64toh(ll->seed.generation) + 1); - - addr = htobe32((h & UINT32_C(0x0000FFFF)) | IPV4LL_NETWORK); - } while (addr == ll->address || - IN_SET(be32toh(addr) & 0x0000FF00U, 0x0000U, 0xFF00U)); - - (void) in_addr_to_string(AF_INET, &(union in_addr_union) { .in.s_addr = addr }, &address); - log_ipv4ll(ll, "Picked new IP address %s.", strna(address)); - - return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr }); -} - -#define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) - -static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) { - int r; - bool picked_address = false; - - assert_return(ll, -EINVAL); - assert_return(!ether_addr_is_null(&ll->mac), -EINVAL); - - /* If no random seed is set, generate some from the MAC address */ - if (!ll->seed_set) - ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes)); - - if (reset_generation) - ll->seed.generation = 0; - - if (ll->address == 0) { - r = ipv4ll_pick_address(ll); - if (r < 0) - return r; - - picked_address = true; - } - - r = sd_ipv4acd_start(ll->acd, reset_generation); - if (r < 0) { - - /* We couldn't start? If so, let's forget the picked address again, the user might make a change and - * retry, and we want the new data to take effect when picking an address. */ - if (picked_address) - ll->address = 0; - - return r; - } - - return 1; -} - -int sd_ipv4ll_start(sd_ipv4ll *ll) { - assert_return(ll, -EINVAL); - - if (sd_ipv4ll_is_running(ll)) - return 0; - - return ipv4ll_start_internal(ll, true); -} - -int sd_ipv4ll_restart(sd_ipv4ll *ll) { - ll->address = 0; - - return ipv4ll_start_internal(ll, false); -} - -static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) { - assert(ll); - - if (ll->callback) - ll->callback(ll, event, ll->userdata); -} - -void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { - sd_ipv4ll *ll = userdata; - IPV4LL_DONT_DESTROY(ll); - int r; - - assert(acd); - assert(ll); - - switch (event) { - - case SD_IPV4ACD_EVENT_STOP: - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); - ll->claimed_address = 0; - break; - - case SD_IPV4ACD_EVENT_BIND: - ll->claimed_address = ll->address; - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND); - break; - - case SD_IPV4ACD_EVENT_CONFLICT: - /* if an address was already bound we must call up to the - user to handle this, otherwise we just try again */ - if (ll->claimed_address != 0) { - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_CONFLICT); - - ll->claimed_address = 0; - } else { - r = sd_ipv4ll_restart(ll); - if (r < 0) - goto error; - } - - break; - - default: - assert_not_reached("Invalid IPv4ACD event."); - } - - return; - -error: - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); -} diff --git a/src/core/systemd/src/libsystemd-network/sd-lldp.c b/src/core/systemd/src/libsystemd-network/sd-lldp.c deleted file mode 100644 index b12d8e27..00000000 --- a/src/core/systemd/src/libsystemd-network/sd-lldp.c +++ /dev/null @@ -1,500 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "sd-lldp.h" - -#include "alloc-util.h" -#include "ether-addr-util.h" -#include "event-util.h" -#include "fd-util.h" -#include "lldp-internal.h" -#include "lldp-neighbor.h" -#include "lldp-network.h" -#include "memory-util.h" -#include "socket-util.h" -#include "sort-util.h" -#include "string-table.h" - -#define LLDP_DEFAULT_NEIGHBORS_MAX 128U - -static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = { - [SD_LLDP_EVENT_ADDED] = "added", - [SD_LLDP_EVENT_REMOVED] = "removed", - [SD_LLDP_EVENT_UPDATED] = "updated", - [SD_LLDP_EVENT_REFRESHED] = "refreshed", -}; - -DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event); - -static void lldp_flush_neighbors(sd_lldp *lldp) { - assert(lldp); - - hashmap_clear(lldp->neighbor_by_id); -} - -static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) { - assert(lldp); - assert(event >= 0 && event < _SD_LLDP_EVENT_MAX); - - if (!lldp->callback) { - log_lldp("Received '%s' event.", lldp_event_to_string(event)); - return; - } - - log_lldp("Invoking callback for '%s' event.", lldp_event_to_string(event)); - lldp->callback(lldp, event, n, lldp->userdata); -} - -static int lldp_make_space(sd_lldp *lldp, size_t extra) { - usec_t t = USEC_INFINITY; - bool changed = false; - - assert(lldp); - - /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries - * are free. */ - - for (;;) { - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - - n = prioq_peek(lldp->neighbor_by_expiry); - if (!n) - break; - - sd_lldp_neighbor_ref(n); - - if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra)) - goto remove_one; - - if (t == USEC_INFINITY) - t = now(clock_boottime_or_monotonic()); - - if (n->until > t) - break; - - remove_one: - lldp_neighbor_unlink(n); - lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n); - changed = true; - } - - return changed; -} - -static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { - assert(lldp); - assert(n); - - /* Don't keep data with a zero TTL */ - if (n->ttl <= 0) - return false; - - /* Filter out data from the filter address */ - if (!ether_addr_is_null(&lldp->filter_address) && - ether_addr_equal(&lldp->filter_address, &n->source_address)) - return false; - - /* Only add if the neighbor has a capability we are interested in. Note that we also store all neighbors with - * no caps field set. */ - if (n->has_capabilities && - (n->enabled_capabilities & lldp->capability_mask) == 0) - return false; - - /* Keep everything else */ - return true; -} - -static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor); - -static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL; - bool keep; - int r; - - assert(lldp); - assert(n); - assert(!n->lldp); - - keep = lldp_keep_neighbor(lldp, n); - - /* First retrieve the old entry for this MSAP */ - old = hashmap_get(lldp->neighbor_by_id, &n->id); - if (old) { - sd_lldp_neighbor_ref(old); - - if (!keep) { - lldp_neighbor_unlink(old); - lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old); - return 0; - } - - if (lldp_neighbor_equal(n, old)) { - /* Is this equal, then restart the TTL counter, but don't do anything else. */ - old->timestamp = n->timestamp; - lldp_start_timer(lldp, old); - lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old); - return 0; - } - - /* Data changed, remove the old entry, and add a new one */ - lldp_neighbor_unlink(old); - - } else if (!keep) - return 0; - - /* Then, make room for at least one new neighbor */ - lldp_make_space(lldp, 1); - - r = hashmap_put(lldp->neighbor_by_id, &n->id, n); - if (r < 0) - goto finish; - - r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx); - if (r < 0) { - assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n); - goto finish; - } - - n->lldp = lldp; - - lldp_start_timer(lldp, n); - lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n); - - return 1; - -finish: - if (old) - lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old); - - return r; -} - -static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) { - int r; - - assert(lldp); - assert(n); - - r = lldp_neighbor_parse(n); - if (r == -EBADMSG) /* Ignore bad messages */ - return 0; - if (r < 0) - return r; - - r = lldp_add_neighbor(lldp, n); - if (r < 0) { - log_lldp_errno(r, "Failed to add datagram. Ignoring."); - return 0; - } - - log_lldp("Successfully processed LLDP datagram."); - return 0; -} - -static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - ssize_t space, length; - sd_lldp *lldp = userdata; - struct timespec ts; - - assert(fd >= 0); - assert(lldp); - - space = next_datagram_size_fd(fd); - if (space < 0) - return log_lldp_errno(space, "Failed to determine datagram size to read: %m"); - - n = lldp_neighbor_new(space); - if (!n) - return -ENOMEM; - - length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); - if (length < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - return log_lldp_errno(errno, "Failed to read LLDP datagram: %m"); - } - - if ((size_t) length != n->raw_size) { - log_lldp("Packet size mismatch."); - return -EINVAL; - } - - /* Try to get the timestamp of this packet if it is known */ - if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0) - triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts)); - else - triple_timestamp_get(&n->timestamp); - - return lldp_handle_datagram(lldp, n); -} - -static void lldp_reset(sd_lldp *lldp) { - assert(lldp); - - (void) event_source_disable(lldp->timer_event_source); - lldp->io_event_source = sd_event_source_unref(lldp->io_event_source); - lldp->fd = safe_close(lldp->fd); -} - -_public_ int sd_lldp_start(sd_lldp *lldp) { - int r; - - assert_return(lldp, -EINVAL); - assert_return(lldp->event, -EINVAL); - assert_return(lldp->ifindex > 0, -EINVAL); - - if (lldp->fd >= 0) - return 0; - - assert(!lldp->io_event_source); - - lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex); - if (lldp->fd < 0) - return lldp->fd; - - r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp); - if (r < 0) - goto fail; - - r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority); - if (r < 0) - goto fail; - - (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io"); - - log_lldp("Started LLDP client"); - return 1; - -fail: - lldp_reset(lldp); - return r; -} - -_public_ int sd_lldp_stop(sd_lldp *lldp) { - if (!lldp) - return 0; - - if (lldp->fd < 0) - return 0; - - log_lldp("Stopping LLDP client"); - - lldp_reset(lldp); - lldp_flush_neighbors(lldp); - - return 1; -} - -_public_ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) { - int r; - - assert_return(lldp, -EINVAL); - assert_return(lldp->fd < 0, -EBUSY); - assert_return(!lldp->event, -EBUSY); - - if (event) - lldp->event = sd_event_ref(event); - else { - r = sd_event_default(&lldp->event); - if (r < 0) - return r; - } - - lldp->event_priority = priority; - - return 0; -} - -_public_ int sd_lldp_detach_event(sd_lldp *lldp) { - - assert_return(lldp, -EINVAL); - assert_return(lldp->fd < 0, -EBUSY); - - lldp->event = sd_event_unref(lldp->event); - return 0; -} - -_public_ sd_event* sd_lldp_get_event(sd_lldp *lldp) { - assert_return(lldp, NULL); - - return lldp->event; -} - -_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) { - assert_return(lldp, -EINVAL); - - lldp->callback = cb; - lldp->userdata = userdata; - - return 0; -} - -_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) { - assert_return(lldp, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(lldp->fd < 0, -EBUSY); - - lldp->ifindex = ifindex; - return 0; -} - -static sd_lldp* lldp_free(sd_lldp *lldp) { - assert(lldp); - - lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source); - - lldp_reset(lldp); - sd_lldp_detach_event(lldp); - lldp_flush_neighbors(lldp); - - hashmap_free(lldp->neighbor_by_id); - prioq_free(lldp->neighbor_by_expiry); - return mfree(lldp); -} - -DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp, sd_lldp, lldp_free); - -_public_ int sd_lldp_new(sd_lldp **ret) { - _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; - int r; - - assert_return(ret, -EINVAL); - - lldp = new(sd_lldp, 1); - if (!lldp) - return -ENOMEM; - - *lldp = (sd_lldp) { - .n_ref = 1, - .fd = -1, - .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX, - .capability_mask = (uint16_t) -1, - }; - - lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops); - if (!lldp->neighbor_by_id) - return -ENOMEM; - - r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func); - if (r < 0) - return r; - - *ret = TAKE_PTR(lldp); - - return 0; -} - -static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) { - return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id); -} - -static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) { - sd_lldp *lldp = userdata; - int r; - - r = lldp_make_space(lldp, 0); - if (r < 0) - return log_lldp_errno(r, "Failed to make space: %m"); - - r = lldp_start_timer(lldp, NULL); - if (r < 0) - return log_lldp_errno(r, "Failed to restart timer: %m"); - - return 0; -} - -static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { - sd_lldp_neighbor *n; - - assert(lldp); - - if (neighbor) - lldp_neighbor_start_ttl(neighbor); - - n = prioq_peek(lldp->neighbor_by_expiry); - if (!n) - return event_source_disable(lldp->timer_event_source); - - if (!lldp->event) - return 0; - - return event_reset_time(lldp->event, &lldp->timer_event_source, - clock_boottime_or_monotonic(), - n->until, 0, - on_timer_event, lldp, - lldp->event_priority, "lldp-timer", true); -} - -_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { - sd_lldp_neighbor **l = NULL, *n; - int k = 0, r; - - assert_return(lldp, -EINVAL); - assert_return(ret, -EINVAL); - - if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */ - *ret = NULL; - return 0; - } - - l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id)); - if (!l) - return -ENOMEM; - - r = lldp_start_timer(lldp, NULL); - if (r < 0) { - free(l); - return r; - } - - HASHMAP_FOREACH(n, lldp->neighbor_by_id) - l[k++] = sd_lldp_neighbor_ref(n); - - assert((size_t) k == hashmap_size(lldp->neighbor_by_id)); - - /* Return things in a stable order */ - typesafe_qsort(l, k, neighbor_compare_func); - *ret = l; - - return k; -} - -_public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) { - assert_return(lldp, -EINVAL); - assert_return(m > 0, -EINVAL); - - lldp->neighbors_max = m; - lldp_make_space(lldp, 0); - - return 0; -} - -_public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) { - assert_return(lldp, -EINVAL); - assert_return(mask != 0, -EINVAL); - - lldp->capability_mask = mask; - - return 0; -} - -_public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *addr) { - assert_return(lldp, -EINVAL); - - /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so - * that our own can be filtered out here. */ - - if (addr) - lldp->filter_address = *addr; - else - zero(lldp->filter_address); - - return 0; -} diff --git a/src/core/systemd/src/libsystemd/sd-event/event-source.h b/src/core/systemd/src/libsystemd/sd-event/event-source.h deleted file mode 100644 index f0d2a1b9..00000000 --- a/src/core/systemd/src/libsystemd/sd-event/event-source.h +++ /dev/null @@ -1,220 +0,0 @@ -#pragma once -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include -#include -#include - -#include "sd-event.h" - -#include "fs-util.h" -#include "hashmap.h" -#include "list.h" -#include "prioq.h" -#include "ratelimit.h" - -typedef enum EventSourceType { - SOURCE_IO, - SOURCE_TIME_REALTIME, - SOURCE_TIME_BOOTTIME, - SOURCE_TIME_MONOTONIC, - SOURCE_TIME_REALTIME_ALARM, - SOURCE_TIME_BOOTTIME_ALARM, - SOURCE_SIGNAL, - SOURCE_CHILD, - SOURCE_DEFER, - SOURCE_POST, - SOURCE_EXIT, - SOURCE_WATCHDOG, - SOURCE_INOTIFY, - _SOURCE_EVENT_SOURCE_TYPE_MAX, - _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1 -} EventSourceType; - -/* All objects we use in epoll events start with this value, so that - * we know how to dispatch it */ -typedef enum WakeupType { - WAKEUP_NONE, - WAKEUP_EVENT_SOURCE, /* either I/O or pidfd wakeup */ - WAKEUP_CLOCK_DATA, - WAKEUP_SIGNAL_DATA, - WAKEUP_INOTIFY_DATA, - _WAKEUP_TYPE_MAX, - _WAKEUP_TYPE_INVALID = -1, -} WakeupType; - -struct inode_data; - -struct sd_event_source { - WakeupType wakeup; - - unsigned n_ref; - - sd_event *event; - void *userdata; - sd_event_handler_t prepare; - - char *description; - - EventSourceType type:5; - signed int enabled:3; - bool pending:1; - bool dispatching:1; - bool floating:1; - bool exit_on_failure:1; - bool ratelimited:1; - - int64_t priority; - unsigned pending_index; - unsigned prepare_index; - uint64_t pending_iteration; - uint64_t prepare_iteration; - - sd_event_destroy_t destroy_callback; - - LIST_FIELDS(sd_event_source, sources); - - RateLimit rate_limit; - - /* These are primarily fields relevant for time event sources, but since any event source can - * effectively become one when rate-limited, this is part of the common fields. */ - unsigned earliest_index; - unsigned latest_index; - - union { - struct { - sd_event_io_handler_t callback; - int fd; - uint32_t events; - uint32_t revents; - bool registered:1; - bool owned:1; - } io; - struct { - sd_event_time_handler_t callback; - usec_t next, accuracy; - } time; - struct { - sd_event_signal_handler_t callback; - struct signalfd_siginfo siginfo; - int sig; - } signal; - struct { - sd_event_child_handler_t callback; - siginfo_t siginfo; - pid_t pid; - int options; - int pidfd; - bool registered:1; /* whether the pidfd is registered in the epoll */ - bool pidfd_owned:1; /* close pidfd when event source is freed */ - bool process_owned:1; /* kill+reap process when event source is freed */ - bool exited:1; /* true if process exited (i.e. if there's value in SIGKILLing it if we want to get rid of it) */ - bool waited:1; /* true if process was waited for (i.e. if there's value in waitid(P_PID)'ing it if we want to get rid of it) */ - } child; - struct { - sd_event_handler_t callback; - } defer; - struct { - sd_event_handler_t callback; - } post; - struct { - sd_event_handler_t callback; - unsigned prioq_index; - } exit; - struct { - sd_event_inotify_handler_t callback; - uint32_t mask; - struct inode_data *inode_data; - LIST_FIELDS(sd_event_source, by_inode_data); - } inotify; - }; -}; - -struct clock_data { - WakeupType wakeup; - int fd; - - /* For all clocks we maintain two priority queues each, one - * ordered for the earliest times the events may be - * dispatched, and one ordered by the latest times they must - * have been dispatched. The range between the top entries in - * the two prioqs is the time window we can freely schedule - * wakeups in */ - - Prioq *earliest; - Prioq *latest; - usec_t next; - - bool needs_rearm:1; -}; - -struct signal_data { - WakeupType wakeup; - - /* For each priority we maintain one signal fd, so that we - * only have to dequeue a single event per priority at a - * time. */ - - int fd; - int64_t priority; - sigset_t sigset; - sd_event_source *current; -}; - -/* A structure listing all event sources currently watching a specific inode */ -struct inode_data { - /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */ - ino_t ino; - dev_t dev; - - /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can - * rearrange the priority still until then, as we need the original inode to change the priority as we need to - * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the - * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of - * the sd-event object, so that it is efficient to close everything, before entering the next event loop - * iteration. */ - int fd; - - /* The inotify "watch descriptor" */ - int wd; - - /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has - * most recently been set on the watch descriptor. */ - uint32_t combined_mask; - - /* All event sources subscribed to this inode */ - LIST_HEAD(sd_event_source, event_sources); - - /* The inotify object we watch this inode with */ - struct inotify_data *inotify_data; - - /* A linked list of all inode data objects with fds to close (see above) */ - LIST_FIELDS(struct inode_data, to_close); -}; - -/* A structure encapsulating an inotify fd */ -struct inotify_data { - WakeupType wakeup; - - /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at - * a time */ - - int fd; - int64_t priority; - - Hashmap *inodes; /* The inode_data structures keyed by dev+ino */ - Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */ - - /* The buffer we read inotify events into */ - union inotify_event_buffer buffer; - size_t buffer_filled; /* fill level of the buffer */ - - /* How many event sources are currently marked pending for this inotify. We won't read new events off the - * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing - * the events locally if they can't be coalesced). */ - unsigned n_pending; - - /* A linked list of all inotify objects with data already read, that still need processing. We keep this list - * to make it efficient to figure out what inotify objects to process data on next. */ - LIST_FIELDS(struct inotify_data, buffered); -}; diff --git a/src/core/systemd/src/libsystemd/sd-event/event-util.c b/src/core/systemd/src/libsystemd/sd-event/event-util.c deleted file mode 100644 index 7cc55be1..00000000 --- a/src/core/systemd/src/libsystemd/sd-event/event-util.c +++ /dev/null @@ -1,101 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include - -#include "event-source.h" -#include "event-util.h" -#include "log.h" -#include "string-util.h" - -int event_reset_time( - sd_event *e, - sd_event_source **s, - clockid_t clock, - uint64_t usec, - uint64_t accuracy, - sd_event_time_handler_t callback, - void *userdata, - int64_t priority, - const char *description, - bool force_reset) { - - bool created = false; - int enabled, r; - clockid_t c; - - assert(e); - assert(s); - - if (*s) { - if (!force_reset) { - r = sd_event_source_get_enabled(*s, &enabled); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to query whether event source \"%s\" is enabled or not: %m", - strna((*s)->description ?: description)); - - if (enabled != SD_EVENT_OFF) - return 0; - } - - r = sd_event_source_get_time_clock(*s, &c); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to get clock id of event source \"%s\": %m", strna((*s)->description ?: description)); - - if (c != clock) - return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "sd-event: Current clock id %i of event source \"%s\" is different from specified one %i.", - (int)c, - strna((*s)->description ? : description), - (int)clock); - - r = sd_event_source_set_time(*s, usec); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to set time for event source \"%s\": %m", strna((*s)->description ?: description)); - - r = sd_event_source_set_time_accuracy(*s, accuracy); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to set accuracy for event source \"%s\": %m", strna((*s)->description ?: description)); - - /* callback function is not updated, as we do not have sd_event_source_set_time_callback(). */ - - (void) sd_event_source_set_userdata(*s, userdata); - - r = sd_event_source_set_enabled(*s, SD_EVENT_ONESHOT); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to enable event source \"%s\": %m", strna((*s)->description ?: description)); - } else { - r = sd_event_add_time(e, s, clock, usec, accuracy, callback, userdata); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to create timer event \"%s\": %m", strna(description)); - - created = true; - } - - r = sd_event_source_set_priority(*s, priority); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to set priority for event source \"%s\": %m", strna((*s)->description ?: description)); - - if (description) { - r = sd_event_source_set_description(*s, description); - if (r < 0) - return log_debug_errno(r, "sd-event: Failed to set description for event source \"%s\": %m", description); - } - - return created; -} - -int event_source_disable(sd_event_source *s) { - if (!s) - return 0; - - return sd_event_source_set_enabled(s, SD_EVENT_OFF); -} - -int event_source_is_enabled(sd_event_source *s) { - if (!s) - return false; - - return sd_event_source_get_enabled(s, NULL); -} diff --git a/src/core/systemd/src/libsystemd/sd-event/event-util.h b/src/core/systemd/src/libsystemd/sd-event/event-util.h deleted file mode 100644 index c8f97bc8..00000000 --- a/src/core/systemd/src/libsystemd/sd-event/event-util.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include - -#include "sd-event.h" - -int event_reset_time(sd_event *e, sd_event_source **s, - clockid_t clock, uint64_t usec, uint64_t accuracy, - sd_event_time_handler_t callback, void *userdata, - int64_t priority, const char *description, bool force_reset); -int event_source_disable(sd_event_source *s); -int event_source_is_enabled(sd_event_source *s); diff --git a/src/core/systemd/src/libsystemd/sd-event/sd-event.c b/src/core/systemd/src/libsystemd/sd-event/sd-event.c deleted file mode 100644 index dda4be00..00000000 --- a/src/core/systemd/src/libsystemd/sd-event/sd-event.c +++ /dev/null @@ -1,4329 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "sd-daemon.h" -#include "sd-event.h" -#include "sd-id128.h" - -#include "alloc-util.h" -#include "env-util.h" -#include "event-source.h" -#include "fd-util.h" -#include "fs-util.h" -#include "hashmap.h" -#include "list.h" -#include "macro.h" -#include "memory-util.h" -#include "missing_syscall.h" -#include "prioq.h" -#include "process-util.h" -#include "set.h" -#include "signal-util.h" -#include "string-table.h" -#include "string-util.h" -#include "strxcpyx.h" -#include "time-util.h" - -#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) - -static bool EVENT_SOURCE_WATCH_PIDFD(sd_event_source *s) { - /* Returns true if this is a PID event source and can be implemented by watching EPOLLIN */ - return s && - s->type == SOURCE_CHILD && - s->child.pidfd >= 0 && - s->child.options == WEXITED; -} - -static bool event_source_is_online(sd_event_source *s) { - assert(s); - return s->enabled != SD_EVENT_OFF && !s->ratelimited; -} - -static bool event_source_is_offline(sd_event_source *s) { - assert(s); - return s->enabled == SD_EVENT_OFF || s->ratelimited; -} - -static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { - [SOURCE_IO] = "io", - [SOURCE_TIME_REALTIME] = "realtime", - [SOURCE_TIME_BOOTTIME] = "bootime", - [SOURCE_TIME_MONOTONIC] = "monotonic", - [SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm", - [SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm", - [SOURCE_SIGNAL] = "signal", - [SOURCE_CHILD] = "child", - [SOURCE_DEFER] = "defer", - [SOURCE_POST] = "post", - [SOURCE_EXIT] = "exit", - [SOURCE_WATCHDOG] = "watchdog", - [SOURCE_INOTIFY] = "inotify", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); - -#define EVENT_SOURCE_IS_TIME(t) \ - IN_SET((t), \ - SOURCE_TIME_REALTIME, \ - SOURCE_TIME_BOOTTIME, \ - SOURCE_TIME_MONOTONIC, \ - SOURCE_TIME_REALTIME_ALARM, \ - SOURCE_TIME_BOOTTIME_ALARM) - -#define EVENT_SOURCE_CAN_RATE_LIMIT(t) \ - IN_SET((t), \ - SOURCE_IO, \ - SOURCE_TIME_REALTIME, \ - SOURCE_TIME_BOOTTIME, \ - SOURCE_TIME_MONOTONIC, \ - SOURCE_TIME_REALTIME_ALARM, \ - SOURCE_TIME_BOOTTIME_ALARM, \ - SOURCE_SIGNAL, \ - SOURCE_DEFER, \ - SOURCE_INOTIFY) - -struct sd_event { - unsigned n_ref; - - int epoll_fd; - int watchdog_fd; - - Prioq *pending; - Prioq *prepare; - - /* timerfd_create() only supports these five clocks so far. We - * can add support for more clocks when the kernel learns to - * deal with them, too. */ - struct clock_data realtime; - struct clock_data boottime; - struct clock_data monotonic; - struct clock_data realtime_alarm; - struct clock_data boottime_alarm; - - usec_t perturb; - - sd_event_source **signal_sources; /* indexed by signal number */ - Hashmap *signal_data; /* indexed by priority */ - - Hashmap *child_sources; - unsigned n_online_child_sources; - - Set *post_sources; - - Prioq *exit; - - Hashmap *inotify_data; /* indexed by priority */ - - /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */ - LIST_HEAD(struct inode_data, inode_data_to_close); - - /* A list of inotify objects that already have events buffered which aren't processed yet */ - LIST_HEAD(struct inotify_data, inotify_data_buffered); - - pid_t original_pid; - - uint64_t iteration; - triple_timestamp timestamp; - int state; - - bool exit_requested:1; - bool need_process_child:1; - bool watchdog:1; - bool profile_delays:1; - - int exit_code; - - pid_t tid; - sd_event **default_event_ptr; - - usec_t watchdog_last, watchdog_period; - - unsigned n_sources; - - struct epoll_event *event_queue; - size_t event_queue_allocated; - - LIST_HEAD(sd_event_source, sources); - - usec_t last_run_usec, last_log_usec; - unsigned delays[sizeof(usec_t) * 8]; -}; - -static thread_local sd_event *default_event = NULL; - -static void source_disconnect(sd_event_source *s); -static void event_gc_inode_data(sd_event *e, struct inode_data *d); - -static sd_event *event_resolve(sd_event *e) { - return e == SD_EVENT_DEFAULT ? default_event : e; -} - -static int pending_prioq_compare(const void *a, const void *b) { - const sd_event_source *x = a, *y = b; - int r; - - assert(x->pending); - assert(y->pending); - - /* Enabled ones first */ - if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) - return -1; - if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) - return 1; - - /* Non rate-limited ones first. */ - r = CMP(!!x->ratelimited, !!y->ratelimited); - if (r != 0) - return r; - - /* Lower priority values first */ - r = CMP(x->priority, y->priority); - if (r != 0) - return r; - - /* Older entries first */ - return CMP(x->pending_iteration, y->pending_iteration); -} - -static int prepare_prioq_compare(const void *a, const void *b) { - const sd_event_source *x = a, *y = b; - int r; - - assert(x->prepare); - assert(y->prepare); - - /* Enabled ones first */ - if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) - return -1; - if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) - return 1; - - /* Non rate-limited ones first. */ - r = CMP(!!x->ratelimited, !!y->ratelimited); - if (r != 0) - return r; - - /* Move most recently prepared ones last, so that we can stop - * preparing as soon as we hit one that has already been - * prepared in the current iteration */ - r = CMP(x->prepare_iteration, y->prepare_iteration); - if (r != 0) - return r; - - /* Lower priority values first */ - return CMP(x->priority, y->priority); -} - -static usec_t time_event_source_next(const sd_event_source *s) { - assert(s); - - /* We have two kinds of event sources that have elapsation times associated with them: the actual - * time based ones and the ones for which a ratelimit can be in effect (where we want to be notified - * once the ratelimit time window ends). Let's return the next elapsing time depending on what we are - * looking at here. */ - - if (s->ratelimited) { /* If rate-limited the next elapsation is when the ratelimit time window ends */ - assert(s->rate_limit.begin != 0); - assert(s->rate_limit.interval != 0); - return usec_add(s->rate_limit.begin, s->rate_limit.interval); - } - - /* Otherwise this must be a time event source, if not ratelimited */ - if (EVENT_SOURCE_IS_TIME(s->type)) - return s->time.next; - - return USEC_INFINITY; -} - -static int earliest_time_prioq_compare(const void *a, const void *b) { - const sd_event_source *x = a, *y = b; - - /* Enabled ones first */ - if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) - return -1; - if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) - return 1; - - /* Move the pending ones to the end */ - if (!x->pending && y->pending) - return -1; - if (x->pending && !y->pending) - return 1; - - /* Order by time */ - return CMP(time_event_source_next(x), time_event_source_next(y)); -} - -static usec_t time_event_source_latest(const sd_event_source *s) { - assert(s); - - if (s->ratelimited) { /* For ratelimited stuff the earliest and the latest time shall actually be the - * same, as we should avoid adding additional inaccuracy on an inaccuracy time - * window */ - assert(s->rate_limit.begin != 0); - assert(s->rate_limit.interval != 0); - return usec_add(s->rate_limit.begin, s->rate_limit.interval); - } - - /* Must be a time event source, if not ratelimited */ - if (EVENT_SOURCE_IS_TIME(s->type)) - return usec_add(s->time.next, s->time.accuracy); - - return USEC_INFINITY; -} - -static int latest_time_prioq_compare(const void *a, const void *b) { - const sd_event_source *x = a, *y = b; - - /* Enabled ones first */ - if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) - return -1; - if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) - return 1; - - /* Move the pending ones to the end */ - if (!x->pending && y->pending) - return -1; - if (x->pending && !y->pending) - return 1; - - /* Order by time */ - return CMP(time_event_source_latest(x), time_event_source_latest(y)); -} - -static int exit_prioq_compare(const void *a, const void *b) { - const sd_event_source *x = a, *y = b; - - assert(x->type == SOURCE_EXIT); - assert(y->type == SOURCE_EXIT); - - /* Enabled ones first */ - if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) - return -1; - if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) - return 1; - - /* Lower priority values first */ - return CMP(x->priority, y->priority); -} - -static void free_clock_data(struct clock_data *d) { - assert(d); - assert(d->wakeup == WAKEUP_CLOCK_DATA); - - safe_close(d->fd); - prioq_free(d->earliest); - prioq_free(d->latest); -} - -static sd_event *event_free(sd_event *e) { - sd_event_source *s; - - assert(e); - - while ((s = e->sources)) { - assert(s->floating); - source_disconnect(s); - sd_event_source_unref(s); - } - - assert(e->n_sources == 0); - - if (e->default_event_ptr) - *(e->default_event_ptr) = NULL; - - safe_close(e->epoll_fd); - safe_close(e->watchdog_fd); - - free_clock_data(&e->realtime); - free_clock_data(&e->boottime); - free_clock_data(&e->monotonic); - free_clock_data(&e->realtime_alarm); - free_clock_data(&e->boottime_alarm); - - prioq_free(e->pending); - prioq_free(e->prepare); - prioq_free(e->exit); - - free(e->signal_sources); - hashmap_free(e->signal_data); - - hashmap_free(e->inotify_data); - - hashmap_free(e->child_sources); - set_free(e->post_sources); - - free(e->event_queue); - - return mfree(e); -} - -_public_ int sd_event_new(sd_event** ret) { - sd_event *e; - int r; - - assert_return(ret, -EINVAL); - - e = new(sd_event, 1); - if (!e) - return -ENOMEM; - - *e = (sd_event) { - .n_ref = 1, - .epoll_fd = -1, - .watchdog_fd = -1, - .realtime.wakeup = WAKEUP_CLOCK_DATA, - .realtime.fd = -1, - .realtime.next = USEC_INFINITY, - .boottime.wakeup = WAKEUP_CLOCK_DATA, - .boottime.fd = -1, - .boottime.next = USEC_INFINITY, - .monotonic.wakeup = WAKEUP_CLOCK_DATA, - .monotonic.fd = -1, - .monotonic.next = USEC_INFINITY, - .realtime_alarm.wakeup = WAKEUP_CLOCK_DATA, - .realtime_alarm.fd = -1, - .realtime_alarm.next = USEC_INFINITY, - .boottime_alarm.wakeup = WAKEUP_CLOCK_DATA, - .boottime_alarm.fd = -1, - .boottime_alarm.next = USEC_INFINITY, - .perturb = USEC_INFINITY, - .original_pid = getpid_cached(), - }; - - r = prioq_ensure_allocated(&e->pending, pending_prioq_compare); - if (r < 0) - goto fail; - - e->epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (e->epoll_fd < 0) { - r = -errno; - goto fail; - } - - e->epoll_fd = fd_move_above_stdio(e->epoll_fd); - - if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) { - log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s."); - e->profile_delays = true; - } - - *ret = e; - return 0; - -fail: - event_free(e); - return r; -} - -DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free); - -_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) { - if (s) - (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); - return sd_event_source_unref(s); -} - -static bool event_pid_changed(sd_event *e) { - assert(e); - - /* We don't support people creating an event loop and keeping - * it around over a fork(). Let's complain. */ - - return e->original_pid != getpid_cached(); -} - -static void source_io_unregister(sd_event_source *s) { - assert(s); - assert(s->type == SOURCE_IO); - - if (event_pid_changed(s->event)) - return; - - if (!s->io.registered) - return; - - if (epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL) < 0) - log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll, ignoring: %m", - strna(s->description), event_source_type_to_string(s->type)); - - s->io.registered = false; -} - -static int source_io_register( - sd_event_source *s, - int enabled, - uint32_t events) { - - assert(s); - assert(s->type == SOURCE_IO); - assert(enabled != SD_EVENT_OFF); - - struct epoll_event ev = { - .events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0), - .data.ptr = s, - }; - - if (epoll_ctl(s->event->epoll_fd, - s->io.registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, - s->io.fd, &ev) < 0) - return -errno; - - s->io.registered = true; - - return 0; -} - -static void source_child_pidfd_unregister(sd_event_source *s) { - assert(s); - assert(s->type == SOURCE_CHILD); - - if (event_pid_changed(s->event)) - return; - - if (!s->child.registered) - return; - - if (EVENT_SOURCE_WATCH_PIDFD(s)) - if (epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->child.pidfd, NULL) < 0) - log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll, ignoring: %m", - strna(s->description), event_source_type_to_string(s->type)); - - s->child.registered = false; -} - -static int source_child_pidfd_register(sd_event_source *s, int enabled) { - assert(s); - assert(s->type == SOURCE_CHILD); - assert(enabled != SD_EVENT_OFF); - - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - struct epoll_event ev = { - .events = EPOLLIN | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0), - .data.ptr = s, - }; - - if (epoll_ctl(s->event->epoll_fd, - s->child.registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, - s->child.pidfd, &ev) < 0) - return -errno; - } - - s->child.registered = true; - return 0; -} - -static clockid_t event_source_type_to_clock(EventSourceType t) { - - switch (t) { - - case SOURCE_TIME_REALTIME: - return CLOCK_REALTIME; - - case SOURCE_TIME_BOOTTIME: - return CLOCK_BOOTTIME; - - case SOURCE_TIME_MONOTONIC: - return CLOCK_MONOTONIC; - - case SOURCE_TIME_REALTIME_ALARM: - return CLOCK_REALTIME_ALARM; - - case SOURCE_TIME_BOOTTIME_ALARM: - return CLOCK_BOOTTIME_ALARM; - - default: - return (clockid_t) -1; - } -} - -static EventSourceType clock_to_event_source_type(clockid_t clock) { - - switch (clock) { - - case CLOCK_REALTIME: - return SOURCE_TIME_REALTIME; - - case CLOCK_BOOTTIME: - return SOURCE_TIME_BOOTTIME; - - case CLOCK_MONOTONIC: - return SOURCE_TIME_MONOTONIC; - - case CLOCK_REALTIME_ALARM: - return SOURCE_TIME_REALTIME_ALARM; - - case CLOCK_BOOTTIME_ALARM: - return SOURCE_TIME_BOOTTIME_ALARM; - - default: - return _SOURCE_EVENT_SOURCE_TYPE_INVALID; - } -} - -static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) { - assert(e); - - switch (t) { - - case SOURCE_TIME_REALTIME: - return &e->realtime; - - case SOURCE_TIME_BOOTTIME: - return &e->boottime; - - case SOURCE_TIME_MONOTONIC: - return &e->monotonic; - - case SOURCE_TIME_REALTIME_ALARM: - return &e->realtime_alarm; - - case SOURCE_TIME_BOOTTIME_ALARM: - return &e->boottime_alarm; - - default: - return NULL; - } -} - -static void event_free_signal_data(sd_event *e, struct signal_data *d) { - assert(e); - - if (!d) - return; - - hashmap_remove(e->signal_data, &d->priority); - safe_close(d->fd); - free(d); -} - -static int event_make_signal_data( - sd_event *e, - int sig, - struct signal_data **ret) { - - struct signal_data *d; - bool added = false; - sigset_t ss_copy; - int64_t priority; - int r; - - assert(e); - - if (event_pid_changed(e)) - return -ECHILD; - - if (e->signal_sources && e->signal_sources[sig]) - priority = e->signal_sources[sig]->priority; - else - priority = SD_EVENT_PRIORITY_NORMAL; - - d = hashmap_get(e->signal_data, &priority); - if (d) { - if (sigismember(&d->sigset, sig) > 0) { - if (ret) - *ret = d; - return 0; - } - } else { - r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops); - if (r < 0) - return r; - - d = new(struct signal_data, 1); - if (!d) - return -ENOMEM; - - *d = (struct signal_data) { - .wakeup = WAKEUP_SIGNAL_DATA, - .fd = -1, - .priority = priority, - }; - - r = hashmap_put(e->signal_data, &d->priority, d); - if (r < 0) { - free(d); - return r; - } - - added = true; - } - - ss_copy = d->sigset; - assert_se(sigaddset(&ss_copy, sig) >= 0); - - r = signalfd(d->fd, &ss_copy, SFD_NONBLOCK|SFD_CLOEXEC); - if (r < 0) { - r = -errno; - goto fail; - } - - d->sigset = ss_copy; - - if (d->fd >= 0) { - if (ret) - *ret = d; - return 0; - } - - d->fd = fd_move_above_stdio(r); - - struct epoll_event ev = { - .events = EPOLLIN, - .data.ptr = d, - }; - - if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) { - r = -errno; - goto fail; - } - - if (ret) - *ret = d; - - return 0; - -fail: - if (added) - event_free_signal_data(e, d); - - return r; -} - -static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig) { - assert(e); - assert(d); - - /* Turns off the specified signal in the signal data - * object. If the signal mask of the object becomes empty that - * way removes it. */ - - if (sigismember(&d->sigset, sig) == 0) - return; - - assert_se(sigdelset(&d->sigset, sig) >= 0); - - if (sigisemptyset(&d->sigset)) { - /* If all the mask is all-zero we can get rid of the structure */ - event_free_signal_data(e, d); - return; - } - - assert(d->fd >= 0); - - if (signalfd(d->fd, &d->sigset, SFD_NONBLOCK|SFD_CLOEXEC) < 0) - log_debug_errno(errno, "Failed to unset signal bit, ignoring: %m"); -} - -static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) { - struct signal_data *d; - static const int64_t zero_priority = 0; - - assert(e); - - /* Rechecks if the specified signal is still something we are interested in. If not, we'll unmask it, - * and possibly drop the signalfd for it. */ - - if (sig == SIGCHLD && - e->n_online_child_sources > 0) - return; - - if (e->signal_sources && - e->signal_sources[sig] && - event_source_is_online(e->signal_sources[sig])) - return; - - /* - * The specified signal might be enabled in three different queues: - * - * 1) the one that belongs to the priority passed (if it is non-NULL) - * 2) the one that belongs to the priority of the event source of the signal (if there is one) - * 3) the 0 priority (to cover the SIGCHLD case) - * - * Hence, let's remove it from all three here. - */ - - if (priority) { - d = hashmap_get(e->signal_data, priority); - if (d) - event_unmask_signal_data(e, d, sig); - } - - if (e->signal_sources && e->signal_sources[sig]) { - d = hashmap_get(e->signal_data, &e->signal_sources[sig]->priority); - if (d) - event_unmask_signal_data(e, d, sig); - } - - d = hashmap_get(e->signal_data, &zero_priority); - if (d) - event_unmask_signal_data(e, d, sig); -} - -static void event_source_pp_prioq_reshuffle(sd_event_source *s) { - assert(s); - - /* Reshuffles the pending + prepare prioqs. Called whenever the dispatch order changes, i.e. when - * they are enabled/disabled or marked pending and such. */ - - if (s->pending) - prioq_reshuffle(s->event->pending, s, &s->pending_index); - - if (s->prepare) - prioq_reshuffle(s->event->prepare, s, &s->prepare_index); -} - -static void event_source_time_prioq_reshuffle(sd_event_source *s) { - struct clock_data *d; - - assert(s); - - /* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy, - * pending, enable state. Makes sure the two prioq's are ordered properly again. */ - - if (s->ratelimited) - d = &s->event->monotonic; - else { - assert(EVENT_SOURCE_IS_TIME(s->type)); - assert_se(d = event_get_clock_data(s->event, s->type)); - } - - prioq_reshuffle(d->earliest, s, &s->earliest_index); - prioq_reshuffle(d->latest, s, &s->latest_index); - d->needs_rearm = true; -} - -static void event_source_time_prioq_remove( - sd_event_source *s, - struct clock_data *d) { - - assert(s); - assert(d); - - prioq_remove(d->earliest, s, &s->earliest_index); - prioq_remove(d->latest, s, &s->latest_index); - s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; - d->needs_rearm = true; -} - -static void source_disconnect(sd_event_source *s) { - sd_event *event; - - assert(s); - - if (!s->event) - return; - - assert(s->event->n_sources > 0); - - switch (s->type) { - - case SOURCE_IO: - if (s->io.fd >= 0) - source_io_unregister(s); - - break; - - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: - /* Only remove this event source from the time event source here if it is not ratelimited. If - * it is ratelimited, we'll remove it below, separately. Why? Because the clock used might - * differ: ratelimiting always uses CLOCK_MONOTONIC, but timer events might use any clock */ - - if (!s->ratelimited) { - struct clock_data *d; - assert_se(d = event_get_clock_data(s->event, s->type)); - event_source_time_prioq_remove(s, d); - } - - break; - - case SOURCE_SIGNAL: - if (s->signal.sig > 0) { - - if (s->event->signal_sources) - s->event->signal_sources[s->signal.sig] = NULL; - - event_gc_signal_data(s->event, &s->priority, s->signal.sig); - } - - break; - - case SOURCE_CHILD: - if (s->child.pid > 0) { - if (event_source_is_online(s)) { - assert(s->event->n_online_child_sources > 0); - s->event->n_online_child_sources--; - } - - (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); - } - - if (EVENT_SOURCE_WATCH_PIDFD(s)) - source_child_pidfd_unregister(s); - else - event_gc_signal_data(s->event, &s->priority, SIGCHLD); - - break; - - case SOURCE_DEFER: - /* nothing */ - break; - - case SOURCE_POST: - set_remove(s->event->post_sources, s); - break; - - case SOURCE_EXIT: - prioq_remove(s->event->exit, s, &s->exit.prioq_index); - break; - - case SOURCE_INOTIFY: { - struct inode_data *inode_data; - - inode_data = s->inotify.inode_data; - if (inode_data) { - struct inotify_data *inotify_data; - assert_se(inotify_data = inode_data->inotify_data); - - /* Detach this event source from the inode object */ - LIST_REMOVE(inotify.by_inode_data, inode_data->event_sources, s); - s->inotify.inode_data = NULL; - - if (s->pending) { - assert(inotify_data->n_pending > 0); - inotify_data->n_pending--; - } - - /* Note that we don't reduce the inotify mask for the watch descriptor here if the inode is - * continued to being watched. That's because inotify doesn't really have an API for that: we - * can only change watch masks with access to the original inode either by fd or by path. But - * paths aren't stable, and keeping an O_PATH fd open all the time would mean wasting an fd - * continuously and keeping the mount busy which we can't really do. We could reconstruct the - * original inode from /proc/self/fdinfo/$INOTIFY_FD (as all watch descriptors are listed - * there), but given the need for open_by_handle_at() which is privileged and not universally - * available this would be quite an incomplete solution. Hence we go the other way, leave the - * mask set, even if it is not minimized now, and ignore all events we aren't interested in - * anymore after reception. Yes, this sucks, but … Linux … */ - - /* Maybe release the inode data (and its inotify) */ - event_gc_inode_data(s->event, inode_data); - } - - break; - } - - default: - assert_not_reached("Wut? I shouldn't exist."); - } - - if (s->pending) - prioq_remove(s->event->pending, s, &s->pending_index); - - if (s->prepare) - prioq_remove(s->event->prepare, s, &s->prepare_index); - - if (s->ratelimited) - event_source_time_prioq_remove(s, &s->event->monotonic); - - event = TAKE_PTR(s->event); - LIST_REMOVE(sources, event->sources, s); - event->n_sources--; - - /* Note that we don't invalidate the type here, since we still need it in order to close the fd or - * pidfd associated with this event source, which we'll do only on source_free(). */ - - if (!s->floating) - sd_event_unref(event); -} - -static void source_free(sd_event_source *s) { - assert(s); - - source_disconnect(s); - - if (s->type == SOURCE_IO && s->io.owned) - s->io.fd = safe_close(s->io.fd); - - if (s->type == SOURCE_CHILD) { - /* Eventually the kernel will do this automatically for us, but for now let's emulate this (unreliably) in userspace. */ - - if (s->child.process_owned) { - - if (!s->child.exited) { - bool sent = false; - - if (s->child.pidfd >= 0) { - if (pidfd_send_signal(s->child.pidfd, SIGKILL, NULL, 0) < 0) { - if (errno == ESRCH) /* Already dead */ - sent = true; - else if (!ERRNO_IS_NOT_SUPPORTED(errno)) - log_debug_errno(errno, "Failed to kill process " PID_FMT " via pidfd_send_signal(), re-trying via kill(): %m", - s->child.pid); - } else - sent = true; - } - - if (!sent) - if (kill(s->child.pid, SIGKILL) < 0) - if (errno != ESRCH) /* Already dead */ - log_debug_errno(errno, "Failed to kill process " PID_FMT " via kill(), ignoring: %m", - s->child.pid); - } - - if (!s->child.waited) { - siginfo_t si = {}; - - /* Reap the child if we can */ - (void) waitid(P_PID, s->child.pid, &si, WEXITED); - } - } - - if (s->child.pidfd_owned) - s->child.pidfd = safe_close(s->child.pidfd); - } - - if (s->destroy_callback) - s->destroy_callback(s->userdata); - - free(s->description); - free(s); -} -DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, source_free); - -static int source_set_pending(sd_event_source *s, bool b) { - int r; - - assert(s); - assert(s->type != SOURCE_EXIT); - - if (s->pending == b) - return 0; - - s->pending = b; - - if (b) { - s->pending_iteration = s->event->iteration; - - r = prioq_put(s->event->pending, s, &s->pending_index); - if (r < 0) { - s->pending = false; - return r; - } - } else - assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); - - if (EVENT_SOURCE_IS_TIME(s->type)) - event_source_time_prioq_reshuffle(s); - - if (s->type == SOURCE_SIGNAL && !b) { - struct signal_data *d; - - d = hashmap_get(s->event->signal_data, &s->priority); - if (d && d->current == s) - d->current = NULL; - } - - if (s->type == SOURCE_INOTIFY) { - - assert(s->inotify.inode_data); - assert(s->inotify.inode_data->inotify_data); - - if (b) - s->inotify.inode_data->inotify_data->n_pending ++; - else { - assert(s->inotify.inode_data->inotify_data->n_pending > 0); - s->inotify.inode_data->inotify_data->n_pending --; - } - } - - return 0; -} - -static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { - sd_event_source *s; - - assert(e); - - s = new(sd_event_source, 1); - if (!s) - return NULL; - - *s = (struct sd_event_source) { - .n_ref = 1, - .event = e, - .floating = floating, - .type = type, - .pending_index = PRIOQ_IDX_NULL, - .prepare_index = PRIOQ_IDX_NULL, - }; - - if (!floating) - sd_event_ref(e); - - LIST_PREPEND(sources, e->sources, s); - e->n_sources++; - - return s; -} - -static int io_exit_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - assert(s); - - return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); -} - -_public_ int sd_event_add_io( - sd_event *e, - sd_event_source **ret, - int fd, - uint32_t events, - sd_event_io_handler_t callback, - void *userdata) { - - _cleanup_(source_freep) sd_event_source *s = NULL; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(fd >= 0, -EBADF); - assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = io_exit_callback; - - s = source_new(e, !ret, SOURCE_IO); - if (!s) - return -ENOMEM; - - s->wakeup = WAKEUP_EVENT_SOURCE; - s->io.fd = fd; - s->io.events = events; - s->io.callback = callback; - s->userdata = userdata; - s->enabled = SD_EVENT_ON; - - r = source_io_register(s, s->enabled, events); - if (r < 0) - return r; - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -static void initialize_perturb(sd_event *e) { - sd_id128_t bootid = {}; - - /* When we sleep for longer, we try to realign the wakeup to - the same time within each minute/second/250ms, so that - events all across the system can be coalesced into a single - CPU wakeup. However, let's take some system-specific - randomness for this value, so that in a network of systems - with synced clocks timer events are distributed a - bit. Here, we calculate a perturbation usec offset from the - boot ID. */ - - if (_likely_(e->perturb != USEC_INFINITY)) - return; - - if (sd_id128_get_boot(&bootid) >= 0) - e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE; -} - -static int event_setup_timer_fd( - sd_event *e, - struct clock_data *d, - clockid_t clock) { - - assert(e); - assert(d); - - if (_likely_(d->fd >= 0)) - return 0; - - _cleanup_close_ int fd = -1; - - fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC); - if (fd < 0) - return -errno; - - fd = fd_move_above_stdio(fd); - - struct epoll_event ev = { - .events = EPOLLIN, - .data.ptr = d, - }; - - if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) - return -errno; - - d->fd = TAKE_FD(fd); - return 0; -} - -static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) { - assert(s); - - return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); -} - -static int setup_clock_data(sd_event *e, struct clock_data *d, clockid_t clock) { - int r; - - assert(d); - - if (d->fd < 0) { - r = event_setup_timer_fd(e, d, clock); - if (r < 0) - return r; - } - - r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); - if (r < 0) - return r; - - r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); - if (r < 0) - return r; - - return 0; -} - -static int event_source_time_prioq_put( - sd_event_source *s, - struct clock_data *d) { - - int r; - - assert(s); - assert(d); - - r = prioq_put(d->earliest, s, &s->earliest_index); - if (r < 0) - return r; - - r = prioq_put(d->latest, s, &s->latest_index); - if (r < 0) { - assert_se(prioq_remove(d->earliest, s, &s->earliest_index) > 0); - s->earliest_index = PRIOQ_IDX_NULL; - return r; - } - - d->needs_rearm = true; - return 0; -} - -_public_ int sd_event_add_time( - sd_event *e, - sd_event_source **ret, - clockid_t clock, - uint64_t usec, - uint64_t accuracy, - sd_event_time_handler_t callback, - void *userdata) { - - EventSourceType type; - _cleanup_(source_freep) sd_event_source *s = NULL; - struct clock_data *d; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(accuracy != (uint64_t) -1, -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */ - return -EOPNOTSUPP; - - type = clock_to_event_source_type(clock); /* checks whether sd-event supports this clock */ - if (type < 0) - return -EOPNOTSUPP; - - if (!callback) - callback = time_exit_callback; - - assert_se(d = event_get_clock_data(e, type)); - - r = setup_clock_data(e, d, clock); - if (r < 0) - return r; - - s = source_new(e, !ret, type); - if (!s) - return -ENOMEM; - - s->time.next = usec; - s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; - s->time.callback = callback; - s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; - s->userdata = userdata; - s->enabled = SD_EVENT_ONESHOT; - - r = event_source_time_prioq_put(s, d); - if (r < 0) - return r; - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -#if 0 /* NM_IGNORED */ -_public_ int sd_event_add_time_relative( - sd_event *e, - sd_event_source **ret, - clockid_t clock, - uint64_t usec, - uint64_t accuracy, - sd_event_time_handler_t callback, - void *userdata) { - - usec_t t; - int r; - - /* Same as sd_event_add_time() but operates relative to the event loop's current point in time, and - * checks for overflow. */ - - r = sd_event_now(e, clock, &t); - if (r < 0) - return r; - - if (usec >= USEC_INFINITY - t) - return -EOVERFLOW; - - return sd_event_add_time(e, ret, clock, t + usec, accuracy, callback, userdata); -} - -static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { - assert(s); - - return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); -} - -_public_ int sd_event_add_signal( - sd_event *e, - sd_event_source **ret, - int sig, - sd_event_signal_handler_t callback, - void *userdata) { - - _cleanup_(source_freep) sd_event_source *s = NULL; - struct signal_data *d; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(SIGNAL_VALID(sig), -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = signal_exit_callback; - - r = signal_is_blocked(sig); - if (r < 0) - return r; - if (r == 0) - return -EBUSY; - - if (!e->signal_sources) { - e->signal_sources = new0(sd_event_source*, _NSIG); - if (!e->signal_sources) - return -ENOMEM; - } else if (e->signal_sources[sig]) - return -EBUSY; - - s = source_new(e, !ret, SOURCE_SIGNAL); - if (!s) - return -ENOMEM; - - s->signal.sig = sig; - s->signal.callback = callback; - s->userdata = userdata; - s->enabled = SD_EVENT_ON; - - e->signal_sources[sig] = s; - - r = event_make_signal_data(e, sig, &d); - if (r < 0) - return r; - - /* Use the signal name as description for the event source by default */ - (void) sd_event_source_set_description(s, signal_to_string(sig)); - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *userdata) { - assert(s); - - return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); -} - -static bool shall_use_pidfd(void) { - /* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */ - return getenv_bool_secure("SYSTEMD_PIDFD") != 0; -} - -_public_ int sd_event_add_child( - sd_event *e, - sd_event_source **ret, - pid_t pid, - int options, - sd_event_child_handler_t callback, - void *userdata) { - - _cleanup_(source_freep) sd_event_source *s = NULL; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(pid > 1, -EINVAL); - assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); - assert_return(options != 0, -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = child_exit_callback; - - if (e->n_online_child_sources == 0) { - /* Caller must block SIGCHLD before using us to watch children, even if pidfd is available, - * for compatibility with pre-pidfd and because we don't want the reap the child processes - * ourselves, i.e. call waitid(), and don't want Linux' default internal logic for that to - * take effect. - * - * (As an optimization we only do this check on the first child event source created.) */ - r = signal_is_blocked(SIGCHLD); - if (r < 0) - return r; - if (r == 0) - return -EBUSY; - } - - r = hashmap_ensure_allocated(&e->child_sources, NULL); - if (r < 0) - return r; - - if (hashmap_contains(e->child_sources, PID_TO_PTR(pid))) - return -EBUSY; - - s = source_new(e, !ret, SOURCE_CHILD); - if (!s) - return -ENOMEM; - - s->wakeup = WAKEUP_EVENT_SOURCE; - s->child.pid = pid; - s->child.options = options; - s->child.callback = callback; - s->userdata = userdata; - s->enabled = SD_EVENT_ONESHOT; - - /* We always take a pidfd here if we can, even if we wait for anything else than WEXITED, so that we - * pin the PID, and make regular waitid() handling race-free. */ - - if (shall_use_pidfd()) { - s->child.pidfd = pidfd_open(s->child.pid, 0); - if (s->child.pidfd < 0) { - /* Propagate errors unless the syscall is not supported or blocked */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) - return -errno; - } else - s->child.pidfd_owned = true; /* If we allocate the pidfd we own it by default */ - } else - s->child.pidfd = -1; - - r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); - if (r < 0) - return r; - - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - /* We have a pidfd and we only want to watch for exit */ - r = source_child_pidfd_register(s, s->enabled); - if (r < 0) - return r; - - } else { - /* We have no pidfd or we shall wait for some other event than WEXITED */ - r = event_make_signal_data(e, SIGCHLD, NULL); - if (r < 0) - return r; - - e->need_process_child = true; - } - - e->n_online_child_sources++; - - if (ret) - *ret = s; - TAKE_PTR(s); - return 0; -} - -_public_ int sd_event_add_child_pidfd( - sd_event *e, - sd_event_source **ret, - int pidfd, - int options, - sd_event_child_handler_t callback, - void *userdata) { - - - _cleanup_(source_freep) sd_event_source *s = NULL; - pid_t pid; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(pidfd >= 0, -EBADF); - assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); - assert_return(options != 0, -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = child_exit_callback; - - if (e->n_online_child_sources == 0) { - r = signal_is_blocked(SIGCHLD); - if (r < 0) - return r; - if (r == 0) - return -EBUSY; - } - - r = hashmap_ensure_allocated(&e->child_sources, NULL); - if (r < 0) - return r; - - r = pidfd_get_pid(pidfd, &pid); - if (r < 0) - return r; - - if (hashmap_contains(e->child_sources, PID_TO_PTR(pid))) - return -EBUSY; - - s = source_new(e, !ret, SOURCE_CHILD); - if (!s) - return -ENOMEM; - - s->wakeup = WAKEUP_EVENT_SOURCE; - s->child.pidfd = pidfd; - s->child.pid = pid; - s->child.options = options; - s->child.callback = callback; - s->child.pidfd_owned = false; /* If we got the pidfd passed in we don't own it by default (similar to the IO fd case) */ - s->userdata = userdata; - s->enabled = SD_EVENT_ONESHOT; - - r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); - if (r < 0) - return r; - - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - /* We only want to watch for WEXITED */ - r = source_child_pidfd_register(s, s->enabled); - if (r < 0) - return r; - } else { - /* We shall wait for some other event than WEXITED */ - r = event_make_signal_data(e, SIGCHLD, NULL); - if (r < 0) - return r; - - e->need_process_child = true; - } - - e->n_online_child_sources++; - - if (ret) - *ret = s; - TAKE_PTR(s); - return 0; -} -#endif /* NM_IGNORED */ - -static int generic_exit_callback(sd_event_source *s, void *userdata) { - assert(s); - - return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); -} - -_public_ int sd_event_add_defer( - sd_event *e, - sd_event_source **ret, - sd_event_handler_t callback, - void *userdata) { - - _cleanup_(source_freep) sd_event_source *s = NULL; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = generic_exit_callback; - - s = source_new(e, !ret, SOURCE_DEFER); - if (!s) - return -ENOMEM; - - s->defer.callback = callback; - s->userdata = userdata; - s->enabled = SD_EVENT_ONESHOT; - - r = source_set_pending(s, true); - if (r < 0) - return r; - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -_public_ int sd_event_add_post( - sd_event *e, - sd_event_source **ret, - sd_event_handler_t callback, - void *userdata) { - - _cleanup_(source_freep) sd_event_source *s = NULL; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = generic_exit_callback; - - s = source_new(e, !ret, SOURCE_POST); - if (!s) - return -ENOMEM; - - s->post.callback = callback; - s->userdata = userdata; - s->enabled = SD_EVENT_ON; - - r = set_ensure_put(&e->post_sources, NULL, s); - if (r < 0) - return r; - assert(r > 0); - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -_public_ int sd_event_add_exit( - sd_event *e, - sd_event_source **ret, - sd_event_handler_t callback, - void *userdata) { - - _cleanup_(source_freep) sd_event_source *s = NULL; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(callback, -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - r = prioq_ensure_allocated(&e->exit, exit_prioq_compare); - if (r < 0) - return r; - - s = source_new(e, !ret, SOURCE_EXIT); - if (!s) - return -ENOMEM; - - s->exit.callback = callback; - s->userdata = userdata; - s->exit.prioq_index = PRIOQ_IDX_NULL; - s->enabled = SD_EVENT_ONESHOT; - - r = prioq_put(s->event->exit, s, &s->exit.prioq_index); - if (r < 0) - return r; - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -static void event_free_inotify_data(sd_event *e, struct inotify_data *d) { - assert(e); - - if (!d) - return; - - assert(hashmap_isempty(d->inodes)); - assert(hashmap_isempty(d->wd)); - - if (d->buffer_filled > 0) - LIST_REMOVE(buffered, e->inotify_data_buffered, d); - - hashmap_free(d->inodes); - hashmap_free(d->wd); - - assert_se(hashmap_remove(e->inotify_data, &d->priority) == d); - - if (d->fd >= 0) { - if (epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0) - log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m"); - - safe_close(d->fd); - } - free(d); -} - -static int event_make_inotify_data( - sd_event *e, - int64_t priority, - struct inotify_data **ret) { - - _cleanup_close_ int fd = -1; - struct inotify_data *d; - int r; - - assert(e); - - d = hashmap_get(e->inotify_data, &priority); - if (d) { - if (ret) - *ret = d; - return 0; - } - - fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC); - if (fd < 0) - return -errno; - - fd = fd_move_above_stdio(fd); - - r = hashmap_ensure_allocated(&e->inotify_data, &uint64_hash_ops); - if (r < 0) - return r; - - d = new(struct inotify_data, 1); - if (!d) - return -ENOMEM; - - *d = (struct inotify_data) { - .wakeup = WAKEUP_INOTIFY_DATA, - .fd = TAKE_FD(fd), - .priority = priority, - }; - - r = hashmap_put(e->inotify_data, &d->priority, d); - if (r < 0) { - d->fd = safe_close(d->fd); - free(d); - return r; - } - - struct epoll_event ev = { - .events = EPOLLIN, - .data.ptr = d, - }; - - if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) { - r = -errno; - d->fd = safe_close(d->fd); /* let's close this ourselves, as event_free_inotify_data() would otherwise - * remove the fd from the epoll first, which we don't want as we couldn't - * add it in the first place. */ - event_free_inotify_data(e, d); - return r; - } - - if (ret) - *ret = d; - - return 1; -} - -static int inode_data_compare(const struct inode_data *x, const struct inode_data *y) { - int r; - - assert(x); - assert(y); - - r = CMP(x->dev, y->dev); - if (r != 0) - return r; - - return CMP(x->ino, y->ino); -} - -static void inode_data_hash_func(const struct inode_data *d, struct siphash *state) { - assert(d); - - siphash24_compress(&d->dev, sizeof(d->dev), state); - siphash24_compress(&d->ino, sizeof(d->ino), state); -} - -DEFINE_PRIVATE_HASH_OPS(inode_data_hash_ops, struct inode_data, inode_data_hash_func, inode_data_compare); - -static void event_free_inode_data( - sd_event *e, - struct inode_data *d) { - - assert(e); - - if (!d) - return; - - assert(!d->event_sources); - - if (d->fd >= 0) { - LIST_REMOVE(to_close, e->inode_data_to_close, d); - safe_close(d->fd); - } - - if (d->inotify_data) { - - if (d->wd >= 0) { - if (d->inotify_data->fd >= 0) { - /* So here's a problem. At the time this runs the watch descriptor might already be - * invalidated, because an IN_IGNORED event might be queued right the moment we enter - * the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very - * likely case to happen. */ - - if (inotify_rm_watch(d->inotify_data->fd, d->wd) < 0 && errno != EINVAL) - log_debug_errno(errno, "Failed to remove watch descriptor %i from inotify, ignoring: %m", d->wd); - } - - assert_se(hashmap_remove(d->inotify_data->wd, INT_TO_PTR(d->wd)) == d); - } - - assert_se(hashmap_remove(d->inotify_data->inodes, d) == d); - } - - free(d); -} - -static void event_gc_inode_data( - sd_event *e, - struct inode_data *d) { - - struct inotify_data *inotify_data; - - assert(e); - - if (!d) - return; - - if (d->event_sources) - return; - - inotify_data = d->inotify_data; - event_free_inode_data(e, d); - - if (inotify_data && hashmap_isempty(inotify_data->inodes)) - event_free_inotify_data(e, inotify_data); -} - -static int event_make_inode_data( - sd_event *e, - struct inotify_data *inotify_data, - dev_t dev, - ino_t ino, - struct inode_data **ret) { - - struct inode_data *d, key; - int r; - - assert(e); - assert(inotify_data); - - key = (struct inode_data) { - .ino = ino, - .dev = dev, - }; - - d = hashmap_get(inotify_data->inodes, &key); - if (d) { - if (ret) - *ret = d; - - return 0; - } - - r = hashmap_ensure_allocated(&inotify_data->inodes, &inode_data_hash_ops); - if (r < 0) - return r; - - d = new(struct inode_data, 1); - if (!d) - return -ENOMEM; - - *d = (struct inode_data) { - .dev = dev, - .ino = ino, - .wd = -1, - .fd = -1, - .inotify_data = inotify_data, - }; - - r = hashmap_put(inotify_data->inodes, d, d); - if (r < 0) { - free(d); - return r; - } - - if (ret) - *ret = d; - - return 1; -} - -static uint32_t inode_data_determine_mask(struct inode_data *d) { - bool excl_unlink = true; - uint32_t combined = 0; - sd_event_source *s; - - assert(d); - - /* Combines the watch masks of all event sources watching this inode. We generally just OR them together, but - * the IN_EXCL_UNLINK flag is ANDed instead. - * - * Note that we add all sources to the mask here, regardless whether enabled, disabled or oneshot. That's - * because we cannot change the mask anymore after the event source was created once, since the kernel has no - * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and suppress - * events we don't care for client-side. */ - - LIST_FOREACH(inotify.by_inode_data, s, d->event_sources) { - - if ((s->inotify.mask & IN_EXCL_UNLINK) == 0) - excl_unlink = false; - - combined |= s->inotify.mask; - } - - return (combined & ~(IN_ONESHOT|IN_DONT_FOLLOW|IN_ONLYDIR|IN_EXCL_UNLINK)) | (excl_unlink ? IN_EXCL_UNLINK : 0); -} - -static int inode_data_realize_watch(sd_event *e, struct inode_data *d) { - uint32_t combined_mask; - int wd, r; - - assert(d); - assert(d->fd >= 0); - - combined_mask = inode_data_determine_mask(d); - - if (d->wd >= 0 && combined_mask == d->combined_mask) - return 0; - - r = hashmap_ensure_allocated(&d->inotify_data->wd, NULL); - if (r < 0) - return r; - - wd = inotify_add_watch_fd(d->inotify_data->fd, d->fd, combined_mask); - if (wd < 0) - return -errno; - - if (d->wd < 0) { - r = hashmap_put(d->inotify_data->wd, INT_TO_PTR(wd), d); - if (r < 0) { - (void) inotify_rm_watch(d->inotify_data->fd, wd); - return r; - } - - d->wd = wd; - - } else if (d->wd != wd) { - - log_debug("Weird, the watch descriptor we already knew for this inode changed?"); - (void) inotify_rm_watch(d->fd, wd); - return -EINVAL; - } - - d->combined_mask = combined_mask; - return 1; -} - -static int inotify_exit_callback(sd_event_source *s, const struct inotify_event *event, void *userdata) { - assert(s); - - return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); -} - -_public_ int sd_event_add_inotify( - sd_event *e, - sd_event_source **ret, - const char *path, - uint32_t mask, - sd_event_inotify_handler_t callback, - void *userdata) { - - struct inotify_data *inotify_data = NULL; - struct inode_data *inode_data = NULL; - _cleanup_close_ int fd = -1; - _cleanup_(source_freep) sd_event_source *s = NULL; - struct stat st; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(path, -EINVAL); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!callback) - callback = inotify_exit_callback; - - /* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge - * masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence - * the user can't use them for us. */ - if (mask & IN_MASK_ADD) - return -EINVAL; - - fd = open(path, O_PATH|O_CLOEXEC| - (mask & IN_ONLYDIR ? O_DIRECTORY : 0)| - (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0)); - if (fd < 0) - return -errno; - - if (fstat(fd, &st) < 0) - return -errno; - - s = source_new(e, !ret, SOURCE_INOTIFY); - if (!s) - return -ENOMEM; - - s->enabled = mask & IN_ONESHOT ? SD_EVENT_ONESHOT : SD_EVENT_ON; - s->inotify.mask = mask; - s->inotify.callback = callback; - s->userdata = userdata; - - /* Allocate an inotify object for this priority, and an inode object within it */ - r = event_make_inotify_data(e, SD_EVENT_PRIORITY_NORMAL, &inotify_data); - if (r < 0) - return r; - - r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data); - if (r < 0) { - event_free_inotify_data(e, inotify_data); - return r; - } - - /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of - * the event source, until then, for which we need the original inode. */ - if (inode_data->fd < 0) { - inode_data->fd = TAKE_FD(fd); - LIST_PREPEND(to_close, e->inode_data_to_close, inode_data); - } - - /* Link our event source to the inode data object */ - LIST_PREPEND(inotify.by_inode_data, inode_data->event_sources, s); - s->inotify.inode_data = inode_data; - - /* Actually realize the watch now */ - r = inode_data_realize_watch(e, inode_data); - if (r < 0) - return r; - - (void) sd_event_source_set_description(s, path); - - if (ret) - *ret = s; - TAKE_PTR(s); - - return 0; -} - -static sd_event_source* event_source_free(sd_event_source *s) { - if (!s) - return NULL; - - /* Here's a special hack: when we are called from a - * dispatch handler we won't free the event source - * immediately, but we will detach the fd from the - * epoll. This way it is safe for the caller to unref - * the event source and immediately close the fd, but - * we still retain a valid event source object after - * the callback. */ - - if (s->dispatching) { - if (s->type == SOURCE_IO) - source_io_unregister(s); - - source_disconnect(s); - } else - source_free(s); - - return NULL; -} - -DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event_source, sd_event_source, event_source_free); - -_public_ int sd_event_source_set_description(sd_event_source *s, const char *description) { - assert_return(s, -EINVAL); - assert_return(!event_pid_changed(s->event), -ECHILD); - - return free_and_strdup(&s->description, description); -} - -_public_ int sd_event_source_get_description(sd_event_source *s, const char **description) { - assert_return(s, -EINVAL); - assert_return(description, -EINVAL); - assert_return(!event_pid_changed(s->event), -ECHILD); - - if (!s->description) - return -ENXIO; - - *description = s->description; - return 0; -} - -_public_ sd_event *sd_event_source_get_event(sd_event_source *s) { - assert_return(s, NULL); - - return s->event; -} - -_public_ int sd_event_source_get_pending(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type != SOURCE_EXIT, -EDOM); - assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(s->event), -ECHILD); - - return s->pending; -} - -_public_ int sd_event_source_get_io_fd(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - return s->io.fd; -} - -_public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { - int r; - - assert_return(s, -EINVAL); - assert_return(fd >= 0, -EBADF); - assert_return(s->type == SOURCE_IO, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - if (s->io.fd == fd) - return 0; - - if (event_source_is_offline(s)) { - s->io.fd = fd; - s->io.registered = false; - } else { - int saved_fd; - - saved_fd = s->io.fd; - assert(s->io.registered); - - s->io.fd = fd; - s->io.registered = false; - - r = source_io_register(s, s->enabled, s->io.events); - if (r < 0) { - s->io.fd = saved_fd; - s->io.registered = true; - return r; - } - - (void) epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL); - } - - return 0; -} - -_public_ int sd_event_source_get_io_fd_own(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - - return s->io.owned; -} - -_public_ int sd_event_source_set_io_fd_own(sd_event_source *s, int own) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - - s->io.owned = own; - return 0; -} - -_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) { - assert_return(s, -EINVAL); - assert_return(events, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *events = s->io.events; - return 0; -} - -_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) { - int r; - - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); - assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(s->event), -ECHILD); - - /* edge-triggered updates are never skipped, so we can reset edges */ - if (s->io.events == events && !(events & EPOLLET)) - return 0; - - r = source_set_pending(s, false); - if (r < 0) - return r; - - if (event_source_is_online(s)) { - r = source_io_register(s, s->enabled, events); - if (r < 0) - return r; - } - - s->io.events = events; - - return 0; -} - -_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) { - assert_return(s, -EINVAL); - assert_return(revents, -EINVAL); - assert_return(s->type == SOURCE_IO, -EDOM); - assert_return(s->pending, -ENODATA); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *revents = s->io.revents; - return 0; -} - -_public_ int sd_event_source_get_signal(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_SIGNAL, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - return s->signal.sig; -} - -_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) { - assert_return(s, -EINVAL); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *priority = s->priority; - return 0; -} - -_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) { - bool rm_inotify = false, rm_inode = false; - struct inotify_data *new_inotify_data = NULL; - struct inode_data *new_inode_data = NULL; - int r; - - assert_return(s, -EINVAL); - assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(s->event), -ECHILD); - - if (s->priority == priority) - return 0; - - if (s->type == SOURCE_INOTIFY) { - struct inode_data *old_inode_data; - - assert(s->inotify.inode_data); - old_inode_data = s->inotify.inode_data; - - /* We need the original fd to change the priority. If we don't have it we can't change the priority, - * anymore. Note that we close any fds when entering the next event loop iteration, i.e. for inotify - * events we allow priority changes only until the first following iteration. */ - if (old_inode_data->fd < 0) - return -EOPNOTSUPP; - - r = event_make_inotify_data(s->event, priority, &new_inotify_data); - if (r < 0) - return r; - rm_inotify = r > 0; - - r = event_make_inode_data(s->event, new_inotify_data, old_inode_data->dev, old_inode_data->ino, &new_inode_data); - if (r < 0) - goto fail; - rm_inode = r > 0; - - if (new_inode_data->fd < 0) { - /* Duplicate the fd for the new inode object if we don't have any yet */ - new_inode_data->fd = fcntl(old_inode_data->fd, F_DUPFD_CLOEXEC, 3); - if (new_inode_data->fd < 0) { - r = -errno; - goto fail; - } - - LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data); - } - - /* Move the event source to the new inode data structure */ - LIST_REMOVE(inotify.by_inode_data, old_inode_data->event_sources, s); - LIST_PREPEND(inotify.by_inode_data, new_inode_data->event_sources, s); - s->inotify.inode_data = new_inode_data; - - /* Now create the new watch */ - r = inode_data_realize_watch(s->event, new_inode_data); - if (r < 0) { - /* Move it back */ - LIST_REMOVE(inotify.by_inode_data, new_inode_data->event_sources, s); - LIST_PREPEND(inotify.by_inode_data, old_inode_data->event_sources, s); - s->inotify.inode_data = old_inode_data; - goto fail; - } - - s->priority = priority; - - event_gc_inode_data(s->event, old_inode_data); - - } else if (s->type == SOURCE_SIGNAL && event_source_is_online(s)) { - struct signal_data *old, *d; - - /* Move us from the signalfd belonging to the old - * priority to the signalfd of the new priority */ - - assert_se(old = hashmap_get(s->event->signal_data, &s->priority)); - - s->priority = priority; - - r = event_make_signal_data(s->event, s->signal.sig, &d); - if (r < 0) { - s->priority = old->priority; - return r; - } - - event_unmask_signal_data(s->event, old, s->signal.sig); - } else - s->priority = priority; - - event_source_pp_prioq_reshuffle(s); - - if (s->type == SOURCE_EXIT) - prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); - - return 0; - -fail: - if (rm_inode) - event_free_inode_data(s->event, new_inode_data); - - if (rm_inotify) - event_free_inotify_data(s->event, new_inotify_data); - - return r; -} - -_public_ int sd_event_source_get_enabled(sd_event_source *s, int *ret) { - assert_return(s, -EINVAL); - assert_return(!event_pid_changed(s->event), -ECHILD); - - if (ret) - *ret = s->enabled; - - return s->enabled != SD_EVENT_OFF; -} - -static int event_source_offline( - sd_event_source *s, - int enabled, - bool ratelimited) { - - bool was_offline; - int r; - - assert(s); - assert(enabled == SD_EVENT_OFF || ratelimited); - - /* Unset the pending flag when this event source is disabled */ - if (s->enabled != SD_EVENT_OFF && - enabled == SD_EVENT_OFF && - !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { - r = source_set_pending(s, false); - if (r < 0) - return r; - } - - was_offline = event_source_is_offline(s); - s->enabled = enabled; - s->ratelimited = ratelimited; - - switch (s->type) { - - case SOURCE_IO: - source_io_unregister(s); - break; - - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: - event_source_time_prioq_reshuffle(s); - break; - - case SOURCE_SIGNAL: - event_gc_signal_data(s->event, &s->priority, s->signal.sig); - break; - - case SOURCE_CHILD: - if (!was_offline) { - assert(s->event->n_online_child_sources > 0); - s->event->n_online_child_sources--; - } - - if (EVENT_SOURCE_WATCH_PIDFD(s)) - source_child_pidfd_unregister(s); - else - event_gc_signal_data(s->event, &s->priority, SIGCHLD); - break; - - case SOURCE_EXIT: - prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); - break; - - case SOURCE_DEFER: - case SOURCE_POST: - case SOURCE_INOTIFY: - break; - - default: - assert_not_reached("Wut? I shouldn't exist."); - } - - return 1; -} - -static int event_source_online( - sd_event_source *s, - int enabled, - bool ratelimited) { - - bool was_online; - int r; - - assert(s); - assert(enabled != SD_EVENT_OFF || !ratelimited); - - /* Unset the pending flag when this event source is enabled */ - if (s->enabled == SD_EVENT_OFF && - enabled != SD_EVENT_OFF && - !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { - r = source_set_pending(s, false); - if (r < 0) - return r; - } - - /* Are we really ready for onlining? */ - if (enabled == SD_EVENT_OFF || ratelimited) { - /* Nope, we are not ready for onlining, then just update the precise state and exit */ - s->enabled = enabled; - s->ratelimited = ratelimited; - return 0; - } - - was_online = event_source_is_online(s); - - switch (s->type) { - case SOURCE_IO: - r = source_io_register(s, enabled, s->io.events); - if (r < 0) - return r; - break; - - case SOURCE_SIGNAL: - r = event_make_signal_data(s->event, s->signal.sig, NULL); - if (r < 0) { - event_gc_signal_data(s->event, &s->priority, s->signal.sig); - return r; - } - - break; - - case SOURCE_CHILD: - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - /* yes, we have pidfd */ - - r = source_child_pidfd_register(s, enabled); - if (r < 0) - return r; - } else { - /* no pidfd, or something other to watch for than WEXITED */ - - r = event_make_signal_data(s->event, SIGCHLD, NULL); - if (r < 0) { - event_gc_signal_data(s->event, &s->priority, SIGCHLD); - return r; - } - } - - if (!was_online) - s->event->n_online_child_sources++; - break; - - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: - case SOURCE_EXIT: - case SOURCE_DEFER: - case SOURCE_POST: - case SOURCE_INOTIFY: - break; - - default: - assert_not_reached("Wut? I shouldn't exist."); - } - - s->enabled = enabled; - s->ratelimited = ratelimited; - - /* Non-failing operations below */ - switch (s->type) { - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: - event_source_time_prioq_reshuffle(s); - break; - - case SOURCE_EXIT: - prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); - break; - - default: - break; - } - - return 1; -} - -_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { - int r; - - assert_return(s, -EINVAL); - assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL); - assert_return(!event_pid_changed(s->event), -ECHILD); - - /* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */ - if (s->event->state == SD_EVENT_FINISHED) - return m == SD_EVENT_OFF ? 0 : -ESTALE; - - if (s->enabled == m) /* No change? */ - return 0; - - if (m == SD_EVENT_OFF) - r = event_source_offline(s, m, s->ratelimited); - else { - if (s->enabled != SD_EVENT_OFF) { - /* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the - * event source is already enabled after all. */ - s->enabled = m; - return 0; - } - - r = event_source_online(s, m, s->ratelimited); - } - if (r < 0) - return r; - - event_source_pp_prioq_reshuffle(s); - return 0; -} - -_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { - assert_return(s, -EINVAL); - assert_return(usec, -EINVAL); - assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *usec = s->time.next; - return 0; -} - -_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { - int r; - - assert_return(s, -EINVAL); - assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); - assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(s->event), -ECHILD); - - r = source_set_pending(s, false); - if (r < 0) - return r; - - s->time.next = usec; - - event_source_time_prioq_reshuffle(s); - return 0; -} - -_public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec) { - usec_t t; - int r; - - assert_return(s, -EINVAL); - assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); - - r = sd_event_now(s->event, event_source_type_to_clock(s->type), &t); - if (r < 0) - return r; - - if (usec >= USEC_INFINITY - t) - return -EOVERFLOW; - - return sd_event_source_set_time(s, t + usec); -} - -_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { - assert_return(s, -EINVAL); - assert_return(usec, -EINVAL); - assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *usec = s->time.accuracy; - return 0; -} - -_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { - int r; - - assert_return(s, -EINVAL); - assert_return(usec != (uint64_t) -1, -EINVAL); - assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); - assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(s->event), -ECHILD); - - r = source_set_pending(s, false); - if (r < 0) - return r; - - if (usec == 0) - usec = DEFAULT_ACCURACY_USEC; - - s->time.accuracy = usec; - - event_source_time_prioq_reshuffle(s); - return 0; -} - -_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) { - assert_return(s, -EINVAL); - assert_return(clock, -EINVAL); - assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *clock = event_source_type_to_clock(s->type); - return 0; -} - -_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) { - assert_return(s, -EINVAL); - assert_return(pid, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *pid = s->child.pid; - return 0; -} - -_public_ int sd_event_source_get_child_pidfd(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - if (s->child.pidfd < 0) - return -EOPNOTSUPP; - - return s->child.pidfd; -} - -_public_ int sd_event_source_send_child_signal(sd_event_source *s, int sig, const siginfo_t *si, unsigned flags) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - assert_return(SIGNAL_VALID(sig), -EINVAL); - - /* If we already have seen indication the process exited refuse sending a signal early. This way we - * can be sure we don't accidentally kill the wrong process on PID reuse when pidfds are not - * available. */ - if (s->child.exited) - return -ESRCH; - - if (s->child.pidfd >= 0) { - siginfo_t copy; - - /* pidfd_send_signal() changes the siginfo_t argument. This is weird, let's hence copy the - * structure here */ - if (si) - copy = *si; - - if (pidfd_send_signal(s->child.pidfd, sig, si ? © : NULL, 0) < 0) { - /* Let's propagate the error only if the system call is not implemented or prohibited */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) - return -errno; - } else - return 0; - } - - /* Flags are only supported for pidfd_send_signal(), not for rt_sigqueueinfo(), hence let's refuse - * this here. */ - if (flags != 0) - return -EOPNOTSUPP; - - if (si) { - /* We use rt_sigqueueinfo() only if siginfo_t is specified. */ - siginfo_t copy = *si; - - if (rt_sigqueueinfo(s->child.pid, sig, ©) < 0) - return -errno; - } else if (kill(s->child.pid, sig) < 0) - return -errno; - - return 0; -} - -_public_ int sd_event_source_get_child_pidfd_own(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - - if (s->child.pidfd < 0) - return -EOPNOTSUPP; - - return s->child.pidfd_owned; -} - -_public_ int sd_event_source_set_child_pidfd_own(sd_event_source *s, int own) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - - if (s->child.pidfd < 0) - return -EOPNOTSUPP; - - s->child.pidfd_owned = own; - return 0; -} - -_public_ int sd_event_source_get_child_process_own(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - - return s->child.process_owned; -} - -_public_ int sd_event_source_set_child_process_own(sd_event_source *s, int own) { - assert_return(s, -EINVAL); - assert_return(s->type == SOURCE_CHILD, -EDOM); - - s->child.process_owned = own; - return 0; -} - -_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) { - assert_return(s, -EINVAL); - assert_return(mask, -EINVAL); - assert_return(s->type == SOURCE_INOTIFY, -EDOM); - assert_return(!event_pid_changed(s->event), -ECHILD); - - *mask = s->inotify.mask; - return 0; -} - -_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) { - int r; - - assert_return(s, -EINVAL); - assert_return(s->type != SOURCE_EXIT, -EDOM); - assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(s->event), -ECHILD); - - if (s->prepare == callback) - return 0; - - if (callback && s->prepare) { - s->prepare = callback; - return 0; - } - - r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare); - if (r < 0) - return r; - - s->prepare = callback; - - if (callback) { - r = prioq_put(s->event->prepare, s, &s->prepare_index); - if (r < 0) - return r; - } else - prioq_remove(s->event->prepare, s, &s->prepare_index); - - return 0; -} - -_public_ void* sd_event_source_get_userdata(sd_event_source *s) { - assert_return(s, NULL); - - return s->userdata; -} - -_public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) { - void *ret; - - assert_return(s, NULL); - - ret = s->userdata; - s->userdata = userdata; - - return ret; -} - -static int event_source_enter_ratelimited(sd_event_source *s) { - int r; - - assert(s); - - /* When an event source becomes ratelimited, we place it in the CLOCK_MONOTONIC priority queue, with - * the end of the rate limit time window, much as if it was a timer event source. */ - - if (s->ratelimited) - return 0; /* Already ratelimited, this is a NOP hence */ - - /* Make sure we can install a CLOCK_MONOTONIC event further down. */ - r = setup_clock_data(s->event, &s->event->monotonic, CLOCK_MONOTONIC); - if (r < 0) - return r; - - /* Timer event sources are already using the earliest/latest queues for the timer scheduling. Let's - * first remove them from the prioq appropriate for their own clock, so that we can use the prioq - * fields of the event source then for adding it to the CLOCK_MONOTONIC prioq instead. */ - if (EVENT_SOURCE_IS_TIME(s->type)) - event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); - - /* Now, let's add the event source to the monotonic clock instead */ - r = event_source_time_prioq_put(s, &s->event->monotonic); - if (r < 0) - goto fail; - - /* And let's take the event source officially offline */ - r = event_source_offline(s, s->enabled, /* ratelimited= */ true); - if (r < 0) { - event_source_time_prioq_remove(s, &s->event->monotonic); - goto fail; - } - - event_source_pp_prioq_reshuffle(s); - - log_debug("Event source %p (%s) entered rate limit state.", s, strna(s->description)); - return 0; - -fail: - /* Reinstall time event sources in the priority queue as before. This shouldn't fail, since the queue - * space for it should already be allocated. */ - if (EVENT_SOURCE_IS_TIME(s->type)) - assert_se(event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)) >= 0); - - return r; -} - -static int event_source_leave_ratelimit(sd_event_source *s) { - int r; - - assert(s); - - if (!s->ratelimited) - return 0; - - /* Let's take the event source out of the monotonic prioq first. */ - event_source_time_prioq_remove(s, &s->event->monotonic); - - /* Let's then add the event source to its native clock prioq again — if this is a timer event source */ - if (EVENT_SOURCE_IS_TIME(s->type)) { - r = event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)); - if (r < 0) - goto fail; - } - - /* Let's try to take it online again. */ - r = event_source_online(s, s->enabled, /* ratelimited= */ false); - if (r < 0) { - /* Do something roughly sensible when this failed: undo the two prioq ops above */ - if (EVENT_SOURCE_IS_TIME(s->type)) - event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); - - goto fail; - } - - event_source_pp_prioq_reshuffle(s); - ratelimit_reset(&s->rate_limit); - - log_debug("Event source %p (%s) left rate limit state.", s, strna(s->description)); - return 0; - -fail: - /* Do something somewhat reasonable when we cannot move an event sources out of ratelimited mode: - * simply put it back in it, maybe we can then process it more successfully next iteration. */ - assert_se(event_source_time_prioq_put(s, &s->event->monotonic) >= 0); - - return r; -} - -static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { - usec_t c; - assert(e); - assert(a <= b); - - if (a <= 0) - return 0; - if (a >= USEC_INFINITY) - return USEC_INFINITY; - - if (b <= a + 1) - return a; - - initialize_perturb(e); - - /* - Find a good time to wake up again between times a and b. We - have two goals here: - - a) We want to wake up as seldom as possible, hence prefer - later times over earlier times. - - b) But if we have to wake up, then let's make sure to - dispatch as much as possible on the entire system. - - We implement this by waking up everywhere at the same time - within any given minute if we can, synchronised via the - perturbation value determined from the boot ID. If we can't, - then we try to find the same spot in every 10s, then 1s and - then 250ms step. Otherwise, we pick the last possible time - to wake up. - */ - - c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb; - if (c >= b) { - if (_unlikely_(c < USEC_PER_MINUTE)) - return b; - - c -= USEC_PER_MINUTE; - } - - if (c >= a) - return c; - - c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10)); - if (c >= b) { - if (_unlikely_(c < USEC_PER_SEC*10)) - return b; - - c -= USEC_PER_SEC*10; - } - - if (c >= a) - return c; - - c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC); - if (c >= b) { - if (_unlikely_(c < USEC_PER_SEC)) - return b; - - c -= USEC_PER_SEC; - } - - if (c >= a) - return c; - - c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250)); - if (c >= b) { - if (_unlikely_(c < USEC_PER_MSEC*250)) - return b; - - c -= USEC_PER_MSEC*250; - } - - if (c >= a) - return c; - - return b; -} - -static int event_arm_timer( - sd_event *e, - struct clock_data *d) { - - struct itimerspec its = {}; - sd_event_source *a, *b; - usec_t t; - - assert(e); - assert(d); - - if (!d->needs_rearm) - return 0; - else - d->needs_rearm = false; - - a = prioq_peek(d->earliest); - if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) { - - if (d->fd < 0) - return 0; - - if (d->next == USEC_INFINITY) - return 0; - - /* disarm */ - if (timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) - return -errno; - - d->next = USEC_INFINITY; - return 0; - } - - b = prioq_peek(d->latest); - assert_se(b && b->enabled != SD_EVENT_OFF); - - t = sleep_between(e, time_event_source_next(a), time_event_source_latest(b)); - if (d->next == t) - return 0; - - assert_se(d->fd >= 0); - - if (t == 0) { - /* We don' want to disarm here, just mean some time looooong ago. */ - its.it_value.tv_sec = 0; - its.it_value.tv_nsec = 1; - } else - timespec_store(&its.it_value, t); - - if (timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) - return -errno; - - d->next = t; - return 0; -} - -static int process_io(sd_event *e, sd_event_source *s, uint32_t revents) { - assert(e); - assert(s); - assert(s->type == SOURCE_IO); - - /* If the event source was already pending, we just OR in the - * new revents, otherwise we reset the value. The ORing is - * necessary to handle EPOLLONESHOT events properly where - * readability might happen independently of writability, and - * we need to keep track of both */ - - if (s->pending) - s->io.revents |= revents; - else - s->io.revents = revents; - - return source_set_pending(s, true); -} - -static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) { - uint64_t x; - ssize_t ss; - - assert(e); - assert(fd >= 0); - - assert_return(events == EPOLLIN, -EIO); - - ss = read(fd, &x, sizeof(x)); - if (ss < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - return -errno; - } - - if (_unlikely_(ss != sizeof(x))) - return -EIO; - - if (next) - *next = USEC_INFINITY; - - return 0; -} - -static int process_timer( - sd_event *e, - usec_t n, - struct clock_data *d) { - - sd_event_source *s; - int r; - - assert(e); - assert(d); - - for (;;) { - s = prioq_peek(d->earliest); - if (!s || time_event_source_next(s) > n) - break; - - if (s->ratelimited) { - /* This is an event sources whose ratelimit window has ended. Let's turn it on - * again. */ - assert(s->ratelimited); - - r = event_source_leave_ratelimit(s); - if (r < 0) - return r; - - continue; - } - - if (s->enabled == SD_EVENT_OFF || s->pending) - break; - - r = source_set_pending(s, true); - if (r < 0) - return r; - - event_source_time_prioq_reshuffle(s); - } - - return 0; -} - -static int process_child(sd_event *e) { - sd_event_source *s; - int r; - - assert(e); - - e->need_process_child = false; - - /* - So, this is ugly. We iteratively invoke waitid() with P_PID - + WNOHANG for each PID we wait for, instead of using - P_ALL. This is because we only want to get child - information of very specific child processes, and not all - of them. We might not have processed the SIGCHLD even of a - previous invocation and we don't want to maintain a - unbounded *per-child* event queue, hence we really don't - want anything flushed out of the kernel's queue that we - don't care about. Since this is O(n) this means that if you - have a lot of processes you probably want to handle SIGCHLD - yourself. - - We do not reap the children here (by using WNOWAIT), this - is only done after the event source is dispatched so that - the callback still sees the process as a zombie. - */ - - HASHMAP_FOREACH(s, e->child_sources) { - assert(s->type == SOURCE_CHILD); - - if (s->pending) - continue; - - if (event_source_is_offline(s)) - continue; - - if (s->child.exited) - continue; - - if (EVENT_SOURCE_WATCH_PIDFD(s)) /* There's a usable pidfd known for this event source? then don't waitid() for it here */ - continue; - - zero(s->child.siginfo); - if (waitid(P_PID, s->child.pid, &s->child.siginfo, - WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options) < 0) - return -errno; - - if (s->child.siginfo.si_pid != 0) { - bool zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED); - - if (zombie) - s->child.exited = true; - - if (!zombie && (s->child.options & WEXITED)) { - /* If the child isn't dead then let's - * immediately remove the state change - * from the queue, since there's no - * benefit in leaving it queued */ - - assert(s->child.options & (WSTOPPED|WCONTINUED)); - (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); - } - - r = source_set_pending(s, true); - if (r < 0) - return r; - } - } - - return 0; -} - -static int process_pidfd(sd_event *e, sd_event_source *s, uint32_t revents) { - assert(e); - assert(s); - assert(s->type == SOURCE_CHILD); - - if (s->pending) - return 0; - - if (event_source_is_offline(s)) - return 0; - - if (!EVENT_SOURCE_WATCH_PIDFD(s)) - return 0; - - zero(s->child.siginfo); - if (waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG | WNOWAIT | s->child.options) < 0) - return -errno; - - if (s->child.siginfo.si_pid == 0) - return 0; - - if (IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED)) - s->child.exited = true; - - return source_set_pending(s, true); -} - -static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { - bool read_one = false; - int r; - - assert(e); - assert(d); - assert_return(events == EPOLLIN, -EIO); - - /* If there's a signal queued on this priority and SIGCHLD is - on this priority too, then make sure to recheck the - children we watch. This is because we only ever dequeue - the first signal per priority, and if we dequeue one, and - SIGCHLD might be enqueued later we wouldn't know, but we - might have higher priority children we care about hence we - need to check that explicitly. */ - - if (sigismember(&d->sigset, SIGCHLD)) - e->need_process_child = true; - - /* If there's already an event source pending for this - * priority we don't read another */ - if (d->current) - return 0; - - for (;;) { - struct signalfd_siginfo si; - ssize_t n; - sd_event_source *s = NULL; - - n = read(d->fd, &si, sizeof(si)); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return read_one; - - return -errno; - } - - if (_unlikely_(n != sizeof(si))) - return -EIO; - - assert(SIGNAL_VALID(si.ssi_signo)); - - read_one = true; - - if (e->signal_sources) - s = e->signal_sources[si.ssi_signo]; - if (!s) - continue; - if (s->pending) - continue; - - s->signal.siginfo = si; - d->current = s; - - r = source_set_pending(s, true); - if (r < 0) - return r; - - return 1; - } -} - -static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) { - ssize_t n; - - assert(e); - assert(d); - - assert_return(revents == EPOLLIN, -EIO); - - /* If there's already an event source pending for this priority, don't read another */ - if (d->n_pending > 0) - return 0; - - /* Is the read buffer non-empty? If so, let's not read more */ - if (d->buffer_filled > 0) - return 0; - - n = read(d->fd, &d->buffer, sizeof(d->buffer)); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - return -errno; - } - - assert(n > 0); - d->buffer_filled = (size_t) n; - LIST_PREPEND(buffered, e->inotify_data_buffered, d); - - return 1; -} - -static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t sz) { - assert(e); - assert(d); - assert(sz <= d->buffer_filled); - - if (sz == 0) - return; - - /* Move the rest to the buffer to the front, in order to get things properly aligned again */ - memmove(d->buffer.raw, d->buffer.raw + sz, d->buffer_filled - sz); - d->buffer_filled -= sz; - - if (d->buffer_filled == 0) - LIST_REMOVE(buffered, e->inotify_data_buffered, d); -} - -static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { - int r; - - assert(e); - assert(d); - - /* If there's already an event source pending for this priority, don't read another */ - if (d->n_pending > 0) - return 0; - - while (d->buffer_filled > 0) { - size_t sz; - - /* Let's validate that the event structures are complete */ - if (d->buffer_filled < offsetof(struct inotify_event, name)) - return -EIO; - - sz = offsetof(struct inotify_event, name) + d->buffer.ev.len; - if (d->buffer_filled < sz) - return -EIO; - - if (d->buffer.ev.mask & IN_Q_OVERFLOW) { - struct inode_data *inode_data; - - /* The queue overran, let's pass this event to all event sources connected to this inotify - * object */ - - HASHMAP_FOREACH(inode_data, d->inodes) { - sd_event_source *s; - - LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { - - if (event_source_is_offline(s)) - continue; - - r = source_set_pending(s, true); - if (r < 0) - return r; - } - } - } else { - struct inode_data *inode_data; - sd_event_source *s; - - /* Find the inode object for this watch descriptor. If IN_IGNORED is set we also remove it from - * our watch descriptor table. */ - if (d->buffer.ev.mask & IN_IGNORED) { - - inode_data = hashmap_remove(d->wd, INT_TO_PTR(d->buffer.ev.wd)); - if (!inode_data) { - event_inotify_data_drop(e, d, sz); - continue; - } - - /* The watch descriptor was removed by the kernel, let's drop it here too */ - inode_data->wd = -1; - } else { - inode_data = hashmap_get(d->wd, INT_TO_PTR(d->buffer.ev.wd)); - if (!inode_data) { - event_inotify_data_drop(e, d, sz); - continue; - } - } - - /* Trigger all event sources that are interested in these events. Also trigger all event - * sources if IN_IGNORED or IN_UNMOUNT is set. */ - LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { - - if (event_source_is_offline(s)) - continue; - - if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 && - (s->inotify.mask & d->buffer.ev.mask & IN_ALL_EVENTS) == 0) - continue; - - r = source_set_pending(s, true); - if (r < 0) - return r; - } - } - - /* Something pending now? If so, let's finish, otherwise let's read more. */ - if (d->n_pending > 0) - return 1; - } - - return 0; -} - -static int process_inotify(sd_event *e) { - struct inotify_data *d; - int r, done = 0; - - assert(e); - - LIST_FOREACH(buffered, d, e->inotify_data_buffered) { - r = event_inotify_data_process(e, d); - if (r < 0) - return r; - if (r > 0) - done ++; - } - - return done; -} - -static int source_dispatch(sd_event_source *s) { - _cleanup_(sd_event_unrefp) sd_event *saved_event = NULL; - EventSourceType saved_type; - int r = 0; - - assert(s); - assert(s->pending || s->type == SOURCE_EXIT); - - /* Save the event source type, here, so that we still know it after the event callback which might - * invalidate the event. */ - saved_type = s->type; - - /* Similar, store a reference to the event loop object, so that we can still access it after the - * callback might have invalidated/disconnected the event source. */ - saved_event = sd_event_ref(s->event); - - /* Check if we hit the ratelimit for this event source, if so, let's disable it. */ - assert(!s->ratelimited); - if (!ratelimit_below(&s->rate_limit)) { - r = event_source_enter_ratelimited(s); - if (r < 0) - return r; - - return 1; - } - - if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { - r = source_set_pending(s, false); - if (r < 0) - return r; - } - - if (s->type != SOURCE_POST) { - sd_event_source *z; - - /* If we execute a non-post source, let's mark all - * post sources as pending */ - - SET_FOREACH(z, s->event->post_sources) { - if (event_source_is_offline(z)) - continue; - - r = source_set_pending(z, true); - if (r < 0) - return r; - } - } - - if (s->enabled == SD_EVENT_ONESHOT) { - r = sd_event_source_set_enabled(s, SD_EVENT_OFF); - if (r < 0) - return r; - } - - s->dispatching = true; - - switch (s->type) { - - case SOURCE_IO: - r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata); - break; - - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: - r = s->time.callback(s, s->time.next, s->userdata); - break; - - case SOURCE_SIGNAL: - r = s->signal.callback(s, &s->signal.siginfo, s->userdata); - break; - - case SOURCE_CHILD: { - bool zombie; - - zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED); - - r = s->child.callback(s, &s->child.siginfo, s->userdata); - - /* Now, reap the PID for good. */ - if (zombie) { - (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED); - s->child.waited = true; - } - - break; - } - - case SOURCE_DEFER: - r = s->defer.callback(s, s->userdata); - break; - - case SOURCE_POST: - r = s->post.callback(s, s->userdata); - break; - - case SOURCE_EXIT: - r = s->exit.callback(s, s->userdata); - break; - - case SOURCE_INOTIFY: { - struct sd_event *e = s->event; - struct inotify_data *d; - size_t sz; - - assert(s->inotify.inode_data); - assert_se(d = s->inotify.inode_data->inotify_data); - - assert(d->buffer_filled >= offsetof(struct inotify_event, name)); - sz = offsetof(struct inotify_event, name) + d->buffer.ev.len; - assert(d->buffer_filled >= sz); - - r = s->inotify.callback(s, &d->buffer.ev, s->userdata); - - /* When no event is pending anymore on this inotify object, then let's drop the event from the - * buffer. */ - if (d->n_pending == 0) - event_inotify_data_drop(e, d, sz); - - break; - } - - case SOURCE_WATCHDOG: - case _SOURCE_EVENT_SOURCE_TYPE_MAX: - case _SOURCE_EVENT_SOURCE_TYPE_INVALID: - assert_not_reached("Wut? I shouldn't exist."); - } - - s->dispatching = false; - - if (r < 0) { - log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m", - strna(s->description), - event_source_type_to_string(saved_type), - s->exit_on_failure ? "exiting" : "disabling"); - - if (s->exit_on_failure) - (void) sd_event_exit(saved_event, r); - } - - if (s->n_ref == 0) - source_free(s); - else if (r < 0) - sd_event_source_set_enabled(s, SD_EVENT_OFF); - - return 1; -} - -static int event_prepare(sd_event *e) { - int r; - - assert(e); - - for (;;) { - sd_event_source *s; - - s = prioq_peek(e->prepare); - if (!s || s->prepare_iteration == e->iteration || event_source_is_offline(s)) - break; - - s->prepare_iteration = e->iteration; - r = prioq_reshuffle(e->prepare, s, &s->prepare_index); - if (r < 0) - return r; - - assert(s->prepare); - - s->dispatching = true; - r = s->prepare(s, s->userdata); - s->dispatching = false; - - if (r < 0) { - log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, %s: %m", - strna(s->description), - event_source_type_to_string(s->type), - s->exit_on_failure ? "exiting" : "disabling"); - - if (s->exit_on_failure) - (void) sd_event_exit(e, r); - } - - if (s->n_ref == 0) - source_free(s); - else if (r < 0) - sd_event_source_set_enabled(s, SD_EVENT_OFF); - } - - return 0; -} - -static int dispatch_exit(sd_event *e) { - sd_event_source *p; - int r; - - assert(e); - - p = prioq_peek(e->exit); - if (!p || event_source_is_offline(p)) { - e->state = SD_EVENT_FINISHED; - return 0; - } - - _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); - e->iteration++; - e->state = SD_EVENT_EXITING; - r = source_dispatch(p); - e->state = SD_EVENT_INITIAL; - return r; -} - -static sd_event_source* event_next_pending(sd_event *e) { - sd_event_source *p; - - assert(e); - - p = prioq_peek(e->pending); - if (!p) - return NULL; - - if (event_source_is_offline(p)) - return NULL; - - return p; -} - -static int arm_watchdog(sd_event *e) { - struct itimerspec its = {}; - usec_t t; - - assert(e); - assert(e->watchdog_fd >= 0); - - t = sleep_between(e, - e->watchdog_last + (e->watchdog_period / 2), - e->watchdog_last + (e->watchdog_period * 3 / 4)); - - timespec_store(&its.it_value, t); - - /* Make sure we never set the watchdog to 0, which tells the - * kernel to disable it. */ - if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) - its.it_value.tv_nsec = 1; - - if (timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) - return -errno; - - return 0; -} - -static int process_watchdog(sd_event *e) { - assert(e); - - if (!e->watchdog) - return 0; - - /* Don't notify watchdog too often */ - if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic) - return 0; - - sd_notify(false, "WATCHDOG=1"); - e->watchdog_last = e->timestamp.monotonic; - - return arm_watchdog(e); -} - -static void event_close_inode_data_fds(sd_event *e) { - struct inode_data *d; - - assert(e); - - /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin - * filesystems. But we can't close them right-away as we need them as long as the user still wants to make - * adjustments to the even source, such as changing the priority (which requires us to remove and re-add a watch - * for the inode). Hence, let's close them when entering the first iteration after they were added, as a - * compromise. */ - - while ((d = e->inode_data_to_close)) { - assert(d->fd >= 0); - d->fd = safe_close(d->fd); - - LIST_REMOVE(to_close, e->inode_data_to_close, d); - } -} - -_public_ int sd_event_prepare(sd_event *e) { - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); - - /* Let's check that if we are a default event loop we are executed in the correct thread. We only do - * this check here once, since gettid() is typically not cached, and thus want to minimize - * syscalls */ - assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO); - - /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ - _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); - - if (e->exit_requested) - goto pending; - - e->iteration++; - - e->state = SD_EVENT_PREPARING; - r = event_prepare(e); - e->state = SD_EVENT_INITIAL; - if (r < 0) - return r; - - r = event_arm_timer(e, &e->realtime); - if (r < 0) - return r; - - r = event_arm_timer(e, &e->boottime); - if (r < 0) - return r; - - r = event_arm_timer(e, &e->monotonic); - if (r < 0) - return r; - - r = event_arm_timer(e, &e->realtime_alarm); - if (r < 0) - return r; - - r = event_arm_timer(e, &e->boottime_alarm); - if (r < 0) - return r; - - event_close_inode_data_fds(e); - - if (event_next_pending(e) || e->need_process_child) - goto pending; - - e->state = SD_EVENT_ARMED; - - return 0; - -pending: - e->state = SD_EVENT_ARMED; - r = sd_event_wait(e, 0); - if (r == 0) - e->state = SD_EVENT_ARMED; - - return r; -} - -_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { - size_t event_queue_max; - int r, m, i; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(e->state == SD_EVENT_ARMED, -EBUSY); - - if (e->exit_requested) { - e->state = SD_EVENT_PENDING; - return 1; - } - - event_queue_max = MAX(e->n_sources, 1u); - if (!GREEDY_REALLOC(e->event_queue, e->event_queue_allocated, event_queue_max)) - return -ENOMEM; - - /* If we still have inotify data buffered, then query the other fds, but don't wait on it */ - if (e->inotify_data_buffered) - timeout = 0; - - m = epoll_wait(e->epoll_fd, e->event_queue, event_queue_max, - timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC)); - if (m < 0) { - if (errno == EINTR) { - e->state = SD_EVENT_PENDING; - return 1; - } - - r = -errno; - goto finish; - } - - triple_timestamp_get(&e->timestamp); - - for (i = 0; i < m; i++) { - - if (e->event_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) - r = flush_timer(e, e->watchdog_fd, e->event_queue[i].events, NULL); - else { - WakeupType *t = e->event_queue[i].data.ptr; - - switch (*t) { - - case WAKEUP_EVENT_SOURCE: { - sd_event_source *s = e->event_queue[i].data.ptr; - - assert(s); - - switch (s->type) { - - case SOURCE_IO: - r = process_io(e, s, e->event_queue[i].events); - break; - - case SOURCE_CHILD: - r = process_pidfd(e, s, e->event_queue[i].events); - break; - - default: - assert_not_reached("Unexpected event source type"); - } - - break; - } - - case WAKEUP_CLOCK_DATA: { - struct clock_data *d = e->event_queue[i].data.ptr; - - assert(d); - - r = flush_timer(e, d->fd, e->event_queue[i].events, &d->next); - break; - } - - case WAKEUP_SIGNAL_DATA: - r = process_signal(e, e->event_queue[i].data.ptr, e->event_queue[i].events); - break; - - case WAKEUP_INOTIFY_DATA: - r = event_inotify_data_read(e, e->event_queue[i].data.ptr, e->event_queue[i].events); - break; - - default: - assert_not_reached("Invalid wake-up pointer"); - } - } - if (r < 0) - goto finish; - } - - r = process_watchdog(e); - if (r < 0) - goto finish; - - r = process_timer(e, e->timestamp.realtime, &e->realtime); - if (r < 0) - goto finish; - - r = process_timer(e, e->timestamp.boottime, &e->boottime); - if (r < 0) - goto finish; - - r = process_timer(e, e->timestamp.monotonic, &e->monotonic); - if (r < 0) - goto finish; - - r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm); - if (r < 0) - goto finish; - - r = process_timer(e, e->timestamp.boottime, &e->boottime_alarm); - if (r < 0) - goto finish; - - if (e->need_process_child) { - r = process_child(e); - if (r < 0) - goto finish; - } - - r = process_inotify(e); - if (r < 0) - goto finish; - - if (event_next_pending(e)) { - e->state = SD_EVENT_PENDING; - - return 1; - } - - r = 0; - -finish: - e->state = SD_EVENT_INITIAL; - - return r; -} - -_public_ int sd_event_dispatch(sd_event *e) { - sd_event_source *p; - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(e->state == SD_EVENT_PENDING, -EBUSY); - - if (e->exit_requested) - return dispatch_exit(e); - - p = event_next_pending(e); - if (p) { - _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); - - e->state = SD_EVENT_RUNNING; - r = source_dispatch(p); - e->state = SD_EVENT_INITIAL; - return r; - } - - e->state = SD_EVENT_INITIAL; - - return 1; -} - -static void event_log_delays(sd_event *e) { - char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1], *p; - size_t l, i; - - p = b; - l = sizeof(b); - for (i = 0; i < ELEMENTSOF(e->delays); i++) { - l = strpcpyf(&p, l, "%u ", e->delays[i]); - e->delays[i] = 0; - } - log_debug("Event loop iterations: %s", b); -} - -_public_ int sd_event_run(sd_event *e, uint64_t timeout) { - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); - - if (e->profile_delays && e->last_run_usec != 0) { - usec_t this_run; - unsigned l; - - this_run = now(CLOCK_MONOTONIC); - - l = u64log2(this_run - e->last_run_usec); - assert(l < ELEMENTSOF(e->delays)); - e->delays[l]++; - - if (this_run - e->last_log_usec >= 5*USEC_PER_SEC) { - event_log_delays(e); - e->last_log_usec = this_run; - } - } - - /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ - _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); - - r = sd_event_prepare(e); - if (r == 0) - /* There was nothing? Then wait... */ - r = sd_event_wait(e, timeout); - - if (e->profile_delays) - e->last_run_usec = now(CLOCK_MONOTONIC); - - if (r > 0) { - /* There's something now, then let's dispatch it */ - r = sd_event_dispatch(e); - if (r < 0) - return r; - - return 1; - } - - return r; -} - -_public_ int sd_event_loop(sd_event *e) { - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); - - _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = NULL; - - while (e->state != SD_EVENT_FINISHED) { - r = sd_event_run(e, (uint64_t) -1); - if (r < 0) - return r; - } - - return e->exit_code; -} - -_public_ int sd_event_get_fd(sd_event *e) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - - return e->epoll_fd; -} - -_public_ int sd_event_get_state(sd_event *e) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - - return e->state; -} - -_public_ int sd_event_get_exit_code(sd_event *e, int *code) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(code, -EINVAL); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!e->exit_requested) - return -ENODATA; - - *code = e->exit_code; - return 0; -} - -_public_ int sd_event_exit(sd_event *e, int code) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); - assert_return(!event_pid_changed(e), -ECHILD); - - e->exit_requested = true; - e->exit_code = code; - - return 0; -} - -_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(usec, -EINVAL); - assert_return(!event_pid_changed(e), -ECHILD); - - if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock)) - return -EOPNOTSUPP; - - /* Generate a clean error in case CLOCK_BOOTTIME is not available. Note that don't use clock_supported() here, - * for a reason: there are systems where CLOCK_BOOTTIME is supported, but CLOCK_BOOTTIME_ALARM is not, but for - * the purpose of getting the time this doesn't matter. */ - if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported()) - return -EOPNOTSUPP; - - if (!triple_timestamp_is_set(&e->timestamp)) { - /* Implicitly fall back to now() if we never ran before and thus have no cached time. */ - *usec = now(clock); - return 1; - } - - *usec = triple_timestamp_by_clock(&e->timestamp, clock); - return 0; -} - -_public_ int sd_event_default(sd_event **ret) { - sd_event *e = NULL; - int r; - - if (!ret) - return !!default_event; - - if (default_event) { - *ret = sd_event_ref(default_event); - return 0; - } - - r = sd_event_new(&e); - if (r < 0) - return r; - - e->default_event_ptr = &default_event; - e->tid = gettid(); - default_event = e; - - *ret = e; - return 1; -} - -#if 0 /* NM_IGNORED */ -_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(tid, -EINVAL); - assert_return(!event_pid_changed(e), -ECHILD); - - if (e->tid != 0) { - *tid = e->tid; - return 0; - } - - return -ENXIO; -} - -_public_ int sd_event_set_watchdog(sd_event *e, int b) { - int r; - - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - - if (e->watchdog == !!b) - return e->watchdog; - - if (b) { - r = sd_watchdog_enabled(false, &e->watchdog_period); - if (r <= 0) - return r; - - /* Issue first ping immediately */ - sd_notify(false, "WATCHDOG=1"); - e->watchdog_last = now(CLOCK_MONOTONIC); - - e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); - if (e->watchdog_fd < 0) - return -errno; - - r = arm_watchdog(e); - if (r < 0) - goto fail; - - struct epoll_event ev = { - .events = EPOLLIN, - .data.ptr = INT_TO_PTR(SOURCE_WATCHDOG), - }; - - if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev) < 0) { - r = -errno; - goto fail; - } - - } else { - if (e->watchdog_fd >= 0) { - (void) epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL); - e->watchdog_fd = safe_close(e->watchdog_fd); - } - } - - e->watchdog = !!b; - return e->watchdog; - -fail: - e->watchdog_fd = safe_close(e->watchdog_fd); - return r; -} - -_public_ int sd_event_get_watchdog(sd_event *e) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - - return e->watchdog; -} - -_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) { - assert_return(e, -EINVAL); - assert_return(e = event_resolve(e), -ENOPKG); - assert_return(!event_pid_changed(e), -ECHILD); - - *ret = e->iteration; - return 0; -} - -_public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback) { - assert_return(s, -EINVAL); - - s->destroy_callback = callback; - return 0; -} - -_public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret) { - assert_return(s, -EINVAL); - - if (ret) - *ret = s->destroy_callback; - - return !!s->destroy_callback; -} - -_public_ int sd_event_source_get_floating(sd_event_source *s) { - assert_return(s, -EINVAL); - - return s->floating; -} - -_public_ int sd_event_source_set_floating(sd_event_source *s, int b) { - assert_return(s, -EINVAL); - - if (s->floating == !!b) - return 0; - - if (!s->event) /* Already disconnected */ - return -ESTALE; - - s->floating = b; - - if (b) { - sd_event_source_ref(s); - sd_event_unref(s->event); - } else { - sd_event_ref(s->event); - sd_event_source_unref(s); - } - - return 1; -} - -_public_ int sd_event_source_get_exit_on_failure(sd_event_source *s) { - assert_return(s, -EINVAL); - assert_return(s->type != SOURCE_EXIT, -EDOM); - - return s->exit_on_failure; -} - -_public_ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b) { - assert_return(s, -EINVAL); - assert_return(s->type != SOURCE_EXIT, -EDOM); - - if (s->exit_on_failure == !!b) - return 0; - - s->exit_on_failure = b; - return 1; -} - -_public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval, unsigned burst) { - int r; - - assert_return(s, -EINVAL); - - /* Turning on ratelimiting on event source types that don't support it, is a loggable offense. Doing - * so is a programming error. */ - assert_return(EVENT_SOURCE_CAN_RATE_LIMIT(s->type), -EDOM); - - /* When ratelimiting is configured we'll always reset the rate limit state first and start fresh, - * non-ratelimited. */ - r = event_source_leave_ratelimit(s); - if (r < 0) - return r; - - s->rate_limit = (RateLimit) { interval, burst }; - return 0; -} - -_public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) { - assert_return(s, -EINVAL); - - /* Querying whether an event source has ratelimiting configured is not a loggable offsense, hence - * don't use assert_return(). Unlike turning on ratelimiting it's not really a programming error */ - if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) - return -EDOM; - - if (!ratelimit_configured(&s->rate_limit)) - return -ENOEXEC; - - if (ret_interval) - *ret_interval = s->rate_limit.interval; - if (ret_burst) - *ret_burst = s->rate_limit.burst; - - return 0; -} - -_public_ int sd_event_source_is_ratelimited(sd_event_source *s) { - assert_return(s, -EINVAL); - - if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) - return false; - - if (!ratelimit_configured(&s->rate_limit)) - return false; - - return s->ratelimited; -} -#endif /* NM_IGNORED */ diff --git a/src/core/systemd/src/libsystemd/sd-id128/id128-util.c b/src/core/systemd/src/libsystemd/sd-id128/id128-util.c deleted file mode 100644 index b61cfdb0..00000000 --- a/src/core/systemd/src/libsystemd/sd-id128/id128-util.c +++ /dev/null @@ -1,218 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "fd-util.h" -#include "fs-util.h" -#include "hexdecoct.h" -#include "id128-util.h" -#include "io-util.h" -#include "stdio-util.h" -#include "string-util.h" - -#if 0 /* NM_IGNORED */ -char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]) { - unsigned n, k = 0; - - assert(s); - - /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */ - - for (n = 0; n < 16; n++) { - - if (IN_SET(n, 4, 6, 8, 10)) - s[k++] = '-'; - - s[k++] = hexchar(id.bytes[n] >> 4); - s[k++] = hexchar(id.bytes[n] & 0xF); - } - - assert(k == 36); - - s[k] = 0; - - return s; -} - -bool id128_is_valid(const char *s) { - size_t i, l; - - assert(s); - - l = strlen(s); - if (l == 32) { - - /* Plain formatted 128bit hex string */ - - for (i = 0; i < l; i++) { - char c = s[i]; - - if (!(c >= '0' && c <= '9') && - !(c >= 'a' && c <= 'z') && - !(c >= 'A' && c <= 'Z')) - return false; - } - - } else if (l == 36) { - - /* Formatted UUID */ - - for (i = 0; i < l; i++) { - char c = s[i]; - - if (IN_SET(i, 8, 13, 18, 23)) { - if (c != '-') - return false; - } else { - if (!(c >= '0' && c <= '9') && - !(c >= 'a' && c <= 'z') && - !(c >= 'A' && c <= 'Z')) - return false; - } - } - - } else - return false; - - return true; -} -#endif /* NM_IGNORED */ - -int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { - char buffer[36 + 2]; - ssize_t l; - - assert(fd >= 0); - assert(f < _ID128_FORMAT_MAX); - - /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both - * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they - * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you - * accept". */ - - l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */ - if (l < 0) - return (int) l; - if (l == 0) /* empty? */ - return -ENOMEDIUM; - - switch (l) { - - case 13: - case 14: - /* Treat an "uninitialized" id file like an empty one */ - return f == ID128_PLAIN_OR_UNINIT && strneq(buffer, "uninitialized\n", l) ? -ENOMEDIUM : -EINVAL; - - case 33: /* plain UUID with trailing newline */ - if (buffer[32] != '\n') - return -EINVAL; - - _fallthrough_; - case 32: /* plain UUID without trailing newline */ - if (f == ID128_UUID) - return -EINVAL; - - buffer[32] = 0; - break; - - case 37: /* RFC UUID with trailing newline */ - if (buffer[36] != '\n') - return -EINVAL; - - _fallthrough_; - case 36: /* RFC UUID without trailing newline */ - if (IN_SET(f, ID128_PLAIN, ID128_PLAIN_OR_UNINIT)) - return -EINVAL; - - buffer[36] = 0; - break; - - default: - return -EINVAL; - } - - return sd_id128_from_string(buffer, ret); -} - -int id128_read(const char *p, Id128Format f, sd_id128_t *ret) { - _cleanup_close_ int fd = -1; - - fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0) - return -errno; - - return id128_read_fd(fd, f, ret); -} - -#if 0 /* NM_IGNORED */ -int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { - char buffer[36 + 2]; - size_t sz; - int r; - - assert(fd >= 0); - assert(f < _ID128_FORMAT_MAX); - - if (f != ID128_UUID) { - sd_id128_to_string(id, buffer); - buffer[32] = '\n'; - sz = 33; - } else { - id128_to_uuid_string(id, buffer); - buffer[36] = '\n'; - sz = 37; - } - - r = loop_write(fd, buffer, sz, false); - if (r < 0) - return r; - - if (do_sync) { - if (fsync(fd) < 0) - return -errno; - - r = fsync_directory_of_file(fd); - if (r < 0) - return r; - } - - return 0; -} - -int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) { - _cleanup_close_ int fd = -1; - - fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444); - if (fd < 0) - return -errno; - - return id128_write_fd(fd, f, id, do_sync); -} - -void id128_hash_func(const sd_id128_t *p, struct siphash *state) { - siphash24_compress(p, sizeof(sd_id128_t), state); -} - -int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) { - return memcmp(a, b, 16); -} - -sd_id128_t id128_make_v4_uuid(sd_id128_t id) { - /* Stolen from generate_random_uuid() of drivers/char/random.c - * in the kernel sources */ - - /* Set UUID version to 4 --- truly random generation */ - id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40; - - /* Set the UUID variant to DCE */ - id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80; - - return id; -} - -DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func); -#endif /* NM_IGNORED */ diff --git a/src/core/systemd/src/libsystemd/sd-id128/id128-util.h b/src/core/systemd/src/libsystemd/sd-id128/id128-util.h deleted file mode 100644 index 6b09bcd9..00000000 --- a/src/core/systemd/src/libsystemd/sd-id128/id128-util.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include - -#include "sd-id128.h" - -#include "hash-funcs.h" -#include "macro.h" - -#define ID128_UUID_STRING_MAX 37 - -char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]); - -bool id128_is_valid(const char *s) _pure_; - -typedef enum Id128Format { - ID128_ANY, - ID128_PLAIN, /* formatted as 32 hex chars as-is */ - ID128_PLAIN_OR_UNINIT, /* formatted as 32 hex chars as-is; allow special "uninitialized" - * value when reading from file (id128_read() and id128_read_fd()). - * - * This format should be used when reading a machine-id file. */ - ID128_UUID, /* formatted as 36 character uuid string */ - _ID128_FORMAT_MAX, -} Id128Format; - -int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret); -int id128_read(const char *p, Id128Format f, sd_id128_t *ret); - -int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync); -int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync); - -void id128_hash_func(const sd_id128_t *p, struct siphash *state); -int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_; -extern const struct hash_ops id128_hash_ops; - -sd_id128_t id128_make_v4_uuid(sd_id128_t id); diff --git a/src/core/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/core/systemd/src/libsystemd/sd-id128/sd-id128.c deleted file mode 100644 index 64b8c787..00000000 --- a/src/core/systemd/src/libsystemd/sd-id128/sd-id128.c +++ /dev/null @@ -1,330 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "nm-sd-adapt-core.h" - -#include -#include -#include - -#include "sd-id128.h" - -#include "alloc-util.h" -#include "fd-util.h" -#include "hexdecoct.h" -#include "id128-util.h" -#include "io-util.h" -#include "khash.h" -#include "macro.h" -#include "missing_syscall.h" -#include "random-util.h" -#include "user-util.h" -#include "util.h" - -#if 0 /* NM_IGNORED */ -_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) { - unsigned n; - - assert_return(s, NULL); - - for (n = 0; n < 16; n++) { - s[n*2] = hexchar(id.bytes[n] >> 4); - s[n*2+1] = hexchar(id.bytes[n] & 0xF); - } - - s[32] = 0; - - return s; -} -#endif /* NM_IGNORED */ - -_public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) { - unsigned n, i; - sd_id128_t t; - bool is_guid = false; - - assert_return(s, -EINVAL); - - for (n = 0, i = 0; n < 16;) { - int a, b; - - if (s[i] == '-') { - /* Is this a GUID? Then be nice, and skip over - * the dashes */ - - if (i == 8) - is_guid = true; - else if (IN_SET(i, 13, 18, 23)) { - if (!is_guid) - return -EINVAL; - } else - return -EINVAL; - - i++; - continue; - } - - a = unhexchar(s[i++]); - if (a < 0) - return -EINVAL; - - b = unhexchar(s[i++]); - if (b < 0) - return -EINVAL; - - t.bytes[n++] = (a << 4) | b; - } - - if (i != (is_guid ? 36 : 32)) - return -EINVAL; - - if (s[i] != 0) - return -EINVAL; - - if (ret) - *ret = t; - return 0; -} - -_public_ int sd_id128_get_machine(sd_id128_t *ret) { - static thread_local sd_id128_t saved_machine_id = {}; - int r; - - assert_return(ret, -EINVAL); - - if (sd_id128_is_null(saved_machine_id)) { - r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id); - if (r < 0) - return r; - - if (sd_id128_is_null(saved_machine_id)) - return -ENOMEDIUM; - } - - *ret = saved_machine_id; - return 0; -} - -_public_ int sd_id128_get_boot(sd_id128_t *ret) { - static thread_local sd_id128_t saved_boot_id = {}; - int r; - - assert_return(ret, -EINVAL); - - if (sd_id128_is_null(saved_boot_id)) { - r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id); - if (r < 0) - return r; - } - - *ret = saved_boot_id; - return 0; -} - -#if 0 /* NM_IGNORED */ -static int get_invocation_from_keyring(sd_id128_t *ret) { - _cleanup_free_ char *description = NULL; - char *d, *p, *g, *u, *e; - unsigned long perms; - key_serial_t key; - size_t sz = 256; - uid_t uid; - gid_t gid; - int r, c; - -#define MAX_PERMS ((unsigned long) (KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH| \ - KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH)) - - assert(ret); - - key = request_key("user", "invocation_id", NULL, 0); - if (key == -1) { - /* Keyring support not available? No invocation key stored? */ - if (IN_SET(errno, ENOSYS, ENOKEY)) - return -ENXIO; - - return -errno; - } - - for (;;) { - description = new(char, sz); - if (!description) - return -ENOMEM; - - c = keyctl(KEYCTL_DESCRIBE, key, (unsigned long) description, sz, 0); - if (c < 0) - return -errno; - - if ((size_t) c <= sz) - break; - - sz = c; - free(description); - } - - /* The kernel returns a final NUL in the string, verify that. */ - assert(description[c-1] == 0); - - /* Chop off the final description string */ - d = strrchr(description, ';'); - if (!d) - return -EIO; - *d = 0; - - /* Look for the permissions */ - p = strrchr(description, ';'); - if (!p) - return -EIO; - - errno = 0; - perms = strtoul(p + 1, &e, 16); - if (errno > 0) - return -errno; - if (e == p + 1) /* Read at least one character */ - return -EIO; - if (e != d) /* Must reached the end */ - return -EIO; - - if ((perms & ~MAX_PERMS) != 0) - return -EPERM; - - *p = 0; - - /* Look for the group ID */ - g = strrchr(description, ';'); - if (!g) - return -EIO; - r = parse_gid(g + 1, &gid); - if (r < 0) - return r; - if (gid != 0) - return -EPERM; - *g = 0; - - /* Look for the user ID */ - u = strrchr(description, ';'); - if (!u) - return -EIO; - r = parse_uid(u + 1, &uid); - if (r < 0) - return r; - if (uid != 0) - return -EPERM; - - c = keyctl(KEYCTL_READ, key, (unsigned long) ret, sizeof(sd_id128_t), 0); - if (c < 0) - return -errno; - if (c != sizeof(sd_id128_t)) - return -EIO; - - return 0; -} - -static int get_invocation_from_environment(sd_id128_t *ret) { - const char *e; - - assert(ret); - - e = secure_getenv("INVOCATION_ID"); - if (!e) - return -ENXIO; - - return sd_id128_from_string(e, ret); -} - -_public_ int sd_id128_get_invocation(sd_id128_t *ret) { - static thread_local sd_id128_t saved_invocation_id = {}; - int r; - - assert_return(ret, -EINVAL); - - if (sd_id128_is_null(saved_invocation_id)) { - /* We first check the environment. The environment variable is primarily relevant for user - * services, and sufficiently safe as long as no privilege boundary is involved. */ - r = get_invocation_from_environment(&saved_invocation_id); - if (r < 0 && r != -ENXIO) - return r; - - /* The kernel keyring is relevant for system services (as for user services we don't store - * the invocation ID in the keyring, as there'd be no trust benefit in that). */ - r = get_invocation_from_keyring(&saved_invocation_id); - if (r < 0) - return r; - } - - *ret = saved_invocation_id; - return 0; -} - -_public_ int sd_id128_randomize(sd_id128_t *ret) { - sd_id128_t t; - int r; - - assert_return(ret, -EINVAL); - - /* We allow usage if x86-64 RDRAND here. It might not be trusted enough for keeping secrets, but it should be - * fine for UUIDS. */ - r = genuine_random_bytes(&t, sizeof t, RANDOM_ALLOW_RDRAND); - if (r < 0) - return r; - - /* Turn this into a valid v4 UUID, to be nice. Note that we - * only guarantee this for newly generated UUIDs, not for - * pre-existing ones. */ - - *ret = id128_make_v4_uuid(t); - return 0; -} - -static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) { - _cleanup_(khash_unrefp) khash *h = NULL; - sd_id128_t result; - const void *p; - int r; - - assert(ret); - - r = khash_new_with_key(&h, "hmac(sha256)", &base, sizeof(base)); - if (r < 0) - return r; - - r = khash_put(h, &app_id, sizeof(app_id)); - if (r < 0) - return r; - - r = khash_digest_data(h, &p); - if (r < 0) - return r; - - /* We chop off the trailing 16 bytes */ - memcpy(&result, p, MIN(khash_get_size(h), sizeof(result))); - - *ret = id128_make_v4_uuid(result); - return 0; -} - -_public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) { - sd_id128_t id; - int r; - - assert_return(ret, -EINVAL); - - r = sd_id128_get_machine(&id); - if (r < 0) - return r; - - return get_app_specific(id, app_id, ret); -} - -_public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) { - sd_id128_t id; - int r; - - assert_return(ret, -EINVAL); - - r = sd_id128_get_boot(&id); - if (r < 0) - return r; - - return get_app_specific(id, app_id, ret); -} -#endif /* NM_IGNORED */ diff --git a/src/core/systemd/src/systemd/_sd-common.h b/src/core/systemd/src/systemd/_sd-common.h deleted file mode 100644 index e3de2ae5..00000000 --- a/src/core/systemd/src/systemd/_sd-common.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdcommonhfoo -#define foosdcommonhfoo - -/*** - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -/* This is a private header; never even think of including this directly! */ - -#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1 && !defined(__COVERITY__) -# error "Do not include _sd-common.h directly; it is a private header." -#endif - -typedef void (*_sd_destroy_t)(void *userdata); - -#ifndef _sd_printf_ -# if __GNUC__ >= 4 -# define _sd_printf_(a,b) __attribute__((__format__(printf, a, b))) -# else -# define _sd_printf_(a,b) -# endif -#endif - -#ifndef _sd_sentinel_ -# define _sd_sentinel_ __attribute__((__sentinel__)) -#endif - -#ifndef _sd_packed_ -# define _sd_packed_ __attribute__((__packed__)) -#endif - -#ifndef _sd_pure_ -# define _sd_pure_ __attribute__((__pure__)) -#endif - -/* Note that strictly speaking __deprecated__ has been available before GCC 6. However, starting with GCC 6 - * it also works on enum values, which we are interested in. Since this is a developer-facing feature anyway - * (as opposed to build engineer-facing), let's hence conditionalize this to gcc 6, given that the developers - * are probably going to use something newer anyway. */ -#ifndef _sd_deprecated_ -# if __GNUC__ >= 6 -# define _sd_deprecated_ __attribute__((__deprecated__)) -# else -# define _sd_deprecated_ -# endif -#endif - -#ifndef _SD_STRINGIFY -# define _SD_XSTRINGIFY(x) #x -# define _SD_STRINGIFY(x) _SD_XSTRINGIFY(x) -#endif - -#ifndef _SD_BEGIN_DECLARATIONS -# ifdef __cplusplus -# define _SD_BEGIN_DECLARATIONS \ - extern "C" { \ - struct _sd_useless_struct_to_allow_trailing_semicolon_ -# else -# define _SD_BEGIN_DECLARATIONS \ - struct _sd_useless_struct_to_allow_trailing_semicolon_ -# endif -#endif - -#ifndef _SD_END_DECLARATIONS -# ifdef __cplusplus -# define _SD_END_DECLARATIONS \ - } \ - struct _sd_useless_cpp_struct_to_allow_trailing_semicolon_ -# else -# define _SD_END_DECLARATIONS \ - struct _sd_useless_struct_to_allow_trailing_semicolon_ -# endif -#endif - -#ifndef _SD_ARRAY_STATIC -# if __STDC_VERSION__ >= 199901L -# define _SD_ARRAY_STATIC static -# else -# define _SD_ARRAY_STATIC -# endif -#endif - -#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \ - static __inline__ void func##p(type **p) { \ - if (*p) \ - func(*p); \ - } \ - struct _sd_useless_struct_to_allow_trailing_semicolon_ - -#endif diff --git a/src/core/systemd/src/systemd/sd-dhcp-client.h b/src/core/systemd/src/systemd/sd-dhcp-client.h deleted file mode 100644 index c35328a9..00000000 --- a/src/core/systemd/src/systemd/sd-dhcp-client.h +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosddhcpclienthfoo -#define foosddhcpclienthfoo - -/*** - Copyright © 2013 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include - -#include "sd-dhcp-lease.h" -#include "sd-dhcp-option.h" -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -enum { - SD_DHCP_CLIENT_EVENT_STOP = 0, - SD_DHCP_CLIENT_EVENT_IP_ACQUIRE = 1, - SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2, - SD_DHCP_CLIENT_EVENT_EXPIRED = 3, - SD_DHCP_CLIENT_EVENT_RENEW = 4, - SD_DHCP_CLIENT_EVENT_SELECTING = 5, - SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE = 6, /* Sent when we have not received a reply after the first few attempts. - * The client may want to start acquiring link-local addresses. */ -}; - -enum { - SD_DHCP_OPTION_PAD = 0, - SD_DHCP_OPTION_SUBNET_MASK = 1, - SD_DHCP_OPTION_TIME_OFFSET = 2, - SD_DHCP_OPTION_ROUTER = 3, - SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, - SD_DHCP_OPTION_LPR_SERVER = 9, - SD_DHCP_OPTION_HOST_NAME = 12, - SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, - SD_DHCP_OPTION_DOMAIN_NAME = 15, - SD_DHCP_OPTION_ROOT_PATH = 17, - SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19, - SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20, - SD_DHCP_OPTION_POLICY_FILTER = 21, - SD_DHCP_OPTION_INTERFACE_MDR = 22, - SD_DHCP_OPTION_INTERFACE_TTL = 23, - SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24, - SD_DHCP_OPTION_INTERFACE_MTU = 26, - SD_DHCP_OPTION_BROADCAST = 28, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_ROUTER_DISCOVER = 31, - SD_DHCP_OPTION_STATIC_ROUTE = 33, - SD_DHCP_OPTION_NTP_SERVER = 42, - SD_DHCP_OPTION_VENDOR_SPECIFIC = 43, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_NETBIOS_NAMESERVER = 44, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_NETBIOS_NODETYPE = 46, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_NETBIOS_SCOPE = 47, - SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, - SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, - SD_DHCP_OPTION_OVERLOAD = 52, - SD_DHCP_OPTION_MESSAGE_TYPE = 53, - SD_DHCP_OPTION_SERVER_IDENTIFIER = 54, - SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, - SD_DHCP_OPTION_ERROR_MESSAGE = 56, - SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57, - SD_DHCP_OPTION_RENEWAL_T1_TIME = 58, - SD_DHCP_OPTION_REBINDING_T2_TIME = 59, - SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, - SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61, - SD_DHCP_OPTION_SMTP_SERVER = 69, - SD_DHCP_OPTION_POP3_SERVER = 70, - SD_DHCP_OPTION_USER_CLASS = 77, - SD_DHCP_OPTION_FQDN = 81, - SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, - SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, - SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119, - SD_DHCP_OPTION_SIP_SERVER = 120, - SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, - SD_DHCP_OPTION_MUD_URL = 161, - SD_DHCP_OPTION_PRIVATE_BASE = 224, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252, - SD_DHCP_OPTION_PRIVATE_LAST = 254, - SD_DHCP_OPTION_END = 255, -}; - -typedef struct sd_dhcp_client sd_dhcp_client; - -typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata); -int sd_dhcp_client_set_callback( - sd_dhcp_client *client, - sd_dhcp_client_callback_t cb, - void *userdata); - -int sd_dhcp_client_set_request_option( - sd_dhcp_client *client, - uint8_t option); -int sd_dhcp_client_set_request_address( - sd_dhcp_client *client, - const struct in_addr *last_address); -int sd_dhcp_client_set_request_broadcast( - sd_dhcp_client *client, - int broadcast); -int sd_dhcp_client_set_ifindex( - sd_dhcp_client *client, - int interface_index); -int sd_dhcp_client_set_mac( - sd_dhcp_client *client, - const uint8_t *addr, - const uint8_t *bcast_addr, - size_t addr_len, - uint16_t arp_type); -int sd_dhcp_client_set_client_id( - sd_dhcp_client *client, - uint8_t type, - const uint8_t *data, - size_t data_len); -int sd_dhcp_client_set_iaid_duid( - sd_dhcp_client *client, - bool iaid_set, - uint32_t iaid, - uint16_t duid_type, - const void *duid, - size_t duid_len); -int sd_dhcp_client_set_iaid_duid_llt( - sd_dhcp_client *client, - bool iaid_set, - uint32_t iaid, - uint64_t llt_time); -int sd_dhcp_client_set_duid( - sd_dhcp_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len); -int sd_dhcp_client_set_duid_llt( - sd_dhcp_client *client, - uint64_t llt_time); -int sd_dhcp_client_get_client_id( - sd_dhcp_client *client, - uint8_t *type, - const uint8_t **data, - size_t *data_len); -int sd_dhcp_client_set_mtu( - sd_dhcp_client *client, - uint32_t mtu); -int sd_dhcp_client_set_max_attempts( - sd_dhcp_client *client, - uint64_t attempt); -int sd_dhcp_client_set_client_port( - sd_dhcp_client *client, - uint16_t port); -int sd_dhcp_client_set_hostname( - sd_dhcp_client *client, - const char *hostname); -int sd_dhcp_client_set_vendor_class_identifier( - sd_dhcp_client *client, - const char *vci); -int sd_dhcp_client_set_mud_url( - sd_dhcp_client *client, - const char *mudurl); -int sd_dhcp_client_set_user_class( - sd_dhcp_client *client, - const char* const *user_class); -int sd_dhcp_client_get_lease( - sd_dhcp_client *client, - sd_dhcp_lease **ret); -int sd_dhcp_client_set_service_type( - sd_dhcp_client *client, - int type); -int sd_dhcp_client_set_fallback_lease_lifetime( - sd_dhcp_client *client, - uint32_t fallback_lease_lifetime); - -int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v); -int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v); - -int sd_dhcp_client_stop(sd_dhcp_client *client); -int sd_dhcp_client_start(sd_dhcp_client *client); -int sd_dhcp_client_send_release(sd_dhcp_client *client); -int sd_dhcp_client_send_decline(sd_dhcp_client *client); -int sd_dhcp_client_send_renew(sd_dhcp_client *client); - -sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); -sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); - -/* NOTE: anonymize parameter is used to initialize PRL memory with different - * options when using RFC7844 Anonymity Profiles */ -int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize); - -int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret); - -int sd_dhcp_client_attach_event( - sd_dhcp_client *client, - sd_event *event, - int64_t priority); -int sd_dhcp_client_detach_event(sd_dhcp_client *client); -sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-dhcp-lease.h b/src/core/systemd/src/systemd/sd-dhcp-lease.h deleted file mode 100644 index c255a1f9..00000000 --- a/src/core/systemd/src/systemd/sd-dhcp-lease.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosddhcpleasehfoo -#define foosddhcpleasehfoo - -/*** - Copyright © 2013 Intel Corporation. All rights reserved. - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -typedef struct sd_dhcp_lease sd_dhcp_lease; -typedef struct sd_dhcp_route sd_dhcp_route; - -sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease); -sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease); - -typedef enum sd_dhcp_lease_server_type { - SD_DHCP_LEASE_DNS, - SD_DHCP_LEASE_NTP, - SD_DHCP_LEASE_SIP, - SD_DHCP_LEASE_POP3, - SD_DHCP_LEASE_SMTP, - SD_DHCP_LEASE_LPR, - _SD_DHCP_LEASE_SERVER_TYPE_MAX, - _SD_DHCP_LEASE_SERVER_TYPE_INVALID = -1, -} sd_dhcp_lease_server_type; - -int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr); -int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); -int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); -int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2); -int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr); -int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr); -int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); -int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); -int sd_dhcp_lease_get_servers(sd_dhcp_lease *lease, sd_dhcp_lease_server_type what, const struct in_addr **addr); -int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr); -int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); -int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); -int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); -int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); -int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); -int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes); -int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); -int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); -int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); - -int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination); -int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length); -int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway); -int sd_dhcp_route_get_option(sd_dhcp_route *route); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-dhcp-option.h b/src/core/systemd/src/systemd/sd-dhcp-option.h deleted file mode 100644 index 71aa479b..00000000 --- a/src/core/systemd/src/systemd/sd-dhcp-option.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosddhcpoptionhfoo -#define foosddhcpoptionhfoo - -/*** - Copyright © 2013 Intel Corporation. All rights reserved. - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -typedef struct sd_dhcp_option sd_dhcp_option; - -int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret); -sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra); -sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-dhcp6-client.h b/src/core/systemd/src/systemd/sd-dhcp6-client.h deleted file mode 100644 index 75ee27d6..00000000 --- a/src/core/systemd/src/systemd/sd-dhcp6-client.h +++ /dev/null @@ -1,180 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosddhcp6clienthfoo -#define foosddhcp6clienthfoo - -/*** - Copyright © 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include - -#include "sd-dhcp6-lease.h" -#include "sd-dhcp6-option.h" -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -enum { - SD_DHCP6_CLIENT_EVENT_STOP = 0, - SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE = 10, - SD_DHCP6_CLIENT_EVENT_RETRANS_MAX = 11, - SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE = 12, - SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST = 13, -}; - -enum { - SD_DHCP6_OPTION_CLIENTID = 1, - SD_DHCP6_OPTION_SERVERID = 2, - SD_DHCP6_OPTION_IA_NA = 3, - SD_DHCP6_OPTION_IA_TA = 4, - SD_DHCP6_OPTION_IAADDR = 5, - SD_DHCP6_OPTION_ORO = 6, - SD_DHCP6_OPTION_PREFERENCE = 7, - SD_DHCP6_OPTION_ELAPSED_TIME = 8, - SD_DHCP6_OPTION_RELAY_MSG = 9, - /* option code 10 is unassigned */ - SD_DHCP6_OPTION_AUTH = 11, - SD_DHCP6_OPTION_UNICAST = 12, - SD_DHCP6_OPTION_STATUS_CODE = 13, - SD_DHCP6_OPTION_RAPID_COMMIT = 14, - SD_DHCP6_OPTION_USER_CLASS = 15, - SD_DHCP6_OPTION_VENDOR_CLASS = 16, - SD_DHCP6_OPTION_VENDOR_OPTS = 17, - SD_DHCP6_OPTION_INTERFACE_ID = 18, - SD_DHCP6_OPTION_RECONF_MSG = 19, - SD_DHCP6_OPTION_RECONF_ACCEPT = 20, - - SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */ - SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */ - SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, prefix delegation */ - SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ - - SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ - SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 8415, sec. 21.23 */ - - /* option code 35 is unassigned */ - - SD_DHCP6_OPTION_FQDN = 39, /* RFC 4704 */ - - SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */ - SD_DHCP6_OPTION_MUD_URL = 112, /* RFC 8250 */ - - /* option codes 89-142 are unassigned */ - /* option codes 144-65535 are unassigned */ -}; - -typedef struct sd_dhcp6_client sd_dhcp6_client; - -typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata); -int sd_dhcp6_client_set_callback( - sd_dhcp6_client *client, - sd_dhcp6_client_callback_t cb, - void *userdata); - -int sd_dhcp6_client_set_ifindex( - sd_dhcp6_client *client, - int interface_index); -int sd_dhcp6_client_set_local_address( - sd_dhcp6_client *client, - const struct in6_addr *local_address); -int sd_dhcp6_client_set_mac( - sd_dhcp6_client *client, - const uint8_t *addr, - size_t addr_len, - uint16_t arp_type); -int sd_dhcp6_client_set_duid( - sd_dhcp6_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len); -int sd_dhcp6_client_set_duid_llt( - sd_dhcp6_client *client, - uint64_t llt_time); -int sd_dhcp6_client_set_iaid( - sd_dhcp6_client *client, - uint32_t iaid); -int sd_dhcp6_client_get_iaid( - sd_dhcp6_client *client, - uint32_t *iaid); -int sd_dhcp6_client_duid_as_string( - sd_dhcp6_client *client, - char **duid); -int sd_dhcp6_client_set_fqdn( - sd_dhcp6_client *client, - const char *fqdn); -int sd_dhcp6_client_set_information_request( - sd_dhcp6_client *client, - int enabled); -int sd_dhcp6_client_get_information_request( - sd_dhcp6_client *client, - int *enabled); -int sd_dhcp6_client_set_request_option( - sd_dhcp6_client *client, - uint16_t option); -int sd_dhcp6_client_set_request_mud_url( - sd_dhcp6_client *client, - const char *mudurl); -int sd_dhcp6_client_set_request_user_class( - sd_dhcp6_client *client, - char** user_class); -int sd_dhcp6_client_set_request_vendor_class( - sd_dhcp6_client *client, - char** vendor_class); -int sd_dhcp6_client_set_prefix_delegation_hint( - sd_dhcp6_client *client, - uint8_t prefixlen, - const struct in6_addr *pd_address); -int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, - int *delegation); -int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, - int delegation); -int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, - int *request); -int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, - int request); -int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, - uint32_t transaction_id); -int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client, - sd_dhcp6_option *v); - -int sd_dhcp6_client_get_lease( - sd_dhcp6_client *client, - sd_dhcp6_lease **ret); - -int sd_dhcp6_client_add_option(sd_dhcp6_client *client, sd_dhcp6_option *v); - -int sd_dhcp6_client_stop(sd_dhcp6_client *client); -int sd_dhcp6_client_start(sd_dhcp6_client *client); -int sd_dhcp6_client_is_running(sd_dhcp6_client *client); -int sd_dhcp6_client_attach_event( - sd_dhcp6_client *client, - sd_event *event, - int64_t priority); -int sd_dhcp6_client_detach_event(sd_dhcp6_client *client); -sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client); -sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client); -sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client); -int sd_dhcp6_client_new(sd_dhcp6_client **ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_client, sd_dhcp6_client_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-dhcp6-lease.h b/src/core/systemd/src/systemd/sd-dhcp6-lease.h deleted file mode 100644 index f77b31ac..00000000 --- a/src/core/systemd/src/systemd/sd-dhcp6-lease.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosddhcp6leasehfoo -#define foosddhcp6leasehfoo - -/*** - Copyright © 2014-2015 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -typedef struct sd_dhcp6_lease sd_dhcp6_lease; - -void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease); -int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, - struct in6_addr *addr, - uint32_t *lifetime_preferred, - uint32_t *lifetime_valid); -void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease); -int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, - uint8_t *prefix_len, - uint32_t *lifetime_preferred, - uint32_t *lifetime_valid); - -int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **addrs); -int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains); -int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **addrs); -int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn); -int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **fqdn); - -sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease); -sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_lease, sd_dhcp6_lease_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-dhcp6-option.h b/src/core/systemd/src/systemd/sd-dhcp6-option.h deleted file mode 100644 index ddb2c7ce..00000000 --- a/src/core/systemd/src/systemd/sd-dhcp6-option.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosddhcp6optionhfoo -#define foosddhcp6optionhfoo - -/*** - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -typedef struct sd_dhcp6_option sd_dhcp6_option; - -int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, uint32_t enterprise_identifier, sd_dhcp6_option **ret); -sd_dhcp6_option *sd_dhcp6_option_ref(sd_dhcp6_option *ra); -sd_dhcp6_option *sd_dhcp6_option_unref(sd_dhcp6_option *ra); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_option, sd_dhcp6_option_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-event.h b/src/core/systemd/src/systemd/sd-event.h deleted file mode 100644 index 2ae2a0da..00000000 --- a/src/core/systemd/src/systemd/sd-event.h +++ /dev/null @@ -1,176 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdeventhfoo -#define foosdeventhfoo - -/*** - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "_sd-common.h" - -/* - Why is this better than pure epoll? - - - Supports event source prioritization - - Scales better with a large number of time events because it does not require one timerfd each - - Automatically tries to coalesce timer events system-wide - - Handles signals, child PIDs, inotify events - - Supports systemd-style automatic watchdog event generation -*/ - -_SD_BEGIN_DECLARATIONS; - -#define SD_EVENT_DEFAULT ((sd_event *) 1) - -typedef struct sd_event sd_event; -typedef struct sd_event_source sd_event_source; - -enum { - SD_EVENT_OFF = 0, - SD_EVENT_ON = 1, - SD_EVENT_ONESHOT = -1 -}; - -enum { - SD_EVENT_INITIAL, - SD_EVENT_ARMED, - SD_EVENT_PENDING, - SD_EVENT_RUNNING, - SD_EVENT_EXITING, - SD_EVENT_FINISHED, - SD_EVENT_PREPARING -}; - -enum { - /* And everything in-between and outside is good too */ - SD_EVENT_PRIORITY_IMPORTANT = -100, - SD_EVENT_PRIORITY_NORMAL = 0, - SD_EVENT_PRIORITY_IDLE = 100 -}; - -typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata); -typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata); -typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata); -typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata); -#if defined _GNU_SOURCE || (defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 199309L) -typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata); -#else -typedef void* sd_event_child_handler_t; -#endif -typedef int (*sd_event_inotify_handler_t)(sd_event_source *s, const struct inotify_event *event, void *userdata); -typedef _sd_destroy_t sd_event_destroy_t; - -int sd_event_default(sd_event **e); - -int sd_event_new(sd_event **e); -sd_event* sd_event_ref(sd_event *e); -sd_event* sd_event_unref(sd_event *e); - -int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata); -int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); -int sd_event_add_time_relative(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); -int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); -int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); -int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata); -int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata); -int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); -int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); -int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); - -int sd_event_prepare(sd_event *e); -int sd_event_wait(sd_event *e, uint64_t usec); -int sd_event_dispatch(sd_event *e); -int sd_event_run(sd_event *e, uint64_t usec); -int sd_event_loop(sd_event *e); -int sd_event_exit(sd_event *e, int code); - -int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec); - -int sd_event_get_fd(sd_event *e); -int sd_event_get_state(sd_event *e); -int sd_event_get_tid(sd_event *e, pid_t *tid); -int sd_event_get_exit_code(sd_event *e, int *code); -int sd_event_set_watchdog(sd_event *e, int b); -int sd_event_get_watchdog(sd_event *e); -int sd_event_get_iteration(sd_event *e, uint64_t *ret); - -sd_event_source* sd_event_source_ref(sd_event_source *s); -sd_event_source* sd_event_source_unref(sd_event_source *s); -sd_event_source* sd_event_source_disable_unref(sd_event_source *s); - -sd_event *sd_event_source_get_event(sd_event_source *s); -void* sd_event_source_get_userdata(sd_event_source *s); -void* sd_event_source_set_userdata(sd_event_source *s, void *userdata); - -int sd_event_source_set_description(sd_event_source *s, const char *description); -int sd_event_source_get_description(sd_event_source *s, const char **description); -int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback); -int sd_event_source_get_pending(sd_event_source *s); -int sd_event_source_get_priority(sd_event_source *s, int64_t *priority); -int sd_event_source_set_priority(sd_event_source *s, int64_t priority); -int sd_event_source_get_enabled(sd_event_source *s, int *enabled); -int sd_event_source_set_enabled(sd_event_source *s, int enabled); -int sd_event_source_get_io_fd(sd_event_source *s); -int sd_event_source_set_io_fd(sd_event_source *s, int fd); -int sd_event_source_get_io_fd_own(sd_event_source *s); -int sd_event_source_set_io_fd_own(sd_event_source *s, int own); -int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events); -int sd_event_source_set_io_events(sd_event_source *s, uint32_t events); -int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); -int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); -int sd_event_source_set_time(sd_event_source *s, uint64_t usec); -int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec); -int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); -int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); -int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); -int sd_event_source_get_signal(sd_event_source *s); -int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); -int sd_event_source_get_child_pidfd(sd_event_source *s); -int sd_event_source_get_child_pidfd_own(sd_event_source *s); -int sd_event_source_set_child_pidfd_own(sd_event_source *s, int own); -int sd_event_source_get_child_process_own(sd_event_source *s); -int sd_event_source_set_child_process_own(sd_event_source *s, int own); -#if defined _GNU_SOURCE || (defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 199309L) -int sd_event_source_send_child_signal(sd_event_source *s, int sig, const siginfo_t *si, unsigned flags); -#else -int sd_event_source_send_child_signal(sd_event_source *s, int sig, const void *si, unsigned flags); -#endif -int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret); -int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback); -int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret); -int sd_event_source_get_floating(sd_event_source *s); -int sd_event_source_set_floating(sd_event_source *s, int b); -int sd_event_source_get_exit_on_failure(sd_event_source *s); -int sd_event_source_set_exit_on_failure(sd_event_source *s, int b); -int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst); -int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst); -int sd_event_source_is_ratelimited(sd_event_source *s); - -/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-id128.h b/src/core/systemd/src/systemd/sd-id128.h deleted file mode 100644 index 02aa318a..00000000 --- a/src/core/systemd/src/systemd/sd-id128.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdid128hfoo -#define foosdid128hfoo - -/*** - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -/* 128-bit ID APIs. See sd-id128(3) for more information. */ - -typedef union sd_id128 sd_id128_t; - -union sd_id128 { - uint8_t bytes[16]; - uint64_t qwords[2]; -}; - -#define SD_ID128_STRING_MAX 33 - -char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]); -int sd_id128_from_string(const char *s, sd_id128_t *ret); - -int sd_id128_randomize(sd_id128_t *ret); - -int sd_id128_get_machine(sd_id128_t *ret); -int sd_id128_get_boot(sd_id128_t *ret); -int sd_id128_get_invocation(sd_id128_t *ret); - -int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret); -int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret); - -#define SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ - { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ - 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }} - -#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ - ((const sd_id128_t) SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)) - -/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16 - * times. It is hence not a good idea to call this macro with an - * expensive function as parameter or an expression with side - * effects */ - -#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" -#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] - -/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */ -#define SD_ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" - -#define SD_ID128_CONST_STR(x) \ - ((const char[SD_ID128_STRING_MAX]) { \ - ((x).bytes[0] >> 4) >= 10 ? 'a' + ((x).bytes[0] >> 4) - 10 : '0' + ((x).bytes[0] >> 4), \ - ((x).bytes[0] & 15) >= 10 ? 'a' + ((x).bytes[0] & 15) - 10 : '0' + ((x).bytes[0] & 15), \ - ((x).bytes[1] >> 4) >= 10 ? 'a' + ((x).bytes[1] >> 4) - 10 : '0' + ((x).bytes[1] >> 4), \ - ((x).bytes[1] & 15) >= 10 ? 'a' + ((x).bytes[1] & 15) - 10 : '0' + ((x).bytes[1] & 15), \ - ((x).bytes[2] >> 4) >= 10 ? 'a' + ((x).bytes[2] >> 4) - 10 : '0' + ((x).bytes[2] >> 4), \ - ((x).bytes[2] & 15) >= 10 ? 'a' + ((x).bytes[2] & 15) - 10 : '0' + ((x).bytes[2] & 15), \ - ((x).bytes[3] >> 4) >= 10 ? 'a' + ((x).bytes[3] >> 4) - 10 : '0' + ((x).bytes[3] >> 4), \ - ((x).bytes[3] & 15) >= 10 ? 'a' + ((x).bytes[3] & 15) - 10 : '0' + ((x).bytes[3] & 15), \ - ((x).bytes[4] >> 4) >= 10 ? 'a' + ((x).bytes[4] >> 4) - 10 : '0' + ((x).bytes[4] >> 4), \ - ((x).bytes[4] & 15) >= 10 ? 'a' + ((x).bytes[4] & 15) - 10 : '0' + ((x).bytes[4] & 15), \ - ((x).bytes[5] >> 4) >= 10 ? 'a' + ((x).bytes[5] >> 4) - 10 : '0' + ((x).bytes[5] >> 4), \ - ((x).bytes[5] & 15) >= 10 ? 'a' + ((x).bytes[5] & 15) - 10 : '0' + ((x).bytes[5] & 15), \ - ((x).bytes[6] >> 4) >= 10 ? 'a' + ((x).bytes[6] >> 4) - 10 : '0' + ((x).bytes[6] >> 4), \ - ((x).bytes[6] & 15) >= 10 ? 'a' + ((x).bytes[6] & 15) - 10 : '0' + ((x).bytes[6] & 15), \ - ((x).bytes[7] >> 4) >= 10 ? 'a' + ((x).bytes[7] >> 4) - 10 : '0' + ((x).bytes[7] >> 4), \ - ((x).bytes[7] & 15) >= 10 ? 'a' + ((x).bytes[7] & 15) - 10 : '0' + ((x).bytes[7] & 15), \ - ((x).bytes[8] >> 4) >= 10 ? 'a' + ((x).bytes[8] >> 4) - 10 : '0' + ((x).bytes[8] >> 4), \ - ((x).bytes[8] & 15) >= 10 ? 'a' + ((x).bytes[8] & 15) - 10 : '0' + ((x).bytes[8] & 15), \ - ((x).bytes[9] >> 4) >= 10 ? 'a' + ((x).bytes[9] >> 4) - 10 : '0' + ((x).bytes[9] >> 4), \ - ((x).bytes[9] & 15) >= 10 ? 'a' + ((x).bytes[9] & 15) - 10 : '0' + ((x).bytes[9] & 15), \ - ((x).bytes[10] >> 4) >= 10 ? 'a' + ((x).bytes[10] >> 4) - 10 : '0' + ((x).bytes[10] >> 4), \ - ((x).bytes[10] & 15) >= 10 ? 'a' + ((x).bytes[10] & 15) - 10 : '0' + ((x).bytes[10] & 15), \ - ((x).bytes[11] >> 4) >= 10 ? 'a' + ((x).bytes[11] >> 4) - 10 : '0' + ((x).bytes[11] >> 4), \ - ((x).bytes[11] & 15) >= 10 ? 'a' + ((x).bytes[11] & 15) - 10 : '0' + ((x).bytes[11] & 15), \ - ((x).bytes[12] >> 4) >= 10 ? 'a' + ((x).bytes[12] >> 4) - 10 : '0' + ((x).bytes[12] >> 4), \ - ((x).bytes[12] & 15) >= 10 ? 'a' + ((x).bytes[12] & 15) - 10 : '0' + ((x).bytes[12] & 15), \ - ((x).bytes[13] >> 4) >= 10 ? 'a' + ((x).bytes[13] >> 4) - 10 : '0' + ((x).bytes[13] >> 4), \ - ((x).bytes[13] & 15) >= 10 ? 'a' + ((x).bytes[13] & 15) - 10 : '0' + ((x).bytes[13] & 15), \ - ((x).bytes[14] >> 4) >= 10 ? 'a' + ((x).bytes[14] >> 4) - 10 : '0' + ((x).bytes[14] >> 4), \ - ((x).bytes[14] & 15) >= 10 ? 'a' + ((x).bytes[14] & 15) - 10 : '0' + ((x).bytes[14] & 15), \ - ((x).bytes[15] >> 4) >= 10 ? 'a' + ((x).bytes[15] >> 4) - 10 : '0' + ((x).bytes[15] >> 4), \ - ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \ - 0 }) - -#define SD_ID128_MAKE_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \ - #a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p - -_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) { - return memcmp(&a, &b, 16) == 0; -} - -_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) { - return a.qwords[0] == 0 && a.qwords[1] == 0; -} - -_sd_pure_ static __inline__ int sd_id128_is_allf(sd_id128_t a) { - return a.qwords[0] == UINT64_C(0xFFFFFFFFFFFFFFFF) && a.qwords[1] == UINT64_C(0xFFFFFFFFFFFFFFFF); -} - -#define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }}) -#define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }}) - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-ipv4acd.h b/src/core/systemd/src/systemd/sd-ipv4acd.h deleted file mode 100644 index 2809d874..00000000 --- a/src/core/systemd/src/systemd/sd-ipv4acd.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdipv4acdfoo -#define foosdipv4acdfoo - -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include - -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -enum { - SD_IPV4ACD_EVENT_STOP = 0, - SD_IPV4ACD_EVENT_BIND = 1, - SD_IPV4ACD_EVENT_CONFLICT = 2, -}; - -typedef struct sd_ipv4acd sd_ipv4acd; -typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *acd, int event, void *userdata); - -int sd_ipv4acd_detach_event(sd_ipv4acd *acd); -int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority); -int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address); -int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata); -int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr); -int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index); -int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd); -const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd); -int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address); -int sd_ipv4acd_is_running(sd_ipv4acd *acd); -int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts); -int sd_ipv4acd_stop(sd_ipv4acd *acd); -sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd); -sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd); -int sd_ipv4acd_new(sd_ipv4acd **ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-ipv4ll.h b/src/core/systemd/src/systemd/sd-ipv4ll.h deleted file mode 100644 index aa4d174e..00000000 --- a/src/core/systemd/src/systemd/sd-ipv4ll.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdipv4llfoo -#define foosdipv4llfoo - -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -enum { - SD_IPV4LL_EVENT_STOP = 0, - SD_IPV4LL_EVENT_BIND = 1, - SD_IPV4LL_EVENT_CONFLICT = 2, -}; - -typedef struct sd_ipv4ll sd_ipv4ll; -typedef void (*sd_ipv4ll_callback_t)(sd_ipv4ll *ll, int event, void *userdata); - -int sd_ipv4ll_detach_event(sd_ipv4ll *ll); -int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority); -int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); -int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata); -int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); -int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index); -int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll); -const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll); -int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); -int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed); -int sd_ipv4ll_is_running(sd_ipv4ll *ll); -int sd_ipv4ll_restart(sd_ipv4ll *ll); -int sd_ipv4ll_start(sd_ipv4ll *ll); -int sd_ipv4ll_stop(sd_ipv4ll *ll); -sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll); -sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll); -int sd_ipv4ll_new(sd_ipv4ll **ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-lldp.h b/src/core/systemd/src/systemd/sd-lldp.h deleted file mode 100644 index f551f6b4..00000000 --- a/src/core/systemd/src/systemd/sd-lldp.h +++ /dev/null @@ -1,194 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdlldphfoo -#define foosdlldphfoo - -/*** - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include - -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -/* IEEE 802.1AB-2009 Clause 8: TLV Types */ -enum { - SD_LLDP_TYPE_END = 0, - SD_LLDP_TYPE_CHASSIS_ID = 1, - SD_LLDP_TYPE_PORT_ID = 2, - SD_LLDP_TYPE_TTL = 3, - SD_LLDP_TYPE_PORT_DESCRIPTION = 4, - SD_LLDP_TYPE_SYSTEM_NAME = 5, - SD_LLDP_TYPE_SYSTEM_DESCRIPTION = 6, - SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7, - SD_LLDP_TYPE_MGMT_ADDRESS = 8, - SD_LLDP_TYPE_PRIVATE = 127, -}; - -/* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */ -enum { - SD_LLDP_CHASSIS_SUBTYPE_RESERVED = 0, - SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1, - SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2, - SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3, - SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4, - SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5, - SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6, - SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7, -}; - -/* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */ -enum { - SD_LLDP_PORT_SUBTYPE_RESERVED = 0, - SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1, - SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2, - SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3, - SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4, - SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5, - SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6, - SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7, -}; - -/* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */ -enum { - SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0, - SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1, - SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2, - SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3, - SD_LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4, - SD_LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5, - SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6, - SD_LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7, - SD_LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8, - SD_LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9, - SD_LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10, -}; - -#define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1) - -#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS \ - ((uint16_t) \ - (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER| \ - SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE| \ - SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP| \ - SD_LLDP_SYSTEM_CAPABILITIES_ROUTER| \ - SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS| \ - SD_LLDP_SYSTEM_CAPABILITIES_CVLAN| \ - SD_LLDP_SYSTEM_CAPABILITIES_SVLAN| \ - SD_LLDP_SYSTEM_CAPABILITIES_TPMR)) - -#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 } -#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f } - -#define SD_LLDP_OUI_MUD (uint8_t[]) { 0x00, 0x00, 0x5E } -#define SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION 0x01 - -/* IEEE 802.1AB-2009 Annex E */ -enum { - SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1, - SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2, - SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3, - SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4, - SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5, - SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6, - SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7, -}; - -/* IEEE 802.1AB-2009 Annex F */ -enum { - SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1, - SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI = 2, - SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION = 3, - SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE = 4, -}; - -typedef struct sd_lldp sd_lldp; -typedef struct sd_lldp_neighbor sd_lldp_neighbor; - -typedef enum sd_lldp_event { - SD_LLDP_EVENT_ADDED, - SD_LLDP_EVENT_REMOVED, - SD_LLDP_EVENT_UPDATED, - SD_LLDP_EVENT_REFRESHED, - _SD_LLDP_EVENT_MAX, - _SD_LLDP_EVENT_INVALID = -1, -} sd_lldp_event; - -typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata); - -int sd_lldp_new(sd_lldp **ret); -sd_lldp* sd_lldp_ref(sd_lldp *lldp); -sd_lldp* sd_lldp_unref(sd_lldp *lldp); - -int sd_lldp_start(sd_lldp *lldp); -int sd_lldp_stop(sd_lldp *lldp); - -int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority); -int sd_lldp_detach_event(sd_lldp *lldp); -sd_event *sd_lldp_get_event(sd_lldp *lldp); - -int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata); -int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex); - -/* Controls how much and what to store in the neighbors database */ -int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n); -int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask); -int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *address); - -int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***neighbors); - -int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size); -sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n); -sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n); - -/* Access to LLDP frame metadata */ -int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address); -int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address); -int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret); -int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); - -/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */ -int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size); -int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret); -int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size); -int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret); -int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec); -int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret); -int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret); -int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret); -int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret); -int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret); -int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret); - -/* Low-level, iterative TLV access. This is for everything else, it iteratively goes through all available TLVs - * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */ -int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n); -int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n); -int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type); -int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type); -int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype); -int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype); -int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/systemd/src/systemd/sd-ndisc.h b/src/core/systemd/src/systemd/sd-ndisc.h deleted file mode 100644 index c0e37899..00000000 --- a/src/core/systemd/src/systemd/sd-ndisc.h +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdndiscfoo -#define foosdndiscfoo - -/*** - Copyright © 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include - -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -/* Neighbor Discovery Options, RFC 4861, Section 4.6 and - * https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 */ -enum { - SD_NDISC_OPTION_SOURCE_LL_ADDRESS = 1, - SD_NDISC_OPTION_TARGET_LL_ADDRESS = 2, - SD_NDISC_OPTION_PREFIX_INFORMATION = 3, - SD_NDISC_OPTION_MTU = 5, - SD_NDISC_OPTION_ROUTE_INFORMATION = 24, - SD_NDISC_OPTION_RDNSS = 25, - SD_NDISC_OPTION_FLAGS_EXTENSION = 26, - SD_NDISC_OPTION_DNSSL = 31, - SD_NDISC_OPTION_CAPTIVE_PORTAL = 37, -}; - -/* Route preference, RFC 4191, Section 2.1 */ -enum { - SD_NDISC_PREFERENCE_LOW = 3U, - SD_NDISC_PREFERENCE_MEDIUM = 0U, - SD_NDISC_PREFERENCE_HIGH = 1U, -}; - -typedef struct sd_ndisc sd_ndisc; -typedef struct sd_ndisc_router sd_ndisc_router; - -typedef enum sd_ndisc_event { - SD_NDISC_EVENT_TIMEOUT, - SD_NDISC_EVENT_ROUTER, - _SD_NDISC_EVENT_MAX, - _SD_NDISC_EVENT_INVALID = -1, -} sd_ndisc_event; - -typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata); - -int sd_ndisc_new(sd_ndisc **ret); -sd_ndisc *sd_ndisc_ref(sd_ndisc *nd); -sd_ndisc *sd_ndisc_unref(sd_ndisc *nd); - -int sd_ndisc_start(sd_ndisc *nd); -int sd_ndisc_stop(sd_ndisc *nd); - -int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority); -int sd_ndisc_detach_event(sd_ndisc *nd); -sd_event *sd_ndisc_get_event(sd_ndisc *nd); - -int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb, void *userdata); -int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index); -int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); - -int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *ret); -int sd_ndisc_get_hop_limit(sd_ndisc *nd, uint8_t *ret); - -int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size); -sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt); -sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt); - -int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr); -int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); -int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size); - -int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret); -int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret_flags); -int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret); -int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint16_t *ret_lifetime); -int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret); - -/* Generic option access */ -int sd_ndisc_router_option_rewind(sd_ndisc_router *rt); -int sd_ndisc_router_option_next(sd_ndisc_router *rt); -int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret); -int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type); -int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size); - -/* Specific option access: SD_NDISC_OPTION_PREFIX_INFORMATION */ -int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint32_t *ret); -int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint32_t *ret); -int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret); -int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr); -int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen); - -/* Specific option access: SD_NDISC_OPTION_ROUTE_INFORMATION */ -int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint32_t *ret); -int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr); -int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen); -int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret); - -/* Specific option access: SD_NDISC_OPTION_RDNSS */ -int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret); -int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint32_t *ret); - -/* Specific option access: SD_NDISC_OPTION_DNSSL */ -int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret); -int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router, sd_ndisc_router_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/core/tests/config/test-config.c b/src/core/tests/config/test-config.c index 3bb14815..6794fbf6 100644 --- a/src/core/tests/config/test-config.c +++ b/src/core/tests/config/test-config.c @@ -151,6 +151,7 @@ test_config_simple(void) gs_unref_object NMConfig *config = NULL; gs_strfreev char ** plugins = NULL; char * value; + const char * cvalue; gs_unref_object NMDevice *dev50 = nm_test_device_new("00:00:00:00:00:50"); gs_unref_object NMDevice *dev51 = nm_test_device_new("00:00:00:00:00:51"); gs_unref_object NMDevice *dev52 = nm_test_device_new("00:00:00:00:00:52"); @@ -206,59 +207,50 @@ test_config_simple(void) g_assert_cmpstr(value, ==, "51"); g_free(value); - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv6.route-metric", - NULL); - g_assert_cmpstr(value, ==, NULL); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv4.route-metric", - NULL); - g_assert_cmpstr(value, ==, "50"); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv4.route-metric", - dev50); - g_assert_cmpstr(value, ==, "50"); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv4.route-metric", - dev51); - g_assert_cmpstr(value, ==, "51"); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv4.route-metric", - dev52); - g_assert_cmpstr(value, ==, "52"); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ethernet.mtu", - dev51); - g_assert_cmpstr(value, ==, "9000"); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ethernet.mtu", - dev50); - g_assert_cmpstr(value, ==, "1400"); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv4.dns-priority", - dev51); - g_assert_cmpstr(value, ==, NULL); - g_free(value); - - value = nm_config_data_get_connection_default(nm_config_get_data_orig(config), - "ipv4.dns-priority", - dev50); - g_assert_cmpstr(value, ==, "60"); - g_free(value); + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv6.route-metric", + NULL); + g_assert_cmpstr(cvalue, ==, NULL); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv4.route-metric", + NULL); + g_assert_cmpstr(cvalue, ==, "50"); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv4.route-metric", + dev50); + g_assert_cmpstr(cvalue, ==, "50"); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv4.route-metric", + dev51); + g_assert_cmpstr(cvalue, ==, "51"); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv4.route-metric", + dev52); + g_assert_cmpstr(cvalue, ==, "52"); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ethernet.mtu", + dev51); + g_assert_cmpstr(cvalue, ==, "9000"); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ethernet.mtu", + dev50); + g_assert_cmpstr(cvalue, ==, "1400"); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv4.dns-priority", + dev51); + g_assert_cmpstr(cvalue, ==, NULL); + + cvalue = nm_config_data_get_connection_default(nm_config_get_data_orig(config), + "ipv4.dns-priority", + dev50); + g_assert_cmpstr(cvalue, ==, "60"); } static void @@ -616,7 +608,7 @@ test_config_confdir(void) #define ASSERT_GET_CONN_DEFAULT(xconfig, xname, xvalue) \ G_STMT_START \ { \ - gs_free char *_value = \ + const char *_value = \ nm_config_data_get_connection_default(nm_config_get_data_orig(xconfig), \ (xname), \ NULL); \ diff --git a/src/core/tests/meson.build b/src/core/tests/meson.build index 994563c4..99fa0ae9 100644 --- a/src/core/tests/meson.build +++ b/src/core/tests/meson.build @@ -37,11 +37,17 @@ exe = executable( src_inc, ], dependencies: [ - libnm_systemd_core_dep, - libnm_systemd_shared_dep, + libnm_systemd_shared_dep_inc, + libnm_systemd_core_dep_inc, + glib_dep, ], - c_args: [ - '-DG_LOG_DOMAIN="test"', + link_with: [ + libnm_systemd_shared, + libnm_systemd_core, + libnm_glib_aux, + libnm_log_null, + libnm_std_aux, + libc_siphash, ], ) diff --git a/src/core/tests/test-core-with-expect.c b/src/core/tests/test-core-with-expect.c index 022cf8f3..01784863 100644 --- a/src/core/tests/test-core-with-expect.c +++ b/src/core/tests/test-core-with-expect.c @@ -11,6 +11,7 @@ #include #include "NetworkManagerUtils.h" +#include "libnm-platform/nm-platform-utils.h" #include "nm-test-utils-core.h" @@ -586,7 +587,7 @@ test_nm_ethernet_address_is_valid(void) /*****************************************************************************/ static void -test_nm_utils_new_vlan_name(void) +test_nmp_utils_new_vlan_name(void) { guint i, j; const char *parent_names[] = { @@ -614,7 +615,7 @@ test_nm_utils_new_vlan_name(void) vlan_id_s = g_strdup_printf(".%d", vlan_id); - ifname = nm_utils_new_vlan_name(parent_names[i], vlan_id); + ifname = nmp_utils_new_vlan_name(parent_names[i], vlan_id); g_assert(ifname && ifname[0]); g_assert_cmpint(strlen(ifname), ==, @@ -643,7 +644,7 @@ main(int argc, char **argv) g_test_add_func("/general/nm_utils_array_remove_at_indexes", test_nm_utils_array_remove_at_indexes); g_test_add_func("/general/nm_ethernet_address_is_valid", test_nm_ethernet_address_is_valid); - g_test_add_func("/general/nm_utils_new_vlan_name", test_nm_utils_new_vlan_name); + g_test_add_func("/general/nmp_utils_new_vlan_name", test_nmp_utils_new_vlan_name); return g_test_run(); } diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c index 8698c406..f28c4178 100644 --- a/src/core/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -11,16 +11,36 @@ /* need math.h for isinf() and INFINITY. No need to link with -lm */ #include +#include "libnm-glib-aux/nm-uuid.h" #include "NetworkManagerUtils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-core-utils.h" -#include "systemd/nm-sd-utils-core.h" +#include "libnm-systemd-core/nm-sd-utils-core.h" #include "dns/nm-dns-manager.h" #include "nm-connectivity.h" #include "nm-test-utils-core.h" +/*****************************************************************************/ + +static void +test_config_h(void) +{ +#define ABSOLUTE_PATH(path) \ + G_STMT_START \ + { \ + g_assert_cmpstr("" path "", !=, ""); \ + g_assert("" path ""[0] == '/'); \ + } \ + G_STMT_END + + ABSOLUTE_PATH(IPTABLES_PATH); + ABSOLUTE_PATH(NFT_PATH); +} + +/*****************************************************************************/ + /* Reference implementation for nm_utils_ip6_address_clear_host_address. * Taken originally from set_address_masked(), src/ndisc/nm-lndp-ndisc.c **/ @@ -867,7 +887,7 @@ test_connection_no_match_vlan(void) /* Check that the connections do not match if VLAN flags differ */ s_vlan_orig = nm_connection_get_setting_vlan(orig); g_assert(s_vlan_orig); - g_object_set(G_OBJECT(s_vlan_orig), NM_SETTING_VLAN_FLAGS, NM_VLAN_FLAG_REORDER_HEADERS, NULL); + g_object_set(G_OBJECT(s_vlan_orig), NM_SETTING_VLAN_FLAGS, _NM_VLAN_FLAG_REORDER_HEADERS, NULL); s_vlan_copy = nm_connection_get_setting_vlan(copy); g_assert(s_vlan_copy); @@ -2231,7 +2251,7 @@ test_utils_file_is_in_path(void) g_assert(!nm_utils_file_is_in_path("//b///a/", "/b//")); g_assert(!nm_utils_file_is_in_path("//b///a/", "/b/a/")); g_assert(!nm_utils_file_is_in_path("//b///a", "/b/a/")); - g_assert(nm_utils_file_is_in_path("//b///a/.", "/b/a/")); + g_assert(!nm_utils_file_is_in_path("//b///a/.", "/b/a/")); g_assert(nm_utils_file_is_in_path("//b///a/..", "/b/a/")); } @@ -2569,6 +2589,8 @@ main(int argc, char **argv) { nmtst_init_with_logging(&argc, &argv, NULL, "ALL"); + g_test_add_func("/general/test_config_h", test_config_h); + g_test_add_func("/general/test_logging_domains", test_logging_domains); g_test_add_func("/general/test_logging_error", test_logging_error); diff --git a/src/core/tests/test-ip4-config.c b/src/core/tests/test-ip4-config.c index 27b1d611..3a095d4a 100644 --- a/src/core/tests/test-ip4-config.c +++ b/src/core/tests/test-ip4-config.c @@ -8,7 +8,7 @@ #include #include "nm-ip4-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-test-utils-core.h" diff --git a/src/core/tests/test-ip6-config.c b/src/core/tests/test-ip6-config.c index 3b48fb7f..ddf4c789 100644 --- a/src/core/tests/test-ip6-config.c +++ b/src/core/tests/test-ip6-config.c @@ -10,7 +10,7 @@ #include "nm-ip6-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-test-utils-core.h" static NMIP6Config * diff --git a/src/core/tests/test-l3cfg.c b/src/core/tests/test-l3cfg.c index 43132c6d..ba065c09 100644 --- a/src/core/tests/test-l3cfg.c +++ b/src/core/tests/test-l3cfg.c @@ -5,7 +5,7 @@ #include "nm-l3cfg.h" #include "nm-l3-ipv4ll.h" #include "nm-netns.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "platform/tests/test-common.h" @@ -82,8 +82,8 @@ _test_fixture_1_setup(TestFixture1 *f, int test_idx) f->hwaddr0 = l0->l_address; f->hwaddr1 = l1->l_address; - g_assert(nm_platform_link_set_up(f->platform, f->ifindex0, NULL)); - g_assert(nm_platform_link_set_up(f->platform, f->ifindex1, NULL)); + g_assert(nm_platform_link_change_flags(f->platform, f->ifindex0, IFF_UP, TRUE) >= 0); + g_assert(nm_platform_link_change_flags(f->platform, f->ifindex1, IFF_UP, TRUE) >= 0); return f; } @@ -187,6 +187,12 @@ _test_l3cfg_signal_notify(NML3Cfg * l3cfg, nm_assert(NM_IS_L3_CONFIG_DATA(ti->l3cd)); nm_assert(ti->tag); } + } else if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED) { + g_assert(!notify_data->l3cd_changed.l3cd_old + || NM_IS_L3_CONFIG_DATA(notify_data->l3cd_changed.l3cd_old)); + g_assert(!notify_data->l3cd_changed.l3cd_new + || NM_IS_L3_CONFIG_DATA(notify_data->l3cd_changed.l3cd_new)); + return; } switch (tdata->notify_type) { diff --git a/src/core/tests/test-systemd.c b/src/core/tests/test-systemd.c index fa510366..12d2b911 100644 --- a/src/core/tests/test-systemd.c +++ b/src/core/tests/test-systemd.c @@ -3,68 +3,12 @@ * Copyright (C) 2016 Red Hat, Inc. */ -#include "src/core/systemd/nm-default-systemd.h" +#include "libnm-systemd-core/nm-default-systemd-core.h" -#include "systemd/nm-sd.h" -#include "systemd/nm-sd-utils-shared.h" +#include "libnm-systemd-core/nm-sd.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" -#include "nm-test-utils-core.h" - -/***************************************************************************** - * Stub implementations of libNetworkManagerBase symbols - *****************************************************************************/ - -gboolean -nm_utils_get_testing_initialized(void) -{ - return TRUE; -} - -void -_nm_utils_set_testing(NMUtilsTestFlags flags) -{ - g_assert_not_reached(); -} - -gint32 -nm_utils_get_monotonic_timestamp_sec(void) -{ - return 1; -} - -NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL]; - -gboolean -_nm_log_enabled_impl(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain) -{ - return FALSE; -} - -void -_nm_log_impl(const char *file, - guint line, - const char *func, - gboolean mt_require_locking, - NMLogLevel level, - NMLogDomain domain, - int error, - const char *ifname, - const char *con_uuid, - const char *fmt, - ...) -{} - -gboolean -nm_logging_setup(const char *level, const char *domains, char **bad_domains, GError **error) -{ - return TRUE; -} - -const char * -nm_strerror_native(int errsv) -{ - return g_strerror(errsv); -} +#include "libnm-glib-aux/nm-test-utils.h" /*****************************************************************************/ @@ -178,46 +122,34 @@ test_sd_event(void) static void test_path_equal(void) { -#define _path_equal_check1(path, kill_dots, expected) \ - G_STMT_START \ - { \ - const gboolean _kill_dots = (kill_dots); \ - const char * _path0 = (path); \ - const char * _expected = (expected); \ - gs_free char * _path = g_strdup(_path0); \ - const char * _path_result; \ - \ - if (!_kill_dots && !nm_sd_utils_path_equal(_path0, _expected)) \ - g_error("Paths \"%s\" and \"%s\" don't compare equal", _path0, _expected); \ - \ - _path_result = nm_sd_utils_path_simplify(_path, _kill_dots); \ - g_assert(_path_result == _path); \ - g_assert_cmpstr(_path, ==, _expected); \ - } \ - G_STMT_END - -#define _path_equal_check(path, expected_no_kill_dots, expected_kill_dots) \ - G_STMT_START \ - { \ - _path_equal_check1(path, FALSE, expected_no_kill_dots); \ - _path_equal_check1(path, TRUE, expected_kill_dots ?: expected_no_kill_dots); \ - } \ +#define _path_equal_check(path, expected) \ + G_STMT_START \ + { \ + const char * _path0 = (path); \ + const char * _expected = (expected); \ + gs_free char *_path = g_strdup(_path0); \ + const char * _path_result; \ + \ + _path_result = nm_sd_utils_path_simplify(_path); \ + g_assert(_path_result == _path); \ + g_assert_cmpstr(_path, ==, _expected); \ + } \ G_STMT_END - _path_equal_check("", "", NULL); - _path_equal_check(".", ".", NULL); - _path_equal_check("..", "..", NULL); - _path_equal_check("/..", "/..", NULL); - _path_equal_check("//..", "/..", NULL); - _path_equal_check("/.", "/.", "/"); - _path_equal_check("./", ".", "."); - _path_equal_check("./.", "./.", "."); - _path_equal_check(".///.", "./.", "."); - _path_equal_check(".///./", "./.", "."); - _path_equal_check(".////", ".", "."); - _path_equal_check("//..//foo/", "/../foo", NULL); - _path_equal_check("///foo//./bar/.", "/foo/./bar/.", "/foo/bar"); - _path_equal_check(".//./foo//./bar/.", "././foo/./bar/.", "foo/bar"); + _path_equal_check("", ""); + _path_equal_check(".", "."); + _path_equal_check("..", ".."); + _path_equal_check("/..", "/.."); + _path_equal_check("//..", "/.."); + _path_equal_check("/.", "/"); + _path_equal_check("./", "."); + _path_equal_check("./.", "."); + _path_equal_check(".///.", "."); + _path_equal_check(".///./", "."); + _path_equal_check(".////", "."); + _path_equal_check("//..//foo/", "/../foo"); + _path_equal_check("///foo//./bar/.", "/foo/bar"); + _path_equal_check(".//./foo//./bar/.", "foo/bar"); } /*****************************************************************************/ @@ -327,7 +259,7 @@ NMTST_DEFINE(); int main(int argc, char **argv) { - nmtst_init_assert_logging(&argc, &argv, "INFO", "ALL"); + nmtst_init(&argc, &argv, TRUE); g_test_add_func("/systemd/dhcp/create", test_dhcp_create); g_test_add_func("/systemd/lldp/create", test_lldp_create); diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index 02831b08..d06ca46a 100644 --- a/src/core/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -14,21 +14,22 @@ #include #include #include +#include #include #include "nm-proxy-config.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" -#include "platform/nm-platform.h" +#include "libnm-platform/nm-platform.h" #include "nm-active-connection.h" #include "NetworkManagerUtils.h" #include "settings/nm-settings-connection.h" #include "nm-dispatcher.h" #include "nm-netns.h" #include "settings/nm-agent-manager.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" #include "nm-pacrunner-manager.h" -#include "nm-firewall-manager.h" +#include "nm-firewalld-manager.h" #include "nm-config.h" #include "nm-vpn-plugin-info.h" #include "nm-vpn-manager.h" @@ -95,7 +96,7 @@ typedef struct { NMVpnPluginInfo * plugin_info; char * bus_name; - NMFirewallManagerCallId *fw_call; + NMFirewalldManagerCallId *fw_call; NMNetns *netns; @@ -341,7 +342,7 @@ fw_call_cleanup(NMVpnConnection *self) NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self); if (priv->fw_call) { - nm_firewall_manager_cancel_call(priv->fw_call); + nm_firewalld_manager_cancel_call(priv->fw_call); g_warn_if_fail(!priv->fw_call); priv->fw_call = NULL; } @@ -371,7 +372,7 @@ vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev) if (priv->ip_ifindex) { NMPlatform *platform = nm_netns_get_platform(priv->netns); - nm_platform_link_set_down(platform, priv->ip_ifindex); + nm_platform_link_change_flags(platform, priv->ip_ifindex, IFF_UP, FALSE); nm_platform_ip_route_flush(platform, AF_UNSPEC, priv->ip_ifindex); nm_platform_ip_address_flush(platform, AF_UNSPEC, priv->ip_ifindex); } @@ -380,11 +381,11 @@ vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev) /* Remove zone from firewall */ if (priv->ip_iface) { - nm_firewall_manager_remove_from_zone(nm_firewall_manager_get(), - priv->ip_iface, - NULL, - NULL, - NULL); + nm_firewalld_manager_remove_from_zone(nm_firewalld_manager_get(), + priv->ip_iface, + NULL, + NULL, + NULL); } /* Cancel pending firewall call */ fw_call_cleanup(self); @@ -398,11 +399,6 @@ vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev) g_free(priv->bus_name); priv->bus_name = NULL; - - /* Clear out connection secrets to ensure that the settings service - * gets asked for them next time the connection is activated. - */ - nm_active_connection_clear_secrets(NM_ACTIVE_CONNECTION(self)); } static void @@ -964,11 +960,6 @@ plugin_state_changed(NMVpnConnection *self, NMVpnServiceState new_service_state) priv->service_state = new_service_state; if (new_service_state == NM_VPN_SERVICE_STATE_STOPPED) { - /* Clear connection secrets to ensure secrets get requested each time the - * connection is activated. - */ - nm_active_connection_clear_secrets(NM_ACTIVE_CONNECTION(self)); - if ((priv->vpn_state >= STATE_WAITING) && (priv->vpn_state <= STATE_ACTIVATED)) { VpnState old_state = priv->vpn_state; @@ -1157,7 +1148,10 @@ nm_vpn_connection_apply_config(NMVpnConnection *self) apply_parent_device_config(self); if (priv->ip_ifindex > 0) { - nm_platform_link_set_up(nm_netns_get_platform(priv->netns), priv->ip_ifindex, NULL); + nm_platform_link_change_flags(nm_netns_get_platform(priv->netns), + priv->ip_ifindex, + IFF_UP, + TRUE); if (priv->ip4_config) { nm_assert(priv->ip_ifindex == nm_ip4_config_get_ifindex(priv->ip4_config)); @@ -1211,10 +1205,10 @@ _cleanup_failed_config(NMVpnConnection *self) } static void -fw_change_zone_cb(NMFirewallManager * firewall_manager, - NMFirewallManagerCallId *call_id, - GError * error, - gpointer user_data) +fw_change_zone_cb(NMFirewalldManager * firewalld_manager, + NMFirewalldManagerCallId *call_id, + GError * error, + gpointer user_data) { NMVpnConnection * self = user_data; NMVpnConnectionPrivate *priv; @@ -1270,12 +1264,12 @@ nm_vpn_connection_config_maybe_complete(NMVpnConnection *self, gboolean success) NM_PRINT_FMT_QUOTED(zone, "'", zone, "'", "(default)"), priv->ip_iface); fw_call_cleanup(self); - priv->fw_call = nm_firewall_manager_add_or_change_zone(nm_firewall_manager_get(), - priv->ip_iface, - zone, - FALSE, - fw_change_zone_cb, - self); + priv->fw_call = nm_firewalld_manager_add_or_change_zone(nm_firewalld_manager_get(), + priv->ip_iface, + zone, + FALSE, + fw_change_zone_cb, + self); return; } else if (nm_vpn_connection_apply_config(self)) return; @@ -1632,7 +1626,7 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict) route.metric = route_metric; route.rt_source = NM_IP_CONFIG_SOURCE_VPN; - if (plen > 32 || plen == 0) + if (plen > 32) break; route.plen = plen; route.network = nm_utils_ip4_address_clear_host_address(route.network, plen); @@ -1825,7 +1819,7 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict) if (!ip6_addr_from_variant(dest, &route.network)) goto next; - if (prefix > 128 || prefix == 0) + if (prefix > 128) goto next; route.plen = prefix; @@ -2912,16 +2906,14 @@ static const GDBusSignalInfo signal_info_vpn_state_changed = NM_DEFINE_GDBUS_SIG static const NMDBusInterfaceInfoExtended interface_info_vpn_connection = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( NM_DBUS_INTERFACE_VPN_CONNECTION, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_vpn_state_changed, ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_vpn_state_changed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("VpnState", - "u", - NM_VPN_CONNECTION_VPN_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Banner", - "s", - NM_VPN_CONNECTION_BANNER), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("VpnState", + "u", + NM_VPN_CONNECTION_VPN_STATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Banner", + "s", + NM_VPN_CONNECTION_BANNER), ), ), }; static void diff --git a/src/core/vpn/nm-vpn-connection.h b/src/core/vpn/nm-vpn-connection.h index 66ec7eec..0209ea3d 100644 --- a/src/core/vpn/nm-vpn-connection.h +++ b/src/core/vpn/nm-vpn-connection.h @@ -9,7 +9,7 @@ #include "nm-vpn-dbus-interface.h" #include "devices/nm-device.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-active-connection.h" #include "nm-vpn-plugin-info.h" diff --git a/src/core/vpn/nm-vpn-manager.c b/src/core/vpn/nm-vpn-manager.c index 53fe58dd..f30dba79 100644 --- a/src/core/vpn/nm-vpn-manager.c +++ b/src/core/vpn/nm-vpn-manager.c @@ -12,7 +12,7 @@ #include "nm-vpn-connection.h" #include "nm-setting-vpn.h" #include "nm-vpn-dbus-interface.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" typedef struct { GSList * plugins; -- cgit 1.3.0-6-gf8a5 From 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 13 Jan 2022 22:30:39 +0100 Subject: New upstream version 1.34.0 --- src/core/NetworkManagerUtils.c | 72 +- src/core/NetworkManagerUtils.h | 64 +- src/core/devices/adsl/nm-device-adsl.c | 2 +- src/core/devices/bluetooth/nm-bluez-manager.c | 163 +- src/core/devices/bluetooth/nm-bluez5-dun.c | 44 +- src/core/devices/bluetooth/nm-device-bt.c | 31 +- src/core/devices/bluetooth/tests/nm-bt-test.c | 2 - src/core/devices/nm-acd-manager.c | 8 +- src/core/devices/nm-device-6lowpan.c | 8 +- src/core/devices/nm-device-bond.c | 99 +- src/core/devices/nm-device-bridge.c | 22 +- src/core/devices/nm-device-dummy.c | 36 +- src/core/devices/nm-device-ethernet.c | 36 +- src/core/devices/nm-device-infiniband.c | 21 +- src/core/devices/nm-device-ip-tunnel.c | 13 +- src/core/devices/nm-device-logging.h | 12 +- src/core/devices/nm-device-macvlan.c | 13 +- src/core/devices/nm-device-ppp.c | 57 +- src/core/devices/nm-device-private.h | 2 +- src/core/devices/nm-device-tun.c | 7 +- src/core/devices/nm-device-utils.c | 27 +- src/core/devices/nm-device-utils.h | 16 +- src/core/devices/nm-device-vlan.c | 8 +- src/core/devices/nm-device-vrf.c | 8 +- src/core/devices/nm-device-vxlan.c | 12 +- src/core/devices/nm-device-wireguard.c | 11 +- src/core/devices/nm-device-wpan.c | 9 +- src/core/devices/nm-device.c | 776 ++-- src/core/devices/nm-device.h | 1 + src/core/devices/nm-lldp-listener.c | 42 +- src/core/devices/ovs/nm-ovsdb.c | 141 +- src/core/devices/team/nm-device-team.c | 22 +- src/core/devices/wifi/nm-device-iwd.c | 11 +- src/core/devices/wifi/nm-device-olpc-mesh.c | 7 +- src/core/devices/wifi/nm-device-wifi-p2p.c | 44 +- src/core/devices/wifi/nm-device-wifi.c | 23 +- src/core/devices/wifi/nm-wifi-ap.c | 2 +- src/core/devices/wifi/nm-wifi-common.c | 2 +- src/core/devices/wifi/nm-wifi-p2p-peer.c | 18 +- src/core/devices/wifi/nm-wifi-utils.c | 27 +- src/core/devices/wifi/tests/test-devices-wifi.c | 2 +- src/core/devices/wwan/nm-device-modem.c | 22 +- src/core/devices/wwan/nm-modem-broadband.c | 7 +- src/core/devices/wwan/nm-modem-manager.c | 6 +- src/core/devices/wwan/nm-modem.c | 49 +- src/core/devices/wwan/nm-modem.h | 2 +- src/core/dhcp/nm-dhcp-client.c | 112 +- src/core/dhcp/nm-dhcp-client.h | 34 +- src/core/dhcp/nm-dhcp-dhclient-utils.c | 10 +- src/core/dhcp/nm-dhcp-dhclient.c | 60 +- src/core/dhcp/nm-dhcp-dhcpcanon.c | 47 +- src/core/dhcp/nm-dhcp-dhcpcd.c | 47 +- src/core/dhcp/nm-dhcp-helper.c | 4 +- src/core/dhcp/nm-dhcp-listener.c | 3 +- src/core/dhcp/nm-dhcp-manager.c | 145 +- src/core/dhcp/nm-dhcp-nettools.c | 14 +- src/core/dhcp/nm-dhcp-systemd.c | 22 +- src/core/dhcp/nm-dhcp-utils.c | 20 +- src/core/dhcp/tests/test-dhcp-dhclient.c | 4 +- src/core/dns/nm-dns-manager.c | 32 +- src/core/dns/nm-dns-manager.h | 5 - src/core/dns/nm-dns-systemd-resolved.c | 103 +- src/core/main-utils.c | 1 - src/core/main.c | 4 +- src/core/meson.build | 2 + src/core/ndisc/nm-lndp-ndisc.c | 83 +- src/core/ndisc/nm-lndp-ndisc.h | 7 - src/core/ndisc/nm-ndisc.c | 238 +- src/core/ndisc/nm-ndisc.h | 15 +- src/core/ndisc/tests/test-ndisc-linux.c | 12 +- src/core/nm-active-connection.c | 14 +- src/core/nm-audit-manager.c | 2 +- src/core/nm-auth-utils.c | 8 +- src/core/nm-config-data.c | 35 +- src/core/nm-config-data.h | 20 +- src/core/nm-config.c | 19 +- src/core/nm-connectivity.c | 14 +- src/core/nm-core-utils.c | 193 +- src/core/nm-core-utils.h | 68 +- src/core/nm-dbus-manager.c | 2 +- src/core/nm-dbus-object.c | 2 +- src/core/nm-dbus-utils.c | 20 +- src/core/nm-dcb.c | 5 +- src/core/nm-dhcp-config.c | 2 +- src/core/nm-dispatcher.c | 22 +- src/core/nm-dispatcher.h | 7 +- src/core/nm-firewalld-manager.c | 2 +- src/core/nm-hostname-manager.c | 255 +- src/core/nm-hostname-manager.h | 4 - src/core/nm-iface-helper.c | 78 +- src/core/nm-ip4-config.c | 110 +- src/core/nm-ip4-config.h | 29 +- src/core/nm-ip6-config.c | 11 +- src/core/nm-ip6-config.h | 3 +- src/core/nm-l3-config-data.c | 701 ++-- src/core/nm-l3-config-data.h | 80 +- src/core/nm-l3-ipv4ll.c | 65 +- src/core/nm-l3-ipv6ll.c | 717 ++++ src/core/nm-l3-ipv6ll.h | 112 + src/core/nm-l3cfg.c | 1762 ++++++--- src/core/nm-l3cfg.h | 131 +- src/core/nm-manager.c | 100 +- src/core/nm-netns.c | 13 +- src/core/nm-policy.c | 48 +- src/core/nm-priv-helper-call.c | 101 + src/core/nm-priv-helper-call.h | 15 + src/core/nm-session-monitor.c | 10 +- src/core/nm-sleep-monitor.c | 40 +- src/core/nm-test-utils-core.h | 12 +- src/core/nm-types.h | 2 +- src/core/platform/tests/meson.build | 1 - src/core/platform/tests/test-common.c | 10 +- src/core/platform/tests/test-common.h | 6 +- src/core/platform/tests/test-link.c | 61 +- src/core/platform/tests/test-platform-general.c | 162 +- src/core/platform/tests/test-tc.c | 20 +- src/core/ppp/nm-ppp-manager.c | 4 +- src/core/settings/nm-settings-connection.c | 4 +- src/core/settings/nm-settings.c | 10 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 214 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-storage.c | 2 +- .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 2 + .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 111 +- ...System_test-wired-802-1X-subj-matches.cexpected | 2 + .../ifcfg-Test_Write_Bond_Main.cexpected | 3 + .../ifcfg-Test_Write_Permissions.cexpected | 3 + .../ifcfg-Test_Write_Wifi_LEAP.cexpected | 3 + .../ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected | 3 + .../ifcfg-Test_Write_Wired_Static_Routes.cexpected | 2 + .../ifcfg-Test_Write_Wired_match.cexpected | 2 + .../ifcfg-Vlan_test-vlan-interface.cexpected | 2 + .../tests/network-scripts/ifcfg-dcb-test.cexpected | 1 - .../ifcfg-random_wifi_connection.cexpected | 2 + .../ifcfg-random_wifi_connection_2.cexpected | 2 + .../tests/network-scripts/ifcfg-test-bond-port | 9 + .../ifcfg-test-ip6-disabled.cexpected | 2 + .../ifcfg-test-sriov-write.cexpected | 3 + .../ifcfg-test-static-routes-legacy.cexpected | 2 + .../ifcfg-test-tc-write-empty.cexpected | 3 + .../network-scripts/ifcfg-test-tc-write.cexpected | 3 + .../ifcfg-test-vlan-vlanid-use.cexpected | 2 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 3788 ++++++-------------- .../ifupdown/nms-ifupdown-interface-parser.c | 2 +- .../plugins/ifupdown/nms-ifupdown-parser.c | 8 +- .../plugins/ifupdown/nms-ifupdown-plugin.c | 6 +- .../settings/plugins/keyfile/nms-keyfile-plugin.c | 18 +- .../settings/plugins/keyfile/nms-keyfile-storage.c | 2 +- .../plugins/keyfile/tests/test-keyfile-settings.c | 8 +- src/core/supplicant/nm-supplicant-config.c | 2 +- src/core/supplicant/nm-supplicant-interface.c | 83 +- src/core/supplicant/nm-supplicant-interface.h | 4 + src/core/supplicant/nm-supplicant-manager.c | 3 +- .../supplicant/nm-supplicant-settings-verify.c | 2 +- src/core/supplicant/nm-supplicant-types.h | 4 +- src/core/tests/test-core.c | 168 +- src/core/tests/test-ip6-config.c | 12 +- src/core/tests/test-l3cfg.c | 317 +- src/core/tests/test-systemd.c | 8 +- src/core/tests/test-utils.c | 75 +- src/core/vpn/nm-vpn-connection.c | 1 + 162 files changed, 7014 insertions(+), 6022 deletions(-) create mode 100644 src/core/nm-l3-ipv6ll.c create mode 100644 src/core/nm-l3-ipv6ll.h create mode 100644 src/core/nm-priv-helper-call.c create mode 100644 src/core/nm-priv-helper-call.h create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-port (limited to 'src/core') diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 7d3e80be..0da8e0a9 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -17,6 +17,7 @@ #include "libnm-glib-aux/nm-uuid.h" #include "libnm-glib-aux/nm-str-buf.h" #include "libnm-base/nm-net-aux.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-aux-intern/nm-common-macros.h" #include "nm-utils.h" #include "nm-setting-connection.h" @@ -112,7 +113,7 @@ get_new_connection_name(NMConnection *const *existing_connections, * connection id. */ temp = g_strdup_printf(C_("connection id fallback", "%s %u"), fallback_prefix, i); - if (nm_utils_strv_find_first((char **) existing_names, existing_len, temp) < 0) + if (nm_strv_find_first(existing_names, existing_len, temp) < 0) return temp; g_free(temp); @@ -227,28 +228,28 @@ out: /*****************************************************************************/ void -nm_utils_complete_generic(NMPlatform * platform, - NMConnection * connection, - const char * ctype, - NMConnection *const *existing_connections, - const char * preferred_id, - const char * fallback_id_prefix, - const char * ifname_prefix, - const char * ifname, - gboolean default_enable_ipv6) +_nm_utils_complete_generic_with_params(NMPlatform * platform, + NMConnection * connection, + const char * ctype, + NMConnection *const *existing_connections, + const char * preferred_id, + const char * fallback_id_prefix, + const char * ifname_prefix, + const char * ifname, + ...) { NMSettingConnection *s_con; - char * id, *generated_ifname; - GHashTable * parameters; + char * id; + char * generated_ifname; + gs_unref_hashtable GHashTable *parameters = NULL; + va_list ap; + const char * p_val; + const char * p_key; g_assert(fallback_id_prefix); g_return_if_fail(ifname_prefix == NULL || ifname == NULL); - s_con = nm_connection_get_setting_connection(connection); - if (!s_con) { - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - } + s_con = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_TYPE, ctype, NULL); if (!nm_setting_connection_get_uuid(s_con)) { @@ -268,7 +269,9 @@ nm_utils_complete_generic(NMPlatform * platform, } /* Add an interface name, if requested */ - if (ifname) { + if (nm_setting_connection_get_interface_name(s_con)) { + /* pass */ + } else if (ifname) { g_object_set(G_OBJECT(s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NULL); } else if (ifname_prefix && !nm_setting_connection_get_interface_name(s_con)) { generated_ifname = get_new_connection_ifname(platform, existing_connections, ifname_prefix); @@ -277,13 +280,20 @@ nm_utils_complete_generic(NMPlatform * platform, } /* Normalize */ - parameters = g_hash_table_new(nm_str_hash, g_str_equal); - g_hash_table_insert(parameters, - NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD, - default_enable_ipv6 ? NM_SETTING_IP6_CONFIG_METHOD_AUTO - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE); + va_start(ap, ifname); + while ((p_key = va_arg(ap, const char *))) { + p_val = va_arg(ap, const char *); + if (!p_val) { + if (parameters) + g_hash_table_remove(parameters, p_key); + continue; + } + if (!parameters) + parameters = g_hash_table_new(nm_str_hash, g_str_equal); + g_hash_table_insert(parameters, (char *) p_key, (char *) p_val); + } + va_end(ap); nm_connection_normalize(connection, parameters, NULL, NULL); - g_hash_table_destroy(parameters); } /*****************************************************************************/ @@ -1051,6 +1061,12 @@ nm_shutdown_wait_obj_register_full(gpointer watched_obj, if (G_UNLIKELY(!_shutdown_waitobj_lst_head.next)) c_list_init(&_shutdown_waitobj_lst_head); + /* Beware: there are callers with g_main_context_get_thread_default() + * not being g_main_context_get_default(). For example _fw_nft_call(). + * + * If you schedule any sources or async operations, you probably need to + * make sure to use the default context. */ + handle = g_slice_new(NMShutdownWaitObjHandle); *handle = (NMShutdownWaitObjHandle){ /* depending on @free_msg_reason, we take ownership of @msg_reason. @@ -1693,5 +1709,11 @@ nm_platform_get() void nm_linux_platform_setup(void) { - nm_platform_setup(nm_linux_platform_new(FALSE, FALSE)); + nm_platform_setup(nm_linux_platform_new(FALSE, FALSE, FALSE)); +} + +void +nm_linux_platform_setup_with_tc_cache(void) +{ + nm_platform_setup(nm_linux_platform_new(FALSE, FALSE, TRUE)); } diff --git a/src/core/NetworkManagerUtils.h b/src/core/NetworkManagerUtils.h index 1c86387c..a2ac732e 100644 --- a/src/core/NetworkManagerUtils.h +++ b/src/core/NetworkManagerUtils.h @@ -19,15 +19,60 @@ const char *nm_utils_get_ip_config_method(NMConnection *connection, int addr_fam const char *nm_utils_get_shared_wifi_permission(NMConnection *connection); -void nm_utils_complete_generic(NMPlatform * platform, - NMConnection * connection, - const char * ctype, - NMConnection *const *existing_connections, - const char * preferred_id, - const char * fallback_id_prefix, - const char * ifname_prefix, - const char * ifname, - gboolean default_enable_ipv6); +void _nm_utils_complete_generic_with_params(NMPlatform * platform, + NMConnection * connection, + const char * ctype, + NMConnection *const *existing_connections, + const char * preferred_id, + const char * fallback_id_prefix, + const char * ifname_prefix, + const char * ifname, + ...) G_GNUC_NULL_TERMINATED; + +#define nm_utils_complete_generic_with_params(platform, \ + connection, \ + ctype, \ + existing_connections, \ + preferred_id, \ + fallback_id_prefix, \ + ifname_prefix, \ + ifname, \ + ...) \ + _nm_utils_complete_generic_with_params(platform, \ + connection, \ + ctype, \ + existing_connections, \ + preferred_id, \ + fallback_id_prefix, \ + ifname_prefix, \ + ifname, \ + ##__VA_ARGS__, \ + NULL) + +static inline void +nm_utils_complete_generic(NMPlatform * platform, + NMConnection * connection, + const char * ctype, + NMConnection *const *existing_connections, + const char * preferred_id, + const char * fallback_id_prefix, + const char * ifname_prefix, + const char * ifname, + gboolean default_enable_ipv6) +{ + nm_utils_complete_generic_with_params(platform, + connection, + ctype, + existing_connections, + preferred_id, + fallback_id_prefix, + ifname_prefix, + ifname, + NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD, + default_enable_ipv6 + ? NM_SETTING_IP6_CONFIG_METHOD_AUTO + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE); +} typedef gboolean(NMUtilsMatchFilterFunc)(NMConnection *connection, gpointer user_data); @@ -232,6 +277,7 @@ NMPlatform *nm_platform_get(void); #define NM_PLATFORM_GET (nm_platform_get()) void nm_linux_platform_setup(void); +void nm_linux_platform_setup_with_tc_cache(void); /*****************************************************************************/ diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c index 4e4c9dcc..adcf8785 100644 --- a/src/core/devices/adsl/nm-device-adsl.c +++ b/src/core/devices/adsl/nm-device-adsl.c @@ -356,7 +356,7 @@ br2684_create_iface(NMDeviceAdsl *self) return FALSE; } - nm_utils_strdup_reset(&priv->nas_ifname, ni.ifname); + nm_strdup_reset(&priv->nas_ifname, ni.ifname); _LOGD(LOGD_ADSL, "waiting for br2684 iface '%s' to appear", priv->nas_ifname); priv->nas_update_count = 0; priv->nas_update_id = g_timeout_add(100, nas_update_cb, self); diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index fc081580..36e442ad 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -31,9 +31,9 @@ /*****************************************************************************/ #if WITH_BLUEZ5_DUN - #define _NM_BT_CAPABILITY_SUPPORTED_DUN NM_BT_CAPABILITY_DUN +#define _NM_BT_CAPABILITY_SUPPORTED_DUN NM_BT_CAPABILITY_DUN #else - #define _NM_BT_CAPABILITY_SUPPORTED_DUN NM_BT_CAPABILITY_NONE +#define _NM_BT_CAPABILITY_SUPPORTED_DUN NM_BT_CAPABILITY_NONE #endif #define _NM_BT_CAPABILITY_SUPPORTED (NM_BT_CAPABILITY_NAP | _NM_BT_CAPABILITY_SUPPORTED_DUN) @@ -382,64 +382,56 @@ _bzobj_to_string(const BzDBusObj *bzobj, char *buf, gsize len) buf[0] = '\0'; if (bzobj->d_has_adapter_iface) { - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append_str(&buf, &len, "Adapter1 {"); + nm_strbuf_append_str(&buf, &len, "Adapter1 {"); if (bzobj->d_adapter.address) { - nm_utils_strbuf_append(&buf, &len, " d.address: \"%s\"", bzobj->d_adapter.address); + nm_strbuf_append(&buf, &len, " d.address: \"%s\"", bzobj->d_adapter.address); if (bzobj->d_adapter_powered) - nm_utils_strbuf_append_str(&buf, &len, ","); + nm_strbuf_append_str(&buf, &len, ","); } if (bzobj->d_adapter_powered) - nm_utils_strbuf_append(&buf, &len, " d.powered: 1"); - nm_utils_strbuf_append_str(&buf, &len, " }"); + nm_strbuf_append(&buf, &len, " d.powered: 1"); + nm_strbuf_append_str(&buf, &len, " }"); } if (bzobj->d_has_device_iface) { const char *prefix1 = ""; - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append_str(&buf, &len, "Device1 {"); + nm_strbuf_append_str(&buf, &len, "Device1 {"); if (bzobj->d_device.address) { - nm_utils_strbuf_append(&buf, - &len, - "%s d.address: \"%s\"", - prefix1, - bzobj->d_device.address); + nm_strbuf_append(&buf, &len, "%s d.address: \"%s\"", prefix1, bzobj->d_device.address); prefix1 = ","; } if (bzobj->d_device.name) { - nm_utils_strbuf_append(&buf, &len, "%s d.name: \"%s\"", prefix1, bzobj->d_device.name); + nm_strbuf_append(&buf, &len, "%s d.name: \"%s\"", prefix1, bzobj->d_device.name); prefix1 = ","; } if (bzobj->d_device.adapter) { - nm_utils_strbuf_append(&buf, - &len, - "%s d.adapter: \"%s\"", - prefix1, - bzobj->d_device.adapter); + nm_strbuf_append(&buf, &len, "%s d.adapter: \"%s\"", prefix1, bzobj->d_device.adapter); prefix1 = ","; } if (bzobj->d_device_capabilities != NM_BT_CAPABILITY_NONE) { - nm_utils_strbuf_append(&buf, - &len, - "%s d.capabilities: \"%s\"", - prefix1, - nm_bluetooth_capability_to_string(bzobj->d_device_capabilities, - sbuf_cap, - sizeof(sbuf_cap))); + nm_strbuf_append(&buf, + &len, + "%s d.capabilities: \"%s\"", + prefix1, + nm_bluetooth_capability_to_string(bzobj->d_device_capabilities, + sbuf_cap, + sizeof(sbuf_cap))); prefix1 = ","; } if (bzobj->d_device_connected) { - nm_utils_strbuf_append(&buf, &len, "%s d.connected: 1", prefix1); + nm_strbuf_append(&buf, &len, "%s d.connected: 1", prefix1); prefix1 = ","; } if (bzobj->d_device_paired) { - nm_utils_strbuf_append(&buf, &len, "%s d.paired: 1", prefix1); + nm_strbuf_append(&buf, &len, "%s d.paired: 1", prefix1); prefix1 = ","; } - nm_utils_strbuf_append_str(&buf, &len, " }"); + nm_strbuf_append_str(&buf, &len, " }"); } network_server_is_usable = _bzobjs_network_server_is_usable(bzobj, TRUE); @@ -450,43 +442,43 @@ _bzobj_to_string(const BzDBusObj *bzobj, char *buf, gsize len) || !nm_streq0(bzobj->d_has_adapter_iface ? bzobj->d_adapter.address : NULL, bzobj->x_network_server.adapter_address) || bzobj->x_network_server.device_br || bzobj->x_network_server.r_req_data) { - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append(&buf, &len, "NetworkServer1 { "); + nm_strbuf_append(&buf, &len, "NetworkServer1 { "); if (!bzobj->d_has_network_server_iface) - nm_utils_strbuf_append(&buf, &len, " has-d-iface: 0, "); + nm_strbuf_append(&buf, &len, " has-d-iface: 0, "); if (network_server_is_usable != (!c_list_is_empty(&bzobj->x_network_server.lst))) - nm_utils_strbuf_append(&buf, - &len, - "usable: %d, used: %d", - !!network_server_is_usable, - !network_server_is_usable); + nm_strbuf_append(&buf, + &len, + "usable: %d, used: %d", + !!network_server_is_usable, + !network_server_is_usable); else if (network_server_is_usable) - nm_utils_strbuf_append(&buf, &len, "used: 1"); + nm_strbuf_append(&buf, &len, "used: 1"); else - nm_utils_strbuf_append(&buf, &len, "usable: 0"); + nm_strbuf_append(&buf, &len, "usable: 0"); if (!nm_streq0(bzobj->d_has_adapter_iface ? bzobj->d_adapter.address : NULL, bzobj->x_network_server.adapter_address)) { if (bzobj->x_network_server.adapter_address) - nm_utils_strbuf_append(&buf, - &len, - ", adapter-address: \"%s\"", - bzobj->x_network_server.adapter_address); + nm_strbuf_append(&buf, + &len, + ", adapter-address: \"%s\"", + bzobj->x_network_server.adapter_address); else - nm_utils_strbuf_append(&buf, &len, ", adapter-address: "); + nm_strbuf_append(&buf, &len, ", adapter-address: "); } if (bzobj->x_network_server.device_br) - nm_utils_strbuf_append(&buf, &len, ", bridge-device: 1"); + nm_strbuf_append(&buf, &len, ", bridge-device: 1"); if (bzobj->x_network_server.r_req_data) - nm_utils_strbuf_append(&buf, &len, ", register-in-progress: 1"); + nm_strbuf_append(&buf, &len, ", register-in-progress: 1"); - nm_utils_strbuf_append_str(&buf, &len, " }"); + nm_strbuf_append_str(&buf, &len, " }"); } device_is_usable = _bzobjs_device_is_usable(bzobj, NULL, &create_panu_connection); @@ -497,76 +489,72 @@ _bzobj_to_string(const BzDBusObj *bzobj, char *buf, gsize len) || bzobj->x_device_connect_bt_type != NM_BT_CAPABILITY_NONE || bzobj->x_device.connect_dun_context || bzobj->x_device.c_req_data || bzobj->x_device_is_connected != bzobj->d_network_connected) { - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append_str(&buf, &len, "Network1 {"); + nm_strbuf_append_str(&buf, &len, "Network1 {"); if (bzobj->d_network.interface) - nm_utils_strbuf_append(&buf, - &len, - " d.interface: \"%s\", ", - bzobj->d_network.interface); + nm_strbuf_append(&buf, &len, " d.interface: \"%s\", ", bzobj->d_network.interface); if (bzobj->d_network_connected) - nm_utils_strbuf_append(&buf, &len, " d.connected: %d, ", !!bzobj->d_network_connected); + nm_strbuf_append(&buf, &len, " d.connected: %d, ", !!bzobj->d_network_connected); if (!bzobj->d_has_network_iface) - nm_utils_strbuf_append(&buf, &len, " has-d-iface: 0, "); + nm_strbuf_append(&buf, &len, " has-d-iface: 0, "); if (device_is_usable != bzobj->x_device_is_usable) - nm_utils_strbuf_append(&buf, - &len, - " usable: %d, used: %d", - !!device_is_usable, - !device_is_usable); + nm_strbuf_append(&buf, + &len, + " usable: %d, used: %d", + !!device_is_usable, + !device_is_usable); else if (device_is_usable) - nm_utils_strbuf_append(&buf, &len, " used: 1"); + nm_strbuf_append(&buf, &len, " used: 1"); else - nm_utils_strbuf_append(&buf, &len, " usable: 0"); + nm_strbuf_append(&buf, &len, " usable: 0"); if (create_panu_connection) - nm_utils_strbuf_append(&buf, &len, ", create-panu-connection: 1"); + nm_strbuf_append(&buf, &len, ", create-panu-connection: 1"); if (bzobj->x_device.panu_connection) - nm_utils_strbuf_append(&buf, &len, ", has-panu-connection: 1"); + nm_strbuf_append(&buf, &len, ", has-panu-connection: 1"); if (bzobj->x_device.device_bt) - nm_utils_strbuf_append(&buf, &len, ", has-device: 1"); + nm_strbuf_append(&buf, &len, ", has-device: 1"); if (bzobj->x_device_connect_bt_type != NM_BT_CAPABILITY_NONE || bzobj->x_device.connect_dun_context) { - nm_utils_strbuf_append( - &buf, - &len, - ", connect: %s%s", - nm_bluetooth_capability_to_string(bzobj->x_device_connect_bt_type, - sbuf_cap, - sizeof(sbuf_cap)), - bzobj->x_device.connect_dun_context ? ",with-dun-context" : ""); + nm_strbuf_append(&buf, + &len, + ", connect: %s%s", + nm_bluetooth_capability_to_string(bzobj->x_device_connect_bt_type, + sbuf_cap, + sizeof(sbuf_cap)), + bzobj->x_device.connect_dun_context ? ",with-dun-context" : ""); } if (bzobj->x_device.c_req_data) - nm_utils_strbuf_append(&buf, &len, ", connecting: 1"); + nm_strbuf_append(&buf, &len, ", connecting: 1"); if (bzobj->x_device_is_connected != bzobj->d_network_connected) - nm_utils_strbuf_append(&buf, &len, ", connected: %d", !!bzobj->x_device_is_connected); + nm_strbuf_append(&buf, &len, ", connected: %d", !!bzobj->x_device_is_connected); - nm_utils_strbuf_append_str(&buf, &len, " }"); + nm_strbuf_append_str(&buf, &len, " }"); } if (_bzobjs_is_dead(bzobj)) { - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append_str(&buf, &len, "dead: 1"); + nm_strbuf_append_str(&buf, &len, "dead: 1"); } if (!c_list_is_empty(&bzobj->process_change_lst)) { - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append(&buf, &len, "change-pending-on-idle: 1"); + nm_strbuf_append(&buf, &len, "change-pending-on-idle: 1"); } if (_bzobjs_adapter_is_usable_for_device(bzobj) != bzobj->was_usable_adapter_for_device_before) { - nm_utils_strbuf_append_str(&buf, &len, prefix); + nm_strbuf_append_str(&buf, &len, prefix); prefix = ", "; - nm_utils_strbuf_append(&buf, &len, "change-usable-adapter-for-device: 1"); + nm_strbuf_append(&buf, &len, "change-usable-adapter-for-device: 1"); } return buf0; @@ -2864,9 +2852,7 @@ dispose(GObject *object) * BzDBusObj instances and do necessary cleanup actions (like disconnecting devices * or deleting panu_connection). */ - nm_assert(c_list_is_empty(&priv->network_server_lst_head)); - nm_assert(c_list_is_empty(&priv->process_change_lst_head)); - nm_assert(priv->process_change_idle_id == 0); + nm_clear_g_source(&priv->process_change_idle_id); g_atomic_pointer_compare_and_exchange(&nm_bt_vtable_network_server, &priv->vtable_network_server, @@ -2883,6 +2869,9 @@ dispose(GObject *object) nm_clear_pointer(&priv->bzobjs, g_hash_table_destroy); nm_clear_pointer(&priv->conn_data_heads, g_hash_table_destroy); nm_clear_pointer(&priv->conn_data_elems, g_hash_table_destroy); + + nm_assert(c_list_is_empty(&priv->network_server_lst_head)); + nm_assert(c_list_is_empty(&priv->process_change_lst_head)); } static void diff --git a/src/core/devices/bluetooth/nm-bluez5-dun.c b/src/core/devices/bluetooth/nm-bluez5-dun.c index e29884d8..7efbfaf4 100644 --- a/src/core/devices/bluetooth/nm-bluez5-dun.c +++ b/src/core/devices/bluetooth/nm-bluez5-dun.c @@ -182,25 +182,18 @@ _connect_open_tty(NMBluez5DunContext *context) nm_strerror_native(errsv), errsv); context->cdat->connect_open_tty_started_at = nm_utils_get_monotonic_timestamp_nsec(); - context->cdat->source = nm_g_timeout_source_new(100, - G_PRIORITY_DEFAULT, - _connect_open_tty_retry_cb, - context, - NULL); - g_source_attach(context->cdat->source, NULL); + context->cdat->source = + nm_g_timeout_add_source(100, _connect_open_tty_retry_cb, context); } return -errsv; } context->rfcomm_tty_fd = fd; - context->rfcomm_tty_poll_source = nm_g_unix_fd_source_new(context->rfcomm_tty_fd, + context->rfcomm_tty_poll_source = nm_g_unix_fd_add_source(context->rfcomm_tty_fd, G_IO_ERR | G_IO_HUP, - G_PRIORITY_DEFAULT, _rfcomm_tty_poll_cb, - context, - NULL); - g_source_attach(context->rfcomm_tty_poll_source, NULL); + context); _context_invoke_callback_success(context); return 0; @@ -369,13 +362,10 @@ _connect_socket_connect(NMBluez5DunContext *context) context->dst_str, context->rfcomm_channel); - context->cdat->source = nm_g_unix_fd_source_new(context->rfcomm_sock_fd, + context->cdat->source = nm_g_unix_fd_add_source(context->rfcomm_sock_fd, G_IO_OUT, - G_PRIORITY_DEFAULT, _connect_socket_connect_cb, - context, - NULL); - g_source_attach(context->cdat->source, NULL); + context); return; } @@ -567,12 +557,8 @@ _connect_sdp_io_cb(int fd, GIOCondition condition, gpointer user_data) nm_strerror_native(errsv), errsv); nm_clear_g_source_inst(&context->cdat->source); - context->cdat->source = nm_g_timeout_source_new(1000, - G_PRIORITY_DEFAULT, - _connect_sdp_session_start_on_idle_cb, - context, - NULL); - g_source_attach(context->cdat->source, NULL); + context->cdat->source = + nm_g_timeout_add_source(1000, _connect_sdp_session_start_on_idle_cb, context); return G_SOURCE_REMOVE; } @@ -616,13 +602,10 @@ _connect_sdp_io_cb(int fd, GIOCondition condition, gpointer user_data) } /* Set callback responsible for update the internal SDP transaction */ - context->cdat->source = nm_g_unix_fd_source_new(fd, + context->cdat->source = nm_g_unix_fd_add_source(fd, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - G_PRIORITY_DEFAULT, _connect_sdp_search_io_cb, - context, - NULL); - g_source_attach(context->cdat->source, NULL); + context); done: if (error) @@ -664,13 +647,10 @@ _connect_sdp_session_start(NMBluez5DunContext *context, GError **error) return FALSE; } - context->cdat->source = nm_g_unix_fd_source_new(sdp_get_socket(context->cdat->sdp_session), + context->cdat->source = nm_g_unix_fd_add_source(sdp_get_socket(context->cdat->sdp_session), G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - G_PRIORITY_DEFAULT, _connect_sdp_io_cb, - context, - NULL); - g_source_attach(context->cdat->source, NULL); + context); return TRUE; } diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index 8f4ceba7..3dbfbbe0 100644 --- a/src/core/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -10,6 +10,7 @@ #include #include +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "nm-bluez-common.h" #include "nm-bluez-manager.h" @@ -273,11 +274,7 @@ complete_connection(NMDevice * device, s_serial = nm_connection_get_setting_serial(connection); s_ppp = nm_connection_get_setting_ppp(connection); - s_bt = nm_connection_get_setting_bluetooth(connection); - if (!s_bt) { - s_bt = (NMSettingBluetooth *) nm_setting_bluetooth_new(); - nm_connection_add_setting(connection, NM_SETTING(s_bt)); - } + s_bt = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BLUETOOTH); ctype = nm_setting_bluetooth_get_connection_type(s_bt); if (ctype) { @@ -1007,21 +1004,21 @@ act_stage3_ip_config_start(NMDevice * device, gpointer * out_config, NMDeviceStateReason *out_failure_reason) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device); + gboolean autoip4 = FALSE; + NMActStageReturn ret; - nm_assert_addr_family(addr_family); + if (priv->connect_bt_type != NM_BT_CAPABILITY_DUN) + goto out_chain_up; - if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) { - if (addr_family == AF_INET) { - return nm_modem_stage3_ip4_config_start(priv->modem, - device, - NM_DEVICE_CLASS(nm_device_bt_parent_class), - out_failure_reason); - } else { - return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); - } - } + if (!NM_IS_IPv4(addr_family)) + return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); + + ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4) + return ret; +out_chain_up: return NM_DEVICE_CLASS(nm_device_bt_parent_class) ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); } diff --git a/src/core/devices/bluetooth/tests/nm-bt-test.c b/src/core/devices/bluetooth/tests/nm-bt-test.c index 0fc8aa87..548e7249 100644 --- a/src/core/devices/bluetooth/tests/nm-bt-test.c +++ b/src/core/devices/bluetooth/tests/nm-bt-test.c @@ -2,8 +2,6 @@ #include "src/core/nm-default-daemon.h" -#include - #include "devices/bluetooth/nm-bluez5-dun.h" #include "nm-test-utils-core.h" diff --git a/src/core/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c index 145947bb..c041163e 100644 --- a/src/core/devices/nm-acd-manager.c +++ b/src/core/devices/nm-acd-manager.c @@ -349,9 +349,7 @@ nm_acd_manager_start_probe(NMAcdManager *self, guint timeout) nm_assert(!self->event_source); n_acd_get_fd(self->acd, &fd); - self->event_source = - nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, acd_event, self, NULL); - g_source_attach(self->event_source, NULL); + self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self); return success ? 0 : -NME_UNSPEC; } @@ -439,9 +437,7 @@ nm_acd_manager_announce_addresses(NMAcdManager *self) if (!self->event_source) { n_acd_get_fd(self->acd, &fd); - self->event_source = - nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, acd_event, self, NULL); - g_source_attach(self->event_source, NULL); + self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self); } return success ? 0 : -NME_UNSPEC; diff --git a/src/core/devices/nm-device-6lowpan.c b/src/core/devices/nm-device-6lowpan.c index 96218658..8b77c22c 100644 --- a/src/core/devices/nm-device-6lowpan.c +++ b/src/core/devices/nm-device-6lowpan.c @@ -9,6 +9,7 @@ #include "nm-device-private.h" #include "settings/nm-settings.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-6lowpan.h" @@ -221,12 +222,7 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMSetting6Lowpan *s_6lowpan = - NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN)); - - if (!s_6lowpan) { - s_6lowpan = (NMSetting6Lowpan *) nm_setting_6lowpan_new(); - nm_connection_add_setting(connection, (NMSetting *) s_6lowpan); - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_6LOWPAN); g_object_set( s_6lowpan, diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index b208e2c0..f7d78f57 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -14,8 +14,10 @@ #include "nm-device-private.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "nm-ip4-config.h" +#include "nm-setting-bond-port.h" #define _NMLOG_DEVICE_TYPE NMDeviceBond #include "nm-device-logging.h" @@ -79,8 +81,6 @@ complete_connection(NMDevice * device, NMConnection *const *existing_connections, GError ** error) { - NMSettingBond *s_bond; - nm_utils_complete_generic(nm_device_get_platform(device), connection, NM_SETTING_BOND_SETTING_NAME, @@ -91,11 +91,7 @@ complete_connection(NMDevice * device, NULL, TRUE); - s_bond = nm_connection_get_setting_bond(connection); - if (!s_bond) { - s_bond = (NMSettingBond *) nm_setting_bond_new(); - nm_connection_add_setting(connection, NM_SETTING(s_bond)); - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND); return TRUE; } @@ -168,16 +164,11 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceBond * self = NM_DEVICE_BOND(device); - NMSettingBond *s_bond = nm_connection_get_setting_bond(connection); + NMSettingBond *s_bond = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND); int ifindex = nm_device_get_ifindex(device); NMBondMode mode = NM_BOND_MODE_UNKNOWN; const char ** options; - if (!s_bond) { - s_bond = (NMSettingBond *) nm_setting_bond_new(); - nm_connection_add_setting(connection, (NMSetting *) s_bond); - } - /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options(NULL); for (; options[0]; options++) { @@ -225,11 +216,29 @@ update_connection(NMDevice *device, NMConnection *connection) } static gboolean -master_update_slave_connection(NMDevice * self, - NMDevice * slave, - NMConnection *connection, - GError ** error) +controller_update_port_connection(NMDevice * self, + NMDevice * port, + NMConnection *connection, + GError ** error) { + NMSettingBondPort *s_port; + int ifindex_port = nm_device_get_ifindex(port); + uint queue_id = NM_BOND_PORT_QUEUE_ID_DEF; + gs_free char * queue_id_str = NULL; + + g_return_val_if_fail(ifindex_port > 0, FALSE); + + s_port = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND_PORT); + + queue_id_str = + nm_platform_sysctl_slave_get_option(nm_device_get_platform(self), ifindex_port, "queue_id"); + if (queue_id_str) { + queue_id = + _nm_utils_ascii_str_to_int64(queue_id_str, 10, 0, 65535, NM_BOND_PORT_QUEUE_ID_DEF); + g_object_set(s_port, NM_SETTING_BOND_PORT_QUEUE_ID, queue_id, NULL); + } else + _LOGW(LOGD_BOND, "failed to read bond port setting '%s'", NM_SETTING_BOND_PORT_QUEUE_ID); + g_object_set(nm_connection_get_setting_connection(connection), NM_SETTING_CONNECTION_MASTER, nm_device_get_iface(self), @@ -250,9 +259,8 @@ set_arp_targets(NMDevice *device, const char *cur_arp_ip_target, const char *new gsize i; gsize j; - cur_strv = nm_utils_strsplit_set_full(cur_arp_ip_target, - NM_ASCII_SPACES, - NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); + cur_strv = + nm_strsplit_set_full(cur_arp_ip_target, NM_ASCII_SPACES, NM_STRSPLIT_SET_FLAGS_STRSTRIP); new_strv = nm_utils_bond_option_arp_ip_targets_split(new_arp_ip_target); cur_len = NM_PTRARRAY_LEN(cur_strv); @@ -276,7 +284,7 @@ set_arp_targets(NMDevice *device, const char *cur_arp_ip_target, const char *new } } - if (nm_utils_strv_find_first((char **) new_strv, i, s) < 0) + if (nm_strv_find_first(new_strv, i, s) < 0) new_strv[j++] = s; } new_strv[j] = NULL; @@ -286,7 +294,7 @@ set_arp_targets(NMDevice *device, const char *cur_arp_ip_target, const char *new if (cur_len == 0 && new_len == 0) return; - if (nm_utils_strv_equal(cur_strv, new_strv)) + if (nm_strv_equal(cur_strv, new_strv)) return; for (i = 0; i < cur_len; i++) @@ -395,30 +403,57 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) return ret; } +static void +commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_port) +{ + char queue_id_str[IFNAMSIZ + NM_STRLEN(":") + 5 + 100]; + + /* + * The queue-id of bond port is read only, we should modify bond interface using: + * echo "eth1:2" > /sys/class/net/bond0/bonding/queue_id + * Kernel allows parital editing, so no need to care about other bond ports. + */ + g_snprintf(queue_id_str, + sizeof(queue_id_str), + "%s:%" G_GUINT32_FORMAT, + nm_device_get_iface(port), + s_port ? nm_setting_bond_port_get_queue_id(s_port) : NM_BOND_PORT_QUEUE_ID_DEF); + + nm_platform_sysctl_master_set_option(nm_device_get_platform(bond_device), + nm_device_get_ifindex(bond_device), + "queue_id", + queue_id_str); +} + static gboolean -enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) { - NMDeviceBond *self = NM_DEVICE_BOND(device); + NMDeviceBond * self = NM_DEVICE_BOND(device); + NMSettingBondPort *s_port; - nm_device_master_check_slave_physical_port(device, slave, LOGD_BOND); + nm_device_master_check_slave_physical_port(device, port, LOGD_BOND); if (configure) { gboolean success; - nm_device_take_down(slave, TRUE); + nm_device_take_down(port, TRUE); success = nm_platform_link_enslave(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), - nm_device_get_ip_ifindex(slave)); - nm_device_bring_up(slave, TRUE, NULL); + nm_device_get_ip_ifindex(port)); + nm_device_bring_up(port, TRUE, NULL); if (!success) { - _LOGI(LOGD_BOND, "enslaved bond slave %s: failed", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BOND, "assigning bond port %s: failed", nm_device_get_ip_iface(port)); return FALSE; } - _LOGI(LOGD_BOND, "enslaved bond slave %s", nm_device_get_ip_iface(slave)); + s_port = _nm_connection_get_setting(connection, NM_TYPE_SETTING_BOND_PORT); + + commit_port_options(device, port, s_port); + + _LOGI(LOGD_BOND, "assigned bond port %s", nm_device_get_ip_iface(port)); } else - _LOGI(LOGD_BOND, "bond slave %s was enslaved", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BOND, "bond port %s was assigned", nm_device_get_ip_iface(port)); return TRUE; } @@ -624,7 +659,7 @@ nm_device_bond_class_init(NMDeviceBondClass *klass) device_class->complete_connection = complete_connection; device_class->update_connection = update_connection; - device_class->master_update_slave_connection = master_update_slave_connection; + device_class->master_update_slave_connection = controller_update_port_connection; device_class->create_and_realize = create_and_realize; device_class->act_stage1_prepare = act_stage1_prepare; diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index a095dc3e..36a73978 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -14,6 +14,7 @@ #include "nm-device-private.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceBridge @@ -145,8 +146,6 @@ complete_connection(NMDevice * device, NMConnection *const *existing_connections, GError ** error) { - NMSettingBridge *s_bridge; - nm_utils_complete_generic(nm_device_get_platform(device), connection, NM_SETTING_BRIDGE_SETTING_NAME, @@ -157,11 +156,7 @@ complete_connection(NMDevice * device, NULL, TRUE); - s_bridge = nm_connection_get_setting_bridge(connection); - if (!s_bridge) { - s_bridge = (NMSettingBridge *) nm_setting_bridge_new(); - nm_connection_add_setting(connection, NM_SETTING(s_bridge)); - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BRIDGE); return TRUE; } @@ -576,17 +571,12 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); - NMSettingBridge *s_bridge = nm_connection_get_setting_bridge(connection); + NMSettingBridge *s_bridge = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BRIDGE); int ifindex = nm_device_get_ifindex(device); const Option * option; gs_free char * stp = NULL; int stp_value; - if (!s_bridge) { - s_bridge = (NMSettingBridge *) nm_setting_bridge_new(); - nm_connection_add_setting(connection, (NMSetting *) s_bridge); - } - option = master_options; nm_assert(nm_streq(option->sysname, "stp_state")); @@ -690,11 +680,7 @@ master_update_slave_connection(NMDevice * device, g_return_val_if_fail(ifindex_slave > 0, FALSE); s_con = nm_connection_get_setting_connection(connection); - s_port = nm_connection_get_setting_bridge_port(connection); - if (!s_port) { - s_port = (NMSettingBridgePort *) nm_setting_bridge_port_new(); - nm_connection_add_setting(connection, NM_SETTING(s_port)); - } + s_port = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BRIDGE_PORT); for (option = slave_options; option->name; option++) { gs_free char *str = nm_platform_sysctl_slave_get_option(nm_device_get_platform(device), diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c index 488f0ba0..4c12648f 100644 --- a/src/core/devices/nm-device-dummy.c +++ b/src/core/devices/nm-device-dummy.c @@ -16,6 +16,7 @@ #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-dummy.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceDummy @@ -48,26 +49,16 @@ complete_connection(NMDevice * device, NMConnection *const *existing_connections, GError ** error) { - NMSettingDummy *s_dummy; + nm_utils_complete_generic_with_params(nm_device_get_platform(device), + connection, + NM_SETTING_DUMMY_SETTING_NAME, + existing_connections, + NULL, + _("Dummy connection"), + NULL, + nm_device_get_ip_iface(device)); - nm_utils_complete_generic(nm_device_get_platform(device), - connection, - NM_SETTING_DUMMY_SETTING_NAME, - existing_connections, - NULL, - _("Dummy connection"), - NULL, - NULL, - TRUE); - - s_dummy = nm_connection_get_setting_dummy(connection); - if (!s_dummy) { - g_set_error_literal(error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'dummy' setting is required."); - return FALSE; - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_DUMMY); return TRUE; } @@ -75,12 +66,7 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMSettingDummy *s_dummy = nm_connection_get_setting_dummy(connection); - - if (!s_dummy) { - s_dummy = (NMSettingDummy *) nm_setting_dummy_new(); - nm_connection_add_setting(connection, (NMSetting *) s_dummy); - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_DUMMY); } static gboolean diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 95336c7a..667ea9b9 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -33,6 +33,7 @@ #include "nm-device-ethernet-utils.h" #include "settings/nm-settings.h" #include "nm-device-factory.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "libnm-udev-aux/nm-udev-utils.h" @@ -1618,11 +1619,7 @@ complete_connection(NMDevice * device, NULL, TRUE); - s_veth = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VETH); - if (!s_veth) { - s_veth = (NMSettingVeth *) nm_setting_veth_new(); - nm_connection_add_setting(connection, NM_SETTING(s_veth)); - } + s_veth = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VETH); ifindex = nm_device_get_ip_ifindex(device); if (ifindex > 0) { @@ -1664,11 +1661,7 @@ complete_connection(NMDevice * device, if (s_pppoe && !nm_setting_verify(NM_SETTING(s_pppoe), NULL, error)) return FALSE; - s_wired = nm_connection_get_setting_wired(connection); - if (!s_wired) { - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - } + s_wired = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRED); /* Default to an ethernet-only connection, but if a PPPoE setting was given * then PPPoE should be our connection type. @@ -1782,20 +1775,15 @@ get_s390_subchannels(NMDevice *device) static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device); - NMSettingWired * s_wired = nm_connection_get_setting_wired(connection); - gboolean perm_hw_addr_is_fake; - const char * perm_hw_addr; - const char * mac = nm_device_get_hw_address(device); - const char * mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; - GHashTableIter iter; - const char * key; - const char * value; - - if (!s_wired) { - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, (NMSetting *) s_wired); - } + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device); + NMSettingWired *s_wired = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRED); + gboolean perm_hw_addr_is_fake; + const char * perm_hw_addr; + const char * mac = nm_device_get_hw_address(device); + const char * mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; + GHashTableIter iter; + const char * key; + const char * value; g_object_set(nm_connection_get_setting_connection(connection), NM_SETTING_CONNECTION_TYPE, diff --git a/src/core/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c index 37065bc8..df14dfa8 100644 --- a/src/core/devices/nm-device-infiniband.c +++ b/src/core/devices/nm-device-infiniband.c @@ -16,6 +16,7 @@ #include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #define NM_DEVICE_INFINIBAND_IS_PARTITION "is-partition" @@ -146,11 +147,7 @@ complete_connection(NMDevice * device, { NMSettingInfiniband *s_infiniband; - s_infiniband = nm_connection_get_setting_infiniband(connection); - if (!s_infiniband) { - s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new(); - nm_connection_add_setting(connection, NM_SETTING(s_infiniband)); - } + s_infiniband = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_INFINIBAND); nm_utils_complete_generic( nm_device_get_platform(device), @@ -175,15 +172,11 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband(connection); - const char * mac = nm_device_get_permanent_hw_address(device); - const char * transport_mode = "datagram"; - int ifindex; - - if (!s_infiniband) { - s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new(); - nm_connection_add_setting(connection, (NMSetting *) s_infiniband); - } + NMSettingInfiniband *s_infiniband = + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_INFINIBAND); + const char *mac = nm_device_get_permanent_hw_address(device); + const char *transport_mode = "datagram"; + int ifindex; if (mac && !nm_utils_hwaddr_matches(mac, -1, NULL, INFINIBAND_ALEN)) g_object_set(s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL); diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index c55dd9f6..fe2e2023 100644 --- a/src/core/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -18,6 +18,7 @@ #include "nm-manager.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings.h" #include "nm-act-request.h" @@ -416,14 +417,10 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(device); - NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); - NMSettingIPTunnel * s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection); - - if (!s_ip_tunnel) { - s_ip_tunnel = (NMSettingIPTunnel *) nm_setting_ip_tunnel_new(); - nm_connection_add_setting(connection, (NMSetting *) s_ip_tunnel); - } + NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); + NMSettingIPTunnel * s_ip_tunnel = + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_IP_TUNNEL); if (nm_setting_ip_tunnel_get_mode(s_ip_tunnel) != priv->mode) g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_MODE, priv->mode, NULL); diff --git a/src/core/devices/nm-device-logging.h b/src/core/devices/nm-device-logging.h index 844e9949..c2602189 100644 --- a/src/core/devices/nm-device-logging.h +++ b/src/core/devices/nm-device-logging.h @@ -9,15 +9,13 @@ #include "nm-device.h" #if !_NM_CC_SUPPORT_GENERIC - #define _NM_DEVICE_CAST(self) ((NMDevice *) (self)) +#define _NM_DEVICE_CAST(self) ((NMDevice *) (self)) #elif !defined(_NMLOG_DEVICE_TYPE) - #define _NM_DEVICE_CAST(self) \ - _Generic((self), NMDevice * \ - : ((NMDevice *) (self)), NMDevice *const \ - : ((NMDevice *) (self))) +#define _NM_DEVICE_CAST(self) \ + _Generic((self), NMDevice * : ((NMDevice *) (self)), NMDevice *const : ((NMDevice *) (self))) #else - #define _NM_DEVICE_CAST(self) \ - _Generic((self), \ +#define _NM_DEVICE_CAST(self) \ + _Generic((self), \ _NMLOG_DEVICE_TYPE * : ((NMDevice *) (self)), \ _NMLOG_DEVICE_TYPE * const: ((NMDevice *) (self)), \ NMDevice * : ((NMDevice *) (self)), \ diff --git a/src/core/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c index 7302ecdf..937ba9e4 100644 --- a/src/core/devices/nm-device-macvlan.c +++ b/src/core/devices/nm-device-macvlan.c @@ -13,6 +13,7 @@ #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-manager.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-macvlan.h" @@ -419,14 +420,10 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE(device); - NMSettingMacvlan * s_macvlan = nm_connection_get_setting_macvlan(connection); - int new_mode; - - if (!s_macvlan) { - s_macvlan = (NMSettingMacvlan *) nm_setting_macvlan_new(); - nm_connection_add_setting(connection, (NMSetting *) s_macvlan); - } + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE(device); + NMSettingMacvlan * s_macvlan = + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_MACVLAN); + int new_mode; new_mode = platform_mode_to_setting(priv->props.mode); if (new_mode != nm_setting_macvlan_get_mode(s_macvlan)) diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c index 8df245bb..04051bec 100644 --- a/src/core/devices/nm-device-ppp.c +++ b/src/core/devices/nm-device-ppp.c @@ -93,28 +93,35 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin } static void -ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) +_ppp_ip4_config_handle(NMDevicePpp *self) { - NMDevice * device = NM_DEVICE(user_data); - NMDevicePpp * self = NM_DEVICE_PPP(device); + NMDevice * device = NM_DEVICE(self); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); - _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd"); + if (!priv->ip4_config) + return; - if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG) { - if (nm_device_activate_ip4_state_in_conf(device)) { - nm_device_activate_schedule_ip_config_result(device, - AF_INET, - NM_IP_CONFIG_CAST(config)); - return; - } - } else { - if (priv->ip4_config) - g_object_unref(priv->ip4_config); - priv->ip4_config = g_object_ref(config); + if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG + && nm_device_activate_ip4_state_in_conf(device)) { + nm_device_activate_schedule_ip_config_result( + device, + AF_INET, + NM_IP_CONFIG_CAST(g_steal_pointer(&priv->ip4_config))); + return; } } +static void +ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) +{ + NMDevicePpp * self = NM_DEVICE_PPP(user_data); + NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + + _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd"); + nm_g_object_ref_set(&priv->ip4_config, config); + _ppp_ip4_config_handle(self); +} + static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { @@ -193,6 +200,15 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_POSTPONE; } +static gboolean +_schedule_ip_config_result(gpointer user_data) +{ + gs_unref_object NMDevicePpp *self = user_data; + + _ppp_ip4_config_handle(self); + return G_SOURCE_REMOVE; +} + static NMActStageReturn act_stage3_ip_config_start(NMDevice * device, int addr_family, @@ -203,13 +219,8 @@ act_stage3_ip_config_start(NMDevice * device, NMDevicePpp * self = NM_DEVICE_PPP(device); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); - if (priv->ip4_config) { - if (out_config) - *out_config = g_steal_pointer(&priv->ip4_config); - else - g_clear_object(&priv->ip4_config); - return NM_ACT_STAGE_RETURN_SUCCESS; - } + if (priv->ip4_config) + nm_g_idle_add(_schedule_ip_config_result, g_object_ref(self)); /* Wait IPCP termination */ return NM_ACT_STAGE_RETURN_POSTPONE; @@ -256,6 +267,8 @@ deactivate(NMDevice *device) nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL); g_clear_object(&priv->ppp_manager); } + + g_clear_object(&priv->ip4_config); } static void diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index eb37b14f..b55e8b43 100644 --- a/src/core/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -143,7 +143,7 @@ NMIP6Config *nm_device_ip6_config_new(NMDevice *self); NMIPConfig *nm_device_ip_config_new(NMDevice *self, int addr_family); -NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self); +NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source); /*****************************************************************************/ diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index ebccddfc..0ab08f65 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -17,6 +17,7 @@ #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-tun.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceTun @@ -186,11 +187,7 @@ update_connection(NMDevice *device, NMConnection *connection) return; } - s_tun = nm_connection_get_setting_tun(connection); - if (!s_tun) { - s_tun = (NMSettingTun *) nm_setting_tun_new(); - nm_connection_add_setting(connection, (NMSetting *) s_tun); - } + s_tun = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TUN); if (mode != nm_setting_tun_get_mode(s_tun)) g_object_set(G_OBJECT(s_tun), NM_SETTING_TUN_MODE, (guint) mode, NULL); diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c index f40ca570..2a6ab04e 100644 --- a/src/core/devices/nm-device-utils.c +++ b/src/core/devices/nm-device-utils.c @@ -10,7 +10,7 @@ /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE( - nm_device_state_queued_state_to_str, + nm_device_state_queued_state_to_string, NMDeviceState, NM_UTILS_LOOKUP_DEFAULT(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_UNKNOWN, @@ -41,14 +41,14 @@ NM_UTILS_LOOKUP_STR_DEFINE( NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"), ); const char * -nm_device_state_to_str(NMDeviceState state) +nm_device_state_to_string(NMDeviceState state) { - return nm_device_state_queued_state_to_str(state) + return nm_device_state_queued_state_to_string(state) + NM_STRLEN(NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE); } NM_UTILS_LOOKUP_STR_DEFINE( - nm_device_state_reason_to_str, + nm_device_state_reason_to_string, NMDeviceStateReason, NM_UTILS_LOOKUP_DEFAULT(NULL), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNKNOWN, "unknown"), @@ -129,7 +129,7 @@ NM_UTILS_LOOKUP_STR_DEFINE( "sriov-configuration-failed"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), ); -NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_str, +NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_string, NMDeviceMtuSource, NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_NONE, "none"), @@ -138,7 +138,7 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_str, NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_MTU_SOURCE_CONNECTION, "connection"), ); -NM_UTILS_LOOKUP_STR_DEFINE(nm_device_sys_iface_state_to_str, +NM_UTILS_LOOKUP_STR_DEFINE(nm_device_sys_iface_state_to_string, NMDeviceSysIfaceState, NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"), @@ -147,7 +147,7 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_device_sys_iface_state_to_str, NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_SYS_IFACE_STATE_REMOVED, "removed"), ); -NM_UTILS_LOOKUP_STR_DEFINE(nm_device_ip_state_to_str, +NM_UTILS_LOOKUP_STR_DEFINE(nm_device_ip_state_to_string, NMDeviceIPState, NM_UTILS_LOOKUP_DEFAULT_WARN("unknown"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_NONE, "none"), @@ -267,7 +267,18 @@ resolve_addr_resolved_cb(NMDnsSystemdResolved * resolved, _LOG2D(info, "error resolving via systemd-resolved: %s", error->message); dbus_error = g_dbus_error_get_remote_error(error); - if (nm_streq0(dbus_error, "org.freedesktop.resolve1.DnsError.NXDOMAIN")) { + if (NM_STR_HAS_PREFIX(dbus_error, "org.freedesktop.resolve1.")) { + /* systemd-resolved is enabled but it couldn't resolve the + * address via DNS. Don't fall back to spawning the helper, + * because the helper will possibly ask again to + * systemd-resolved (via /etc/resolv.conf), potentially using + * other protocols than DNS or returning synthetic results. + * + * Consider the error as the final indication that the address + * can't be resolved. + * + * See: https://www.freedesktop.org/wiki/Software/systemd/resolved/#commonerrors + */ resolve_addr_complete(info, NULL, g_error_copy(error)); return; } diff --git a/src/core/devices/nm-device-utils.h b/src/core/devices/nm-device-utils.h index 8bc957a4..7200b0ea 100644 --- a/src/core/devices/nm-device-utils.h +++ b/src/core/devices/nm-device-utils.h @@ -5,11 +5,11 @@ /*****************************************************************************/ -const char *nm_device_state_to_str(NMDeviceState state); -const char *nm_device_state_reason_to_str(NMDeviceStateReason reason); +const char *nm_device_state_to_string(NMDeviceState state); +const char *nm_device_state_reason_to_string(NMDeviceStateReason reason); -#define nm_device_state_reason_to_str_a(reason) \ - NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_str, reason) +#define nm_device_state_reason_to_string_a(reason) \ + NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_string, reason) static inline NMDeviceStateReason nm_device_state_reason_check(NMDeviceStateReason reason) @@ -41,7 +41,7 @@ nm_device_state_reason_check(NMDeviceStateReason reason) #define NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "queued-state-change-" #define NM_PENDING_ACTIONPREFIX_ACTIVATION "activation-" -const char *nm_device_state_queued_state_to_str(NMDeviceState state); +const char *nm_device_state_queued_state_to_string(NMDeviceState state); /*****************************************************************************/ @@ -52,7 +52,7 @@ typedef enum { NM_DEVICE_MTU_SOURCE_CONNECTION, } NMDeviceMtuSource; -const char *nm_device_mtu_source_to_str(NMDeviceMtuSource mtu_source); +const char *nm_device_mtu_source_to_string(NMDeviceMtuSource mtu_source); /*****************************************************************************/ @@ -69,7 +69,7 @@ typedef enum _nm_packed { NM_DEVICE_SYS_IFACE_STATE_REMOVED, } NMDeviceSysIfaceState; -const char *nm_device_sys_iface_state_to_str(NMDeviceSysIfaceState sys_iface_state); +const char *nm_device_sys_iface_state_to_string(NMDeviceSysIfaceState sys_iface_state); /*****************************************************************************/ @@ -81,7 +81,7 @@ typedef enum { NM_DEVICE_IP_STATE_FAIL, } NMDeviceIPState; -const char *nm_device_ip_state_to_str(NMDeviceIPState ip_state); +const char *nm_device_ip_state_to_string(NMDeviceIPState ip_state); /*****************************************************************************/ diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c index 548245f8..d1e57411 100644 --- a/src/core/devices/nm-device-vlan.c +++ b/src/core/devices/nm-device-vlan.c @@ -19,6 +19,7 @@ #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-manager.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-platform/nmp-object.h" #include "libnm-platform/nm-platform-utils.h" @@ -432,18 +433,13 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceVlanPrivate * priv = NM_DEVICE_VLAN_GET_PRIVATE(device); - NMSettingVlan * s_vlan = nm_connection_get_setting_vlan(connection); + NMSettingVlan * s_vlan = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VLAN); int ifindex = nm_device_get_ifindex(device); const NMPlatformLink *plink; const NMPObject * polnk; guint vlan_id; _NMVlanFlags vlan_flags; - if (!s_vlan) { - s_vlan = (NMSettingVlan *) nm_setting_vlan_new(); - nm_connection_add_setting(connection, (NMSetting *) s_vlan); - } - polnk = nm_platform_link_get_lnk(nm_device_get_platform(device), ifindex, NM_LINK_TYPE_VLAN, diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index 2a1f42c6..c752fa0a 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -9,6 +9,7 @@ #include "nm-device-private.h" #include "nm-manager.h" #include "nm-setting-vrf.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-platform/nm-platform.h" #include "settings/nm-settings.h" @@ -199,12 +200,7 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceVrfPrivate *priv = NM_DEVICE_VRF_GET_PRIVATE(device); - NMSettingVrf * s_vrf = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VRF); - - if (!s_vrf) { - s_vrf = (NMSettingVrf *) nm_setting_vrf_new(); - nm_connection_add_setting(connection, (NMSetting *) s_vrf); - } + NMSettingVrf * s_vrf = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VRF); if (priv->props.table != nm_setting_vrf_get_table(s_vrf)) g_object_set(G_OBJECT(s_vrf), NM_SETTING_VRF_TABLE, priv->props.table, NULL); diff --git a/src/core/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c index f9dfad2a..fcd6950b 100644 --- a/src/core/devices/nm-device-vxlan.c +++ b/src/core/devices/nm-device-vxlan.c @@ -17,6 +17,7 @@ #include "settings/nm-settings.h" #include "nm-act-request.h" #include "nm-ip4-config.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceVxlan @@ -399,14 +400,9 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE(device); - NMSettingVxlan * s_vxlan = nm_connection_get_setting_vxlan(connection); - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - if (!s_vxlan) { - s_vxlan = (NMSettingVxlan *) nm_setting_vxlan_new(); - nm_connection_add_setting(connection, (NMSetting *) s_vxlan); - } + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE(device); + NMSettingVxlan *s_vxlan = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VXLAN); + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; if (priv->props.id != nm_setting_vxlan_get_id(s_vxlan)) g_object_set(G_OBJECT(s_vxlan), NM_SETTING_VXLAN_ID, priv->props.id, NULL); diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index aa9c46eb..f129478f 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -11,6 +11,7 @@ #include #include "nm-setting-wireguard.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-glib-aux/nm-secret-utils.h" #include "nm-device-private.h" @@ -1891,17 +1892,11 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(device); - NMSettingWireGuard * s_wg = - NM_SETTING_WIREGUARD(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIREGUARD)); - const NMPObject * obj_wg; + NMSettingWireGuard *s_wg = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIREGUARD); + const NMPObject * obj_wg; const NMPObjectLnkWireGuard *olnk_wg; guint i; - if (!s_wg) { - s_wg = NM_SETTING_WIREGUARD(nm_setting_wireguard_new()); - nm_connection_add_setting(connection, NM_SETTING(s_wg)); - } - g_object_set(s_wg, NM_SETTING_WIREGUARD_FWMARK, (guint) priv->lnk_curr.fwmark, diff --git a/src/core/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c index 73d79410..9bc43a85 100644 --- a/src/core/devices/nm-device-wpan.c +++ b/src/core/devices/nm-device-wpan.c @@ -18,6 +18,7 @@ #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-wpan.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #define _NMLOG_DEVICE_TYPE NMDeviceWpan @@ -71,13 +72,7 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMSettingWpan *s_wpan = - NM_SETTING_WPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_WPAN)); - - if (!s_wpan) { - s_wpan = (NMSettingWpan *) nm_setting_wpan_new(); - nm_connection_add_setting(connection, (NMSetting *) s_wpan); - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WPAN); } static gboolean diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 50386d00..ea1b9647 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -185,7 +185,7 @@ typedef struct { typedef struct { NMDhcpClient *client; NMDhcpConfig *config; - gulong state_sigid; + gulong notify_sigid; guint grace_id; bool grace_pending : 1; bool was_active : 1; @@ -290,7 +290,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice, PROP_STATISTICS_RX_BYTES, PROP_IP4_CONNECTIVITY, PROP_IP6_CONNECTIVITY, - PROP_INTERFACE_FLAGS, ); + PROP_INTERFACE_FLAGS, + PROP_PORTS, ); typedef struct _NMDevicePrivate { bool in_state_changed; @@ -316,7 +317,12 @@ typedef struct _NMDevicePrivate { guint queued_ip_config_id_x[2]; }; - GSList *pending_actions; + struct { + const char **arr; + guint len; + guint alloc; + } pending_actions; + GSList *dad6_failed_addrs; NMDBusTrackObjPath parent_device; @@ -500,6 +506,7 @@ typedef struct _NMDevicePrivate { NMDeviceStageState stage1_sriov_state : 3; bool ip_config_started : 1; + bool tc_committed : 1; char *current_stable_id; @@ -574,7 +581,6 @@ typedef struct _NMDevicePrivate { AppliedConfig ip6_config; /* Event ID of the current IP6 config from DHCP */ char * event_id; - gulong prefix_sigid; NMNDiscDHCPLevel mode; guint needed_prefixes; } dhcp6; @@ -696,15 +702,17 @@ typedef struct _NMDevicePrivate { guint sriov_reset_pending; struct { - guint timeout_id; - guint refresh_rate_ms; - guint64 tx_bytes; - guint64 rx_bytes; + GSource *timeout_source; + guint refresh_rate_ms; + guint64 tx_bytes; + guint64 rx_bytes; } stats; bool mtu_force_set_done : 1; NMOptionBool promisc_reset; + + GVariant *ports_variant; /* Array of port devices D-Bus path */ } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -1190,6 +1198,29 @@ _prop_get_connection_llmnr(NMDevice *self) NM_SETTING_CONNECTION_LLMNR_DEFAULT); } +static NMSettingConnectionDnsOverTls +_prop_get_connection_dns_over_tls(NMDevice *self) +{ + NMConnection * connection; + NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); + + connection = nm_device_get_applied_connection(self); + if (connection) + dns_over_tls = nm_setting_connection_get_dns_over_tls( + nm_connection_get_setting_connection(connection)); + if (dns_over_tls != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + return dns_over_tls; + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("connection.dns-over-tls"), + self, + NM_SETTING_CONNECTION_DNS_OVER_TLS_NO, + NM_SETTING_CONNECTION_DNS_OVER_TLS_YES, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); +} + static guint32 _prop_get_ipvx_route_table(NMDevice *self, int addr_family) { @@ -2407,7 +2438,7 @@ nm_device_ip_config_new(NMDevice *self, int addr_family) } NML3ConfigData * -nm_device_create_l3_config_data(NMDevice *self) +nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source) { int ifindex; @@ -2417,7 +2448,7 @@ nm_device_create_l3_config_data(NMDevice *self) if (ifindex <= 0) g_return_val_if_reached(NULL); - return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex); + return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex, source); } static void @@ -2554,8 +2585,8 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st if (priv->sys_iface_state != sys_iface_state) { _LOGT(LOGD_DEVICE, "sys-iface-state: %s -> %s", - nm_device_sys_iface_state_to_str(priv->sys_iface_state), - nm_device_sys_iface_state_to_str(sys_iface_state)); + nm_device_sys_iface_state_to_string(priv->sys_iface_state), + nm_device_sys_iface_state_to_string(sys_iface_state)); priv->sys_iface_state_ = sys_iface_state; } @@ -2741,7 +2772,7 @@ nm_device_sysctl_ip_conf_get_int_checked(NMDevice * self, } static void -set_ipv6_token(NMDevice *self, NMUtilsIPv6IfaceId iid, const char *token_str) +set_ipv6_token(NMDevice *self, const NMUtilsIPv6IfaceId *iid, const char *token_str) { NMPlatform * platform; int ifindex; @@ -2757,7 +2788,7 @@ set_ipv6_token(NMDevice *self, NMUtilsIPv6IfaceId iid, const char *token_str) ifindex = nm_device_get_ip_ifindex(self); link = nm_platform_link_get(platform, ifindex); - if (link && link->inet6_token.id == iid.id) { + if (link && link->inet6_token.id == iid->id) { _LOGT(LOGD_DEVICE | LOGD_IP6, "token %s already set", token_str); return; } @@ -2905,7 +2936,7 @@ _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) "ip%c-state: set to %d (%s)", nm_utils_addr_family_to_char(addr_family), (int) new_state, - nm_device_ip_state_to_str(new_state)); + nm_device_ip_state_to_string(new_state)); priv->ip_state_x_[IS_IPv4] = new_state; @@ -3141,8 +3172,9 @@ _set_ip_ifindex(NMDevice *self, int ifindex, const char *ifname) nm_platform_process_events_ensure_link(platform, priv->ip_ifindex, priv->ip_iface); - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) - nm_platform_link_set_user_ipv6ll_enabled(platform, priv->ip_ifindex, TRUE); + nm_platform_link_set_inet6_addr_gen_mode(platform, + priv->ip_ifindex, + NM_IN6_ADDR_GEN_MODE_NONE); if (!nm_platform_link_is_up(platform, priv->ip_ifindex)) nm_platform_link_change_flags(platform, priv->ip_ifindex, IFF_UP, TRUE); @@ -3444,7 +3476,7 @@ _stats_set_refresh_rate(NMDevice *self, guint refresh_rate_ms) if (_stats_refresh_rate_real(old_rate) == refresh_rate_ms) return; - nm_clear_g_source(&priv->stats.timeout_id); + nm_clear_g_source_inst(&priv->stats.timeout_source); if (!refresh_rate_ms) return; @@ -3456,7 +3488,7 @@ _stats_set_refresh_rate(NMDevice *self, guint refresh_rate_ms) if (ifindex > 0) nm_platform_link_refresh(nm_device_get_platform(self), ifindex); - priv->stats.timeout_id = g_timeout_add(refresh_rate_ms, _stats_timeout_cb, self); + priv->stats.timeout_source = nm_g_timeout_add_source(refresh_rate_ms, _stats_timeout_cb, self); } /*****************************************************************************/ @@ -4509,7 +4541,7 @@ concheck_cb(NMConnectivity * connectivity, seq = handle->seq; _LOGT(LOGD_CONCHECK, - "connectivity: [Ipv%c] complete check (seq:%llu, state:%s)", + "connectivity: [IPv%c] complete check (seq:%llu, state:%s)", nm_utils_addr_family_to_char(handle->addr_family), (long long unsigned) handle->seq, nm_connectivity_state_to_string(state)); @@ -5803,7 +5835,7 @@ nm_device_update_from_platform_link(NMDevice *self, const NMPlatformLink *plink) _notify(self, PROP_PATH); } - if (plink && !nm_str_is_empty(plink->name) && nm_utils_strdup_reset(&priv->iface_, plink->name)) + if (plink && !nm_str_is_empty(plink->name) && nm_strdup_reset(&priv->iface_, plink->name)) _notify(self, PROP_IFACE); str = plink ? plink->driver : NULL; @@ -5976,9 +6008,10 @@ config_changed(NMConfig * config, { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->state <= NM_DEVICE_STATE_DISCONNECTED || priv->state > NM_DEVICE_STATE_ACTIVATED) { + if (priv->state <= NM_DEVICE_STATE_DISCONNECTED || priv->state >= NM_DEVICE_STATE_ACTIVATED) { priv->ignore_carrier = nm_config_data_get_ignore_carrier(config_data, self); - if (NM_FLAGS_HAS(changes, NM_CONFIG_CHANGE_VALUES)) + if (NM_FLAGS_HAS(changes, NM_CONFIG_CHANGE_VALUES) + && !nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV)) device_init_static_sriov_num_vfs(self); } } @@ -6023,7 +6056,7 @@ realize_start_setup(NMDevice * self, NMPlatform * platform; NMDeviceCapabilities capabilities = 0; NMConfig * config; - guint real_rate; + guint refresh_rate_ms; gboolean unmanaged; /* plink is a NMPlatformLink type, however, we require it to come from the platform @@ -6087,8 +6120,8 @@ realize_start_setup(NMDevice * self, if (priv->firmware_version) _notify(self, PROP_FIRMWARE_VERSION); - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) - priv->ipv6ll_handle = nm_platform_link_get_user_ipv6ll_enabled(platform, priv->ifindex); + priv->ipv6ll_handle = (nm_platform_link_get_inet6_addr_gen_mode(platform, priv->ifindex) + == NM_IN6_ADDR_GEN_MODE_NONE); if (nm_platform_link_supports_sriov(platform, priv->ifindex)) capabilities |= NM_DEVICE_CAP_SRIOV; @@ -6131,10 +6164,12 @@ realize_start_setup(NMDevice * self, nm_device_set_carrier_from_platform(self); - nm_assert(!priv->stats.timeout_id); - real_rate = _stats_refresh_rate_real(priv->stats.refresh_rate_ms); - if (real_rate) - priv->stats.timeout_id = g_timeout_add(real_rate, _stats_timeout_cb, self); + nm_assert(!priv->stats.timeout_source); + refresh_rate_ms = _stats_refresh_rate_real(priv->stats.refresh_rate_ms); + if (refresh_rate_ms > 0) { + priv->stats.timeout_source = + nm_g_timeout_add_source(refresh_rate_ms, _stats_timeout_cb, self); + } klass->realize_start_notify(self, plink); @@ -6320,7 +6355,7 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) _notify(self, PROP_PHYSICAL_PORT_ID); } - nm_clear_g_source(&priv->stats.timeout_id); + nm_clear_g_source_inst(&priv->stats.timeout_source); _stats_update_counters(self, 0, 0); priv->hw_addr_len_ = 0; @@ -6442,9 +6477,9 @@ slave_state_changed(NMDevice * slave, "slave %s state change %d (%s) -> %d (%s)", nm_device_get_iface(slave), slave_old_state, - nm_device_state_to_str(slave_old_state), + nm_device_state_to_string(slave_old_state), slave_new_state, - nm_device_state_to_str(slave_new_state)); + nm_device_state_to_string(slave_new_state)); /* Don't try to enslave slaves until the master is ready */ if (priv->state < NM_DEVICE_STATE_CONFIG) @@ -6788,7 +6823,9 @@ nm_device_slave_notify_enslave(NMDevice *self, gboolean success) priv->is_enslaved = TRUE; _notify(self, PROP_MASTER); - _notify(priv->master, PROP_SLAVES); + + nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->master)->ports_variant, g_variant_unref); + nm_gobject_notify_together(priv->master, PROP_PORTS, PROP_SLAVES); } else if (activating) { _LOGW(LOGD_DEVICE, "Activation: connection '%s' could not be enslaved", @@ -6852,8 +6889,11 @@ nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) if (priv->is_enslaved) { priv->is_enslaved = FALSE; + _notify(self, PROP_MASTER); - _notify(priv->master, PROP_SLAVES); + + nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->master)->ports_variant, g_variant_unref); + nm_gobject_notify_together(priv->master, PROP_PORTS, PROP_SLAVES); } } @@ -7339,7 +7379,7 @@ nm_device_generate_connection(NMDevice *self, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, NM_IN6_ADDR_GEN_MODE_EUI64, NM_SETTING_IP6_CONFIG_TOKEN, - nm_utils_inet6_interface_identifier_to_token(pllink->inet6_token, sbuf), + nm_utils_inet6_interface_identifier_to_token(&pllink->inet6_token, sbuf), NULL); } } @@ -7756,7 +7796,8 @@ recheck_available(gpointer user_data) now_available ? "" : "not ", new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", - nm_device_state_to_str(new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); + nm_device_state_to_string(new_state == NM_DEVICE_STATE_UNAVAILABLE ? state + : new_state)); priv->recheck_available.available_reason = NM_DEVICE_STATE_REASON_NONE; priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE; @@ -8259,7 +8300,7 @@ activate_stage1_device_prepare(NMDevice *self) priv->master_ready_id = g_signal_connect(active, "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, - (GCallback) master_ready_cb, + G_CALLBACK(master_ready_cb), self); } return; @@ -8478,10 +8519,7 @@ tc_commit(NMDevice *self) qdiscs = nm_utils_qdiscs_from_tc_setting(platform, s_tc, ip_ifindex); tfilters = nm_utils_tfilters_from_tc_setting(platform, s_tc, ip_ifindex); - if (!nm_platform_qdisc_sync(platform, ip_ifindex, qdiscs)) - return FALSE; - - if (!nm_platform_tfilter_sync(platform, ip_ifindex, tfilters)) + if (!nm_platform_tc_sync(platform, ip_ifindex, qdiscs, tfilters)) return FALSE; return TRUE; @@ -8511,13 +8549,14 @@ activate_stage2_device_config(NMDevice *self) _ethtool_state_set(self); if (!nm_device_sys_iface_state_is_external_or_assume(self)) { - if (!tc_commit(self)) { - _LOGW(LOGD_IP6, "failed applying traffic control rules"); + if (!priv->tc_committed && !tc_commit(self)) { + _LOGW(LOGD_DEVICE, "failed applying traffic control rules"); nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; } + priv->tc_committed = TRUE; } _routing_rules_sync(self, NM_TERNARY_TRUE); @@ -8981,6 +9020,7 @@ ensure_con_ip_config(NMDevice *self, int addr_family) nm_connection_get_setting_ip4_config(connection), _prop_get_connection_mdns(self), _prop_get_connection_llmnr(self), + _prop_get_connection_dns_over_tls(self), nm_device_get_route_table(self, addr_family), nm_device_get_route_metric(self, addr_family)); } else { @@ -9028,7 +9068,7 @@ dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) if (priv->dhcp_data_4.client) { /* Stop any ongoing DHCP transaction on this device */ - nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.state_sigid); + nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.notify_sigid); if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) nm_dhcp_client_stop(priv->dhcp_data_4.client, release); @@ -9251,7 +9291,7 @@ ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit) if (commit && priv->ndisc_started && ip6_addr_gen_token && nm_utils_ipv6_interface_identifier_get_from_token(&iid, ip6_addr_gen_token)) { - set_ipv6_token(self, iid, ip6_addr_gen_token); + set_ipv6_token(self, &iid, ip6_addr_gen_token); } } @@ -9291,7 +9331,7 @@ dhcp4_lease_change(NMDevice *self, NMIP4Config *config, gboolean bound) return FALSE; } - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, self, NULL, NULL, NULL, NULL); + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, NULL, NULL); return TRUE; } @@ -9373,7 +9413,7 @@ dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state) _LOGD(LOGD_DHCP4, "DHCPv4 failed (ip_state %s, was_active %d)", - nm_device_ip_state_to_str(priv->ip_state_4), + nm_device_ip_state_to_string(priv->ip_state_4), priv->dhcp_data_4.was_active); /* The client is always left running after a failure. */ @@ -9429,21 +9469,27 @@ dhcp4_dad_cb(NMDevice *self, NMIP4Config **configs, gboolean success) } static void -dhcp4_state_changed(NMDhcpClient *client, - NMDhcpState state, - NMIP4Config * ip4_config, - GHashTable * options, - gpointer user_data) +dhcp4_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) { - NMDevice * self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMIP4Config * manual, **configs; + NMIP4Config * manual; + NMIP4Config ** configs; NMConnection * connection; + NMDhcpState state; + NMIP4Config * ip4_config; + GHashTable * options; + + nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET); + nm_assert(notify_data); + nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED); - g_return_if_fail(nm_dhcp_client_get_addr_family(client) == AF_INET); - g_return_if_fail(!ip4_config || NM_IS_IP4_CONFIG(ip4_config)); + state = notify_data->state_changed.dhcp_state; + ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config); + options = notify_data->state_changed.options; - _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", state); + nm_assert(!ip4_config || NM_IS_IP4_CONFIG(ip4_config)); + + _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) state); switch (state) { case NM_DHCP_STATE_BOUND: @@ -9479,6 +9525,7 @@ dhcp4_state_changed(NMDhcpClient *client, nm_connection_get_setting_ip4_config(connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); @@ -9594,10 +9641,10 @@ dhcp4_start(NMDevice *self) return NM_ACT_STAGE_RETURN_FAILURE; } - priv->dhcp_data_4.state_sigid = g_signal_connect(priv->dhcp_data_4.client, - NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_CALLBACK(dhcp4_state_changed), - self); + priv->dhcp_data_4.notify_sigid = g_signal_connect(priv->dhcp_data_4.client, + NM_DHCP_CLIENT_NOTIFY, + G_CALLBACK(dhcp4_notify), + self); if (nm_device_sys_iface_state_is_external_or_assume(self)) priv->dhcp_data_4.was_active = TRUE; @@ -9768,8 +9815,7 @@ dhcp6_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) priv->dhcp_data_6.grace_pending = FALSE; if (priv->dhcp_data_6.client) { - nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.state_sigid); - nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp6.prefix_sigid); + nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.notify_sigid); if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) nm_dhcp_client_stop(priv->dhcp_data_6.client, release); @@ -9805,7 +9851,7 @@ dhcp6_lease_change(NMDevice *self) return FALSE; } - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, self, NULL, NULL, NULL, NULL); + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, NULL, NULL); return TRUE; } @@ -9818,7 +9864,7 @@ dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state) _LOGD(LOGD_DHCP6, "DHCPv6 failed (ip_state %s, was_active %d)", - nm_device_ip_state_to_str(priv->ip_state_6), + nm_device_ip_state_to_string(priv->ip_state_6), priv->dhcp_data_6.was_active); /* The client is always left running after a failure. */ @@ -9869,20 +9915,34 @@ clear_config: } static void -dhcp6_state_changed(NMDhcpClient *client, - NMDhcpState state, - NMIP6Config * ip6_config, - GHashTable * options, - gpointer user_data) +dhcp6_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) { - NMDevice * self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gs_free char * event_id = NULL; + NMDhcpState state; + NMIP6Config * ip6_config; + GHashTable * options; + + nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET6); + nm_assert(notify_data); + + if (notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED) { + /* Just re-emit. The device just contributes the prefix to the + * pool in NMPolicy, which decides about subnet allocation + * on the shared devices. */ + g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, notify_data->prefix_delegated.prefix); + return; + } + + nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED); - g_return_if_fail(nm_dhcp_client_get_addr_family(client) == AF_INET6); - g_return_if_fail(!ip6_config || NM_IS_IP6_CONFIG(ip6_config)); + state = notify_data->state_changed.dhcp_state; + ip6_config = NM_IP6_CONFIG(notify_data->state_changed.ip_config); + options = notify_data->state_changed.options; - _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", state); + nm_assert(!ip6_config || NM_IS_IP6_CONFIG(ip6_config)); + + _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", (int) state); switch (state) { case NM_DHCP_STATE_BOUND: @@ -9962,17 +10022,6 @@ dhcp6_state_changed(NMDhcpClient *client, } } -static void -dhcp6_prefix_delegated(NMDhcpClient *client, NMPlatformIP6Address *prefix, gpointer user_data) -{ - NMDevice *self = NM_DEVICE(user_data); - - /* Just re-emit. The device just contributes the prefix to the - * pool in NMPolicy, which decides about subnet allocation - * on the shared devices. */ - g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, prefix); -} - /*****************************************************************************/ static gboolean @@ -10054,14 +10103,10 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) return FALSE; } - priv->dhcp_data_6.state_sigid = g_signal_connect(priv->dhcp_data_6.client, - NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_CALLBACK(dhcp6_state_changed), - self); - priv->dhcp6.prefix_sigid = g_signal_connect(priv->dhcp_data_6.client, - NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED, - G_CALLBACK(dhcp6_prefix_delegated), - self); + priv->dhcp_data_6.notify_sigid = g_signal_connect(priv->dhcp_data_6.client, + NM_DHCP_CLIENT_NOTIFY, + G_CALLBACK(dhcp6_notify), + self); if (nm_device_sys_iface_state_is_external_or_assume(self)) priv->dhcp_data_6.was_active = TRUE; @@ -10321,12 +10366,12 @@ check_and_add_ipv6ll_addr(NMDevice *self) const char * stable_id; stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); - if (!nm_utils_ipv6_addr_set_stable_privacy(stable_type, - &lladdr, - nm_device_get_iface(self), - stable_id, - priv->linklocal6_dad_counter++, - &error)) { + if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(stable_type, + &lladdr, + nm_device_get_iface(self), + stable_id, + priv->linklocal6_dad_counter++, + &error)) { _LOGW(LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); g_clear_error(&error); linklocal6_failed(self); @@ -10348,7 +10393,7 @@ check_and_add_ipv6ll_addr(NMDevice *self) _LOGW(LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); return; } - nm_utils_ipv6_addr_set_interface_identifier(&lladdr, iid); + nm_utils_ipv6_addr_set_interface_identifier(&lladdr, &iid); addr_type = "EUI-64"; } @@ -10616,9 +10661,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) _LOGT(LOGD_DEVICE, "mtu: value %u from source '%s' (%u), current source '%s' (%u)%s", (guint) mtu, - nm_device_mtu_source_to_str(source), + nm_device_mtu_source_to_string(source), (guint) source, - nm_device_mtu_source_to_str(priv->mtu_source), + nm_device_mtu_source_to_string(priv->mtu_source), (guint) priv->mtu_source, force ? " (forced)" : ""); } @@ -10801,7 +10846,7 @@ nm_device_commit_mtu(NMDevice *self) } else _LOGT(LOGD_DEVICE, "mtu: commit-mtu... skip due to state %s", - nm_device_state_to_str(state)); + nm_device_state_to_string(state)); } static void @@ -10809,66 +10854,68 @@ ndisc_config_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int { NMNDiscConfigMap changed = changed_int; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int ifindex; guint i; g_return_if_fail(priv->act_request.obj); + ifindex = nm_device_get_ip_ifindex(self); + + if (ifindex <= 0 + || (applied_config_get_current(&priv->ac_ip6_config) + && ifindex + != nm_ip_config_get_ifindex(applied_config_get_current(&priv->ac_ip6_config)))) + applied_config_clear(&priv->ac_ip6_config); + + if (ifindex <= 0) + return; + if (!applied_config_get_current(&priv->ac_ip6_config)) applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6); if (changed & NM_NDISC_CONFIG_ADDRESSES) { - guint8 plen; guint32 ifa_flags; /* Check, whether kernel is recent enough to help user space handling RA. * If it's not supported, we have no ipv6-privacy and must add autoconf * addresses as /128. The reason for the /128 is to prevent the kernel * from adding a prefix route for this address. */ - ifa_flags = 0; - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) { - ifa_flags |= IFA_F_NOPREFIXROUTE; - if (NM_IN_SET(priv->ndisc_use_tempaddr, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) - ifa_flags |= IFA_F_MANAGETEMPADDR; - plen = 64; - } else - plen = 128; + ifa_flags = IFA_F_NOPREFIXROUTE; + if (NM_IN_SET(priv->ndisc_use_tempaddr, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) + ifa_flags |= IFA_F_MANAGETEMPADDR; nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.orig, rdata->addresses, rdata->addresses_n, - plen, + 64, ifa_flags); if (priv->ac_ip6_config.current) { nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.current, rdata->addresses, rdata->addresses_n, - plen, + 64, ifa_flags); } } if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) { - nm_ip6_config_reset_routes_ndisc( - (NMIP6Config *) priv->ac_ip6_config.orig, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6), - nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); + nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.orig, + rdata->gateways, + rdata->gateways_n, + rdata->routes, + rdata->routes_n, + nm_device_get_route_table(self, AF_INET6), + nm_device_get_route_metric(self, AF_INET6)); if (priv->ac_ip6_config.current) { - nm_ip6_config_reset_routes_ndisc( - (NMIP6Config *) priv->ac_ip6_config.current, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6), - nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); + nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.current, + rdata->gateways, + rdata->gateways_n, + rdata->routes, + rdata->routes_n, + nm_device_get_route_table(self, AF_INET6), + nm_device_get_route_metric(self, AF_INET6)); } } @@ -11024,6 +11071,11 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) guint32 ra_timeout; guint32 default_ra_timeout; + if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) { + _LOGI(LOGD_IP6, "addrconf6: kernel does not support IPv6"); + return FALSE; + } + connection = nm_device_get_applied_connection(self); g_assert(connection); @@ -11037,17 +11089,17 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) g_assert(s_ip6); if (nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET6), - NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + NM_SETTING_IP6_CONFIG_METHOD_SHARED)) node_type = NM_NDISC_NODE_TYPE_ROUTER; else node_type = NM_NDISC_NODE_TYPE_HOST; - nm_lndp_ndisc_get_sysctl(nm_device_get_platform(self), - nm_device_get_ip_iface(self), - &max_addresses, - &router_solicitations, - &router_solicitation_interval, - &default_ra_timeout); + nm_ndisc_get_sysctl(nm_device_get_platform(self), + nm_device_get_ip_iface(self), + &max_addresses, + &router_solicitations, + &router_solicitation_interval, + &default_ra_timeout); if (node_type == NM_NDISC_NODE_TYPE_ROUTER) ra_timeout = 0u; @@ -11078,15 +11130,6 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) priv->ndisc_use_tempaddr = use_tempaddr; - if (NM_IN_SET(use_tempaddr, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) - && !nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) { - _LOGW(LOGD_IP6, - "The kernel does not support extended IFA_FLAGS needed by NM for " - "IPv6 private addresses. This feature is not available"); - } - /* ensure link local is ready... */ if (!linklocal6_start(self)) { /* wait for the LL address to show up */ @@ -11181,21 +11224,20 @@ set_nm_ipv6ll(NMDevice *self, gboolean enable) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); int ifindex = nm_device_get_ip_ifindex(self); - if (!nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) - return; - priv->ipv6ll_handle = enable; if (ifindex > 0) { - const char *detail = enable ? "enable" : "disable"; - int r; + int r; - _LOGD(LOGD_IP6, "will %s userland IPv6LL", detail); - r = nm_platform_link_set_user_ipv6ll_enabled(nm_device_get_platform(self), ifindex, enable); + _LOGD(LOGD_IP6, "will %s userland IPv6LL", enable ? "enable" : "disable"); + r = nm_platform_link_set_inet6_addr_gen_mode(nm_device_get_platform(self), + ifindex, + enable ? NM_IN6_ADDR_GEN_MODE_NONE + : NM_IN6_ADDR_GEN_MODE_EUI64); if (r < 0) { _NMLOG(NM_IN_SET(r, -NME_PL_NOT_FOUND, -NME_PL_OPNOTSUPP) ? LOGL_DEBUG : LOGL_WARN, LOGD_IP6, "failed to %s userspace IPv6LL address handling (%s)", - detail, + enable ? "enable" : "disable", nm_strerror(r)); } @@ -11310,6 +11352,7 @@ act_stage3_ip_config_start(NMDevice * self, nm_connection_get_setting_ip4_config(connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); configs = g_new0(NMIP4Config *, 2); @@ -11521,45 +11564,6 @@ nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family) return TRUE; } -/* - * activate_stage3_ip_config_start - * - * Begin automatic/manual IP configuration - * - */ -static void -activate_stage3_ip_config_start(NMDevice *self) -{ - int ifindex; - - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); - - _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY); - - nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - - /* Device should be up before we can do anything with it */ - if ((ifindex = nm_device_get_ip_ifindex(self)) > 0 - && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex)) - _LOGW(LOGD_DEVICE, - "interface %s not up for IP configuration", - nm_device_get_ip_iface(self)); - - if (nm_device_activate_ip4_state_in_wait(self) - && !nm_device_activate_stage3_ip_start(self, AF_INET)) - return; - - if (nm_device_activate_ip6_state_in_wait(self) - && !nm_device_activate_stage3_ip_start(self, AF_INET6)) - return; - - /* Proxy */ - nm_device_set_proxy_config(self, NULL); - - check_ip_state(self, TRUE, TRUE); -} - static void fw_change_zone_cb(NMFirewalldManager * firewalld_manager, NMFirewalldManagerCallId *call_id, @@ -11642,20 +11646,19 @@ fw_change_zone(NMDevice *self) } /* - * nm_device_activate_schedule_stage3_ip_config_start + * activate_stage3_ip_config_start + * + * Begin automatic/manual IP configuration * - * Schedule IP configuration start */ -void -nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) +static void +activate_stage3_ip_config_start(NMDevice *self) { - NMDevicePrivate *priv; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); int ifindex; - g_return_if_fail(NM_IS_DEVICE(self)); - - priv = NM_DEVICE_GET_PRIVATE(self); g_return_if_fail(priv->act_request.obj); + ifindex = nm_device_get_ip_ifindex(self); /* Add the interface to the specified firewall zone */ @@ -11676,6 +11679,51 @@ nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) nm_assert(ifindex <= 0 || priv->fw_state == FIREWALL_STATE_INITIALIZED); + _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); + _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); + + _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY); + + nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); + + /* Device should be up before we can do anything with it */ + if (!nm_device_sys_iface_state_is_external(self) + && (ifindex = nm_device_get_ip_ifindex(self)) > 0 + && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex)) + _LOGW(LOGD_DEVICE, + "interface %s not up for IP configuration", + nm_device_get_ip_iface(self)); + + if (nm_device_activate_ip4_state_in_wait(self) + && !nm_device_activate_stage3_ip_start(self, AF_INET)) + return; + + if (nm_device_activate_ip6_state_in_wait(self) + && !nm_device_activate_stage3_ip_start(self, AF_INET6)) + return; + + /* Proxy */ + nm_device_set_proxy_config(self, NULL); + + check_ip_state(self, TRUE, TRUE); +} + +/* + * nm_device_activate_schedule_stage3_ip_config_start + * + * Schedule IP configuration start + */ +void +nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail(NM_IS_DEVICE(self)); + + priv = NM_DEVICE_GET_PRIVATE(self); + + g_return_if_fail(priv->act_request.obj); + activation_source_schedule(self, activate_stage3_ip_config_start, AF_INET); } @@ -11728,22 +11776,23 @@ activate_stage4_ip_config_timeout_6(NMDevice *self) activate_stage4_ip_config_timeout_x(self, AF_INET6); } +#define activate_stage4_ip_config_timeout_x_fcn(addr_family) \ + (NM_IS_IPv4(addr_family) ? activate_stage4_ip_config_timeout_4 \ + : activate_stage4_ip_config_timeout_6) + void nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family) { NMDevicePrivate *priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6)); priv = NM_DEVICE_GET_PRIVATE(self); g_return_if_fail(priv->act_request.obj); activation_source_schedule(self, - IS_IPv4 ? activate_stage4_ip_config_timeout_4 - : activate_stage4_ip_config_timeout_6, + activate_stage4_ip_config_timeout_x_fcn(addr_family), addr_family); } @@ -11963,7 +12012,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) g_return_if_fail(ip_ifindex); if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex) - && !nm_device_sys_iface_state_is_external_or_assume(self)) { + && !nm_device_sys_iface_state_is_external(self)) { nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE); if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)) _LOGW(LOGD_DEVICE, @@ -11986,7 +12035,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, @@ -12052,7 +12101,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) */ if (priv->dhcp_data_4.client && nm_device_activate_ip4_state_in_conf(self) && (nm_device_get_state(self) > NM_DEVICE_STATE_IP_CONFIG)) { - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, @@ -12425,7 +12474,7 @@ _nm_device_hash_check_invalid_keys(GHashTable * hash, g_hash_table_iter_init(&iter, hash); while (g_hash_table_iter_next(&iter, (gpointer *) &k, NULL)) { - if (nm_utils_strv_find_first((char **) whitelist, -1, k) < 0) { + if (nm_strv_find_first(whitelist, -1, k) < 0) { first_invalid_key = k; break; } @@ -12490,6 +12539,7 @@ nm_device_reactivate_ip_config(NMDevice * self, s_ip_new, _prop_get_connection_mdns(self), _prop_get_connection_llmnr(self), + _prop_get_connection_dns_over_tls(self), nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); } else { @@ -12623,7 +12673,8 @@ can_reapply_change(NMDevice * self, NM_SETTING_CONNECTION_METERED, NM_SETTING_CONNECTION_LLDP, NM_SETTING_CONNECTION_MDNS, - NM_SETTING_CONNECTION_LLMNR); + NM_SETTING_CONNECTION_LLMNR, + NM_SETTING_CONNECTION_DNS_OVER_TLS); } if (NM_IN_STRSET(setting_name, @@ -12912,12 +12963,12 @@ reapply_cb(NMDevice * self, audit_args, subject, local->message); - g_dbus_method_invocation_take_error(context, local); - local = NULL; - } else { - nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, audit_args, subject, NULL); - g_dbus_method_invocation_return_value(context, NULL); + g_dbus_method_invocation_take_error(context, g_steal_pointer(&local)); + return; } + + nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, audit_args, subject, NULL); + g_dbus_method_invocation_return_value(context, NULL); } static void @@ -14737,15 +14788,15 @@ _unmanaged_flags2str(NMUnmanagedFlags flags, NMUnmanagedFlags mask, char *buf, g tmp = buf2; while (TRUE) { if (add_separator) - nm_utils_strbuf_append_c(&b, &len, ','); + nm_strbuf_append_c(&b, &len, ','); add_separator = TRUE; tmp2 = strchr(tmp, ','); if (tmp2) tmp2[0] = '\0'; - nm_utils_strbuf_append_c(&b, &len, '!'); - nm_utils_strbuf_append_str(&b, &len, tmp); + nm_strbuf_append_c(&b, &len, '!'); + nm_strbuf_append_str(&b, &len, tmp); if (!tmp2) break; @@ -14950,7 +15001,7 @@ _set_unmanaged_flags(NMDevice * self, priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self); priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self); - if (!priv->pending_actions) { + if (priv->pending_actions.len == 0) { do_notify_has_pending_actions = TRUE; had_pending_actions = nm_device_has_pending_action(self); } @@ -15004,7 +15055,7 @@ _set_unmanaged_flags(NMDevice * self, flags, NM_PRINT_FMT_QUOTED(allow_state_transition, ", reason ", - nm_device_state_reason_to_str_a(reason), + nm_device_state_reason_to_string_a(reason), transition_state ? ", transition-state" : "", "")); @@ -15744,37 +15795,39 @@ gboolean nm_device_add_pending_action(NMDevice *self, const char *action, gboolean assert_not_yet_pending) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - GSList * iter; - guint count = 0; + gssize idx; g_return_val_if_fail(action, FALSE); - /* Check if the action is already pending. Cannot add duplicate actions */ - for (iter = priv->pending_actions; iter; iter = iter->next) { - if (nm_streq(action, iter->data)) { - if (assert_not_yet_pending) { - _LOGW(LOGD_DEVICE, - "add_pending_action (%d): '%s' already pending", - count + g_slist_length(iter), - action); - g_return_val_if_reached(FALSE); - } else { - _LOGT(LOGD_DEVICE, - "add_pending_action (%d): '%s' already pending (expected)", - count + g_slist_length(iter), - action); - } - return FALSE; + idx = nm_strv_find_binary_search(priv->pending_actions.arr, priv->pending_actions.len, action); + if (idx >= 0) { + if (assert_not_yet_pending) { + _LOGW(LOGD_DEVICE, + "add_pending_action (%u): '%s' already pending", + priv->pending_actions.len, + action); + g_return_val_if_reached(FALSE); + } else { + _LOGT(LOGD_DEVICE, + "add_pending_action (%u): '%s' already pending (expected)", + priv->pending_actions.len, + action); } - count++; + return FALSE; } - priv->pending_actions = g_slist_prepend(priv->pending_actions, (char *) action); - count++; + if (priv->pending_actions.len == priv->pending_actions.alloc) { + nm_assert(priv->pending_actions.alloc < G_MAXUINT / 2u); + priv->pending_actions.alloc = NM_MAX(priv->pending_actions.alloc * 2u, 4u); + priv->pending_actions.arr = + g_renew(const char *, priv->pending_actions.arr, priv->pending_actions.alloc); + } + nm_arr_insert_at(priv->pending_actions.arr, priv->pending_actions.len, ~idx, action); + priv->pending_actions.len++; - _LOGD(LOGD_DEVICE, "add_pending_action (%d): '%s'", count, action); + _LOGD(LOGD_DEVICE, "add_pending_action (%u): '%s'", priv->pending_actions.len, action); - if (count == 1) + if (priv->pending_actions.len == 1) _notify(self, PROP_HAS_PENDING_ACTION); return TRUE; @@ -15796,37 +15849,38 @@ gboolean nm_device_remove_pending_action(NMDevice *self, const char *action, gboolean assert_is_pending) { NMDevicePrivate *priv; - GSList * iter, *next; - guint count = 0; + gssize idx; g_return_val_if_fail(self, FALSE); g_return_val_if_fail(action, FALSE); priv = NM_DEVICE_GET_PRIVATE(self); - for (iter = priv->pending_actions; iter; iter = next) { - next = iter->next; - if (nm_streq(action, iter->data)) { - _LOGD(LOGD_DEVICE, - "remove_pending_action (%d): '%s'", - count + g_slist_length(iter->next), /* length excluding 'iter' */ - action); - priv->pending_actions = g_slist_delete_link(priv->pending_actions, iter); - if (priv->pending_actions == NULL) - _notify(self, PROP_HAS_PENDING_ACTION); - return TRUE; - } - count++; + idx = nm_strv_find_binary_search(priv->pending_actions.arr, priv->pending_actions.len, action); + if (idx >= 0) { + _LOGD(LOGD_DEVICE, + "remove_pending_action (%u): '%s'", + priv->pending_actions.len - 1u, + action); + nm_arr_remove_at(priv->pending_actions.arr, priv->pending_actions.len, idx); + priv->pending_actions.len--; + if (priv->pending_actions.len == 0) + _notify(self, PROP_HAS_PENDING_ACTION); + return TRUE; } if (assert_is_pending) { - _LOGW(LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending", count, action); + _LOGW(LOGD_DEVICE, + "remove_pending_action (%u): '%s' not pending", + priv->pending_actions.len, + action); g_return_val_if_reached(FALSE); - } else + } else { _LOGT(LOGD_DEVICE, - "remove_pending_action (%d): '%s' not pending (expected)", - count, + "remove_pending_action (%u): '%s' not pending (expected)", + priv->pending_actions.len, action); + } return FALSE; } @@ -15836,15 +15890,15 @@ nm_device_has_pending_action_reason(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->pending_actions) { - if (!priv->pending_actions->next && nm_device_get_state(self) == NM_DEVICE_STATE_ACTIVATED - && nm_streq(priv->pending_actions->data, NM_PENDING_ACTION_CARRIER_WAIT)) { + if (priv->pending_actions.len > 0) { + if (priv->pending_actions.len == 1 && nm_device_get_state(self) == NM_DEVICE_STATE_ACTIVATED + && nm_streq(priv->pending_actions.arr[0], NM_PENDING_ACTION_CARRIER_WAIT)) { /* if the device is already in activated state, and the only reason * why it appears still busy is "carrier-wait", then we are already complete. */ return NULL; } - return priv->pending_actions->data; + return priv->pending_actions.arr[0]; } if (nm_device_is_real(self) @@ -16014,7 +16068,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu else _LOGD(LOGD_DEVICE, "deactivating device (reason '%s') [%d]", - nm_device_state_reason_to_str_a(reason), + nm_device_state_reason_to_string_a(reason), reason); /* Save whether or not we tried IPv6 for later */ @@ -16045,15 +16099,16 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu nm_platform_ip_route_flush(platform, AF_UNSPEC, ifindex); nm_platform_ip_address_flush(platform, AF_UNSPEC, ifindex); - set_ipv6_token(self, iid, "::"); + set_ipv6_token(self, &iid, "::"); if (nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG)) { - nm_platform_tfilter_sync(platform, ifindex, NULL); - nm_platform_qdisc_sync(platform, ifindex, NULL); + nm_platform_tc_sync(platform, ifindex, NULL, NULL); } } } + priv->tc_committed = FALSE; + _routing_rules_sync(self, cleanup_type == CLEANUP_TYPE_KEEP ? NM_TERNARY_DEFAULT : NM_TERNARY_FALSE); @@ -16508,20 +16563,20 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, && (state != NM_DEVICE_STATE_UNAVAILABLE || !priv->firmware_missing)) { _LOGD(LOGD_DEVICE, "state change: %s -> %s (reason '%s', sys-iface-state: '%s'%s)", - nm_device_state_to_str(old_state), - nm_device_state_to_str(state), - nm_device_state_reason_to_str_a(reason), - nm_device_sys_iface_state_to_str(priv->sys_iface_state), + nm_device_state_to_string(old_state), + nm_device_state_to_string(state), + nm_device_state_reason_to_string_a(reason), + nm_device_sys_iface_state_to_string(priv->sys_iface_state), priv->firmware_missing ? ", missing firmware" : ""); return; } _LOGI(LOGD_DEVICE, "state change: %s -> %s (reason '%s', sys-iface-state: '%s')", - nm_device_state_to_str(old_state), - nm_device_state_to_str(state), - nm_device_state_reason_to_str_a(reason), - nm_device_sys_iface_state_to_str(priv->sys_iface_state)); + nm_device_state_to_string(old_state), + nm_device_state_to_string(state), + nm_device_state_reason_to_string_a(reason), + nm_device_sys_iface_state_to_string(priv->sys_iface_state)); /* in order to prevent triggering any callback caused * by the device not having any pending action anymore @@ -16866,8 +16921,8 @@ queued_state_set(gpointer user_data) _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "change state"); @@ -16879,7 +16934,7 @@ queued_state_set(gpointer user_data) new_reason = priv->queued_state.reason; nm_device_state_changed(self, new_state, new_reason); - nm_device_remove_pending_action(self, nm_device_state_queued_state_to_str(new_state), TRUE); + nm_device_remove_pending_action(self, nm_device_state_queued_state_to_string(new_state), TRUE); return G_SOURCE_REMOVE; } @@ -16896,13 +16951,13 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r if (priv->queued_state.id && priv->queued_state.state == state) { _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s%s%s%s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "ignore queuing same state change", NM_PRINT_FMT_QUOTED(priv->queued_state.reason != reason, " (reason differs: ", - nm_device_state_reason_to_str_a(reason), + nm_device_state_reason_to_string_a(reason), ")", "")); return; @@ -16910,20 +16965,20 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r /* Add pending action for the new state before clearing the queued states, so * that we don't accidentally pop all pending states and reach 'startup complete' */ - nm_device_add_pending_action(self, nm_device_state_queued_state_to_str(state), TRUE); + nm_device_add_pending_action(self, nm_device_state_queued_state_to_string(state), TRUE); /* We should only ever have one delayed state transition at a time */ if (priv->queued_state.id) { _LOGW(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "replace previously queued state change"); nm_clear_g_source(&priv->queued_state.id); nm_device_remove_pending_action( self, - nm_device_state_queued_state_to_str(priv->queued_state.state), + nm_device_state_queued_state_to_string(priv->queued_state.state), TRUE); } @@ -16933,8 +16988,8 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(state), - nm_device_state_reason_to_str_a(reason), + nm_device_state_to_string(state), + nm_device_state_reason_to_string_a(reason), priv->queued_state.id, "queue state change"); } @@ -16949,14 +17004,15 @@ queued_state_clear(NMDevice *self) _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "clear queued state change"); nm_clear_g_source(&priv->queued_state.id); - nm_device_remove_pending_action(self, - nm_device_state_queued_state_to_str(priv->queued_state.state), - TRUE); + nm_device_remove_pending_action( + self, + nm_device_state_queued_state_to_string(priv->queued_state.state), + TRUE); } NMDeviceState @@ -17069,11 +17125,11 @@ nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); guint8 buf[_NM_UTILS_HWADDR_LEN_MAX]; - size_t len = 0; gboolean success_read; int ifindex; const NMPlatformLink * pllink; const NMConfigDeviceStateData *dev_state; + NMPLinkAddress cached_hw_addr_perm; if (priv->hw_addr_perm) { /* the permanent hardware address is only read once and not @@ -17112,11 +17168,13 @@ nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze) return; } - success_read = - nm_platform_link_get_permanent_address(nm_device_get_platform(self), ifindex, buf, &len); - if (success_read && priv->hw_addr_len == len) { + success_read = nm_platform_link_get_permanent_address(nm_device_get_platform(self), + pllink, + &cached_hw_addr_perm); + if (success_read && priv->hw_addr_len == cached_hw_addr_perm.len) { priv->hw_addr_perm_fake = FALSE; - priv->hw_addr_perm = nm_utils_hwaddr_ntoa(buf, len); + priv->hw_addr_perm = + nm_utils_hwaddr_ntoa(cached_hw_addr_perm.data, cached_hw_addr_perm.len); _LOGD(LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", priv->hw_addr_perm); goto notify_and_out; } @@ -17791,7 +17849,7 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use gboolean valid; resolver->hostname = g_steal_pointer(&output); - valid = nm_hostname_manager_validate_hostname(resolver->hostname); + valid = nm_utils_validate_hostname(resolver->hostname); _LOGD(LOGD_DNS, "hostname-from-dns: lookup done for %s, result %s%s%s%s", @@ -17800,7 +17858,7 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use valid ? "" : " (invalid)"); if (!valid) - g_clear_pointer(&resolver->hostname, g_free); + nm_clear_g_free(&resolver->hostname); } nm_clear_g_cancellable(&resolver->cancellable); @@ -18022,6 +18080,37 @@ _activation_func_to_string(ActivationHandleFunc func) g_return_val_if_reached("unknown"); } +static GVariant * +_device_get_ports_variant(NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(device); + SlaveInfo * info; + GVariantBuilder builder; + gboolean any = FALSE; + + if (priv->ports_variant) + return priv->ports_variant; + + c_list_for_each_entry (info, &priv->slaves, lst_slave) { + const char *path; + + if (!NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved) + continue; + path = nm_dbus_object_get_path(NM_DBUS_OBJECT(info->slave)); + if (!path) + continue; + if (!any) { + any = TRUE; + g_variant_builder_init(&builder, G_VARIANT_TYPE("ao")); + } + g_variant_builder_add(&builder, "o", path); + } + priv->ports_variant = any ? g_variant_ref_sink(g_variant_builder_end(&builder)) + : g_variant_ref(nm_g_variant_singleton_ao()); + + return priv->ports_variant; +} + /*****************************************************************************/ static void @@ -18188,29 +18277,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_boolean(value, nm_device_is_real(self)); break; case PROP_SLAVES: - { - CList *slave_iter; - char **slave_list; - gsize i, n; - - n = c_list_length(&priv->slaves); - slave_list = g_new(char *, n + 1); - i = 0; - c_list_for_each (slave_iter, &priv->slaves) { - SlaveInfo * info = c_list_entry(slave_iter, SlaveInfo, lst_slave); - const char *path; - - if (!NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved) - continue; - path = nm_dbus_object_get_path(NM_DBUS_OBJECT(info->slave)); - if (path) - slave_list[i++] = g_strdup(path); - } - nm_assert(i <= n); - slave_list[i] = NULL; - g_value_take_boxed(value, slave_list); + case PROP_PORTS: + g_value_set_variant(value, _device_get_ports_variant(self)); break; - } case PROP_STATISTICS_REFRESH_RATE_MS: g_value_set_uint(value, priv->stats.refresh_rate_ms); break; @@ -18518,7 +18587,7 @@ dispose(GObject *object) nm_clear_g_source(&priv->check_delete_unrealized_id); - nm_clear_g_source(&priv->stats.timeout_id); + nm_clear_g_source_inst(&priv->stats.timeout_source); carrier_disconnected_action_cancel(self); @@ -18573,7 +18642,7 @@ finalize(GObject *object) g_free(priv->hw_addr); g_free(priv->hw_addr_perm); g_free(priv->hw_addr_initial); - g_slist_free(priv->pending_actions); + g_free(priv->pending_actions.arr); g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); nm_clear_g_free(&priv->physical_port_id); g_free(priv->udi); @@ -18592,6 +18661,8 @@ finalize(GObject *object) nm_dbus_track_obj_path_deinit(&priv->parent_device); nm_dbus_track_obj_path_deinit(&priv->act_request); + nm_g_variant_unref(priv->ports_variant); + G_OBJECT_CLASS(nm_device_parent_class)->finalize(object); /* for testing, NMDeviceTest does not invoke NMDevice::constructed, @@ -18710,9 +18781,8 @@ static const NMDBusInterfaceInfoExtended interface_info_device = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("InterfaceFlags", "u", NM_DEVICE_INTERFACE_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), ), ), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ports", "ao", NM_DEVICE_PORTS), ), ), }; static const NMDBusInterfaceInfoExtended interface_info_device_statistics = { @@ -19007,11 +19077,18 @@ nm_device_class_init(NMDeviceClass *klass) "", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_SLAVES] = g_param_spec_boxed(NM_DEVICE_SLAVES, - "", - "", - G_TYPE_STRV, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SLAVES] = g_param_spec_variant(NM_DEVICE_SLAVES, + "", + "", + G_VARIANT_TYPE("ao"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_PORTS] = g_param_spec_variant(NM_DEVICE_PORTS, + "", + "", + G_VARIANT_TYPE("ao"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATISTICS_REFRESH_RATE_MS] = g_param_spec_uint(NM_DEVICE_STATISTICS_REFRESH_RATE_MS, @@ -19113,16 +19190,17 @@ nm_device_class_init(NMDeviceClass *klass) G_TYPE_OBJECT, G_TYPE_OBJECT); - signals[IP6_PREFIX_DELEGATED] = g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); + signals[IP6_PREFIX_DELEGATED] = + g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_POINTER /* const NMPlatformIP6Address *prefix */); signals[IP6_SUBNET_NEEDED] = g_signal_new(NM_DEVICE_IP6_SUBNET_NEEDED, G_OBJECT_CLASS_TYPE(object_class), diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index f59b6fa8..d967bcb2 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -45,6 +45,7 @@ #define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id" #define NM_DEVICE_MTU "mtu" #define NM_DEVICE_HW_ADDRESS "hw-address" +#define NM_DEVICE_PORTS "ports" /* "perm-hw-address" is exposed on D-Bus both for NMDeviceEthernet * and NMDeviceWifi. */ diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index aba972ae..4e178491 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -32,7 +32,7 @@ /*****************************************************************************/ struct _NMLldpListener { - sd_lldp * lldp_handle; + sd_lldp_rx *lldp_handle; GHashTable *lldp_neighbors; GVariant * variant; @@ -711,9 +711,9 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh) g_variant_new_uint32(unaligned_read_be16(data8)); break; } - } else if (memcmp(oui, SD_LLDP_OUI_MUD, sizeof(oui)) == 0) { + } else if (memcmp(oui, SD_LLDP_OUI_IANA, sizeof(oui)) == 0) { switch (subtype) { - case SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION: + case SD_LLDP_OUI_IANA_SUBTYPE_MUD: if (!v_mud_url) { gs_free char *s_free = NULL; const char * s; @@ -884,12 +884,14 @@ handle_changed: } static void -lldp_event_handler(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n, void *userdata) +lldp_event_handler(sd_lldp_rx *lldp, sd_lldp_rx_event_t event, sd_lldp_neighbor *n, void *userdata) { - process_lldp_neighbor( - userdata, - n, - !NM_IN_SET(event, SD_LLDP_EVENT_ADDED, SD_LLDP_EVENT_UPDATED, SD_LLDP_EVENT_REFRESHED)); + process_lldp_neighbor(userdata, + n, + !NM_IN_SET(event, + SD_LLDP_RX_EVENT_ADDED, + SD_LLDP_RX_EVENT_UPDATED, + SD_LLDP_RX_EVENT_REFRESHED)); } /*****************************************************************************/ @@ -934,14 +936,14 @@ nm_lldp_listener_new(int ifindex, GError ** error) { NMLldpListener *self = NULL; - sd_lldp * lldp_handle; + sd_lldp_rx * lldp_handle; int r; g_return_val_if_fail(ifindex > 0, FALSE); g_return_val_if_fail(!error || !*error, FALSE); g_return_val_if_fail(notify_callback, FALSE); - r = sd_lldp_new(&lldp_handle); + r = sd_lldp_rx_new(&lldp_handle); if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, @@ -950,7 +952,7 @@ nm_lldp_listener_new(int ifindex, return FALSE; } - r = sd_lldp_set_ifindex(lldp_handle, ifindex); + r = sd_lldp_rx_set_ifindex(lldp_handle, ifindex); if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, @@ -959,7 +961,7 @@ nm_lldp_listener_new(int ifindex, goto fail_handle; } - r = sd_lldp_set_neighbors_max(lldp_handle, MAX_NEIGHBORS); + r = sd_lldp_rx_set_neighbors_max(lldp_handle, MAX_NEIGHBORS); nm_assert(r == 0); self = g_slice_new(NMLldpListener); @@ -969,19 +971,19 @@ nm_lldp_listener_new(int ifindex, .notify_user_data = notify_user_data, }; - r = sd_lldp_set_callback(lldp_handle, lldp_event_handler, self); + r = sd_lldp_rx_set_callback(lldp_handle, lldp_event_handler, self); if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "set callback failed"); goto fail_handle; } - r = sd_lldp_attach_event(lldp_handle, NULL, 0); + r = sd_lldp_rx_attach_event(lldp_handle, NULL, 0); if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "attach event failed"); goto fail_attached; } - r = sd_lldp_start(lldp_handle); + r = sd_lldp_rx_start(lldp_handle); if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "start failed"); goto fail_attached; @@ -997,11 +999,11 @@ nm_lldp_listener_new(int ifindex, return self; fail_attached: - sd_lldp_detach_event(lldp_handle); + sd_lldp_rx_detach_event(lldp_handle); fail_handle: if (self) nm_g_slice_free(self); - sd_lldp_unref(lldp_handle); + sd_lldp_rx_unref(lldp_handle); return NULL; } @@ -1010,9 +1012,9 @@ nm_lldp_listener_destroy(NMLldpListener *self) { g_return_if_fail(self); - sd_lldp_stop(self->lldp_handle); - sd_lldp_detach_event(self->lldp_handle); - sd_lldp_unref(self->lldp_handle); + sd_lldp_rx_stop(self->lldp_handle); + sd_lldp_rx_detach_event(self->lldp_handle); + sd_lldp_rx_unref(self->lldp_handle); nm_clear_g_source_inst(&self->ratelimit_source); diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index b8d5311a..e5673347 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -17,6 +17,7 @@ #include "devices/nm-device.h" #include "nm-manager.h" #include "nm-setting-ovs-external-ids.h" +#include "nm-priv-helper-call.h" /*****************************************************************************/ @@ -25,7 +26,7 @@ /*****************************************************************************/ #if JANSSON_VERSION_HEX < 0x020400 - #warning "requires at least libjansson 2.4" +#warning "requires at least libjansson 2.4" #endif typedef struct { @@ -118,9 +119,8 @@ enum { static guint signals[LAST_SIGNAL] = {0}; typedef struct { - GSocketClient * client; GSocketConnection *conn; - GCancellable * cancellable; + GCancellable * conn_cancellable; char buf[4096]; /* Input buffer */ size_t bufp; /* Last decoded byte in the input buffer. */ GString * input; /* JSON stream waiting for decoding. */ @@ -753,6 +753,7 @@ _insert_interface(json_t * params, NMSettingOvsInterface *s_ovs_iface; NMSettingOvsDpdk * s_ovs_dpdk; NMSettingOvsPatch * s_ovs_patch; + const char * dpdk_devargs; json_t * options = json_array(); json_t * row; guint32 mtu = 0; @@ -777,9 +778,11 @@ _insert_interface(json_t * params, s_ovs_patch = nm_connection_get_setting_ovs_patch(interface); if (s_ovs_dpdk) { - json_array_append_new( - options, - json_pack("[[s, s]]", "dpdk-devargs", nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk))); + dpdk_devargs = nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk); + if (dpdk_devargs) + json_array_append_new(options, json_pack("[[s, s]]", "dpdk-devargs", dpdk_devargs)); + else + json_array_append_new(options, json_array()); } else if (s_ovs_patch) { json_array_append_new( options, @@ -1595,7 +1598,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) iter = json_object_iter(ovs); s = json_object_iter_key(iter); if (s) - nm_utils_strdup_reset(&priv->db_uuid, s); + nm_strdup_reset(&priv->db_uuid, s); } json_object_foreach (interface, key, value) { @@ -1665,8 +1668,8 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_assert(nm_streq0(ovs_interface->name, name)); - changed |= nm_utils_strdup_reset(&ovs_interface->type, type); - changed |= nm_utils_strdup_reset(&ovs_interface->connection_uuid, connection_uuid); + changed |= nm_strdup_reset(&ovs_interface->type, type); + changed |= nm_strdup_reset(&ovs_interface->connection_uuid, connection_uuid); if (!_external_ids_equal(ovs_interface->external_ids, external_ids_arr)) { NM_SWAP(&ovs_interface->external_ids, &external_ids_arr); changed = TRUE; @@ -1776,8 +1779,8 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_assert(nm_streq0(ovs_port->name, name)); - changed |= nm_utils_strdup_reset(&ovs_port->name, name); - changed |= nm_utils_strdup_reset(&ovs_port->connection_uuid, connection_uuid); + changed |= nm_strdup_reset(&ovs_port->name, name); + changed |= nm_strdup_reset(&ovs_port->connection_uuid, connection_uuid); if (nm_strv_ptrarray_cmp(ovs_port->interfaces, interfaces) != 0) { NM_SWAP(&ovs_port->interfaces, &interfaces); changed = TRUE; @@ -1881,8 +1884,8 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_assert(nm_streq0(ovs_bridge->name, name)); - changed = nm_utils_strdup_reset(&ovs_bridge->name, name); - changed = nm_utils_strdup_reset(&ovs_bridge->connection_uuid, connection_uuid); + changed = nm_strdup_reset(&ovs_bridge->name, name); + changed = nm_strdup_reset(&ovs_bridge->connection_uuid, connection_uuid); if (nm_strv_ptrarray_cmp(ovs_bridge->ports, ports) != 0) { NM_SWAP(&ovs_bridge->ports, &ports); changed = TRUE; @@ -2223,7 +2226,7 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) nm_assert(!retry || !is_disposing); - if (!priv->client) + if (!priv->conn && !priv->conn_cancellable) return; _LOGD("disconnecting from ovsdb, retry %d", retry); @@ -2250,10 +2253,9 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) priv->bufp = 0; g_string_truncate(priv->input, 0); g_string_truncate(priv->output, 0); - g_clear_object(&priv->client); g_clear_object(&priv->conn); nm_clear_g_free(&priv->db_uuid); - nm_clear_g_cancellable(&priv->cancellable); + nm_clear_g_cancellable(&priv->conn_cancellable); if (retry) ovsdb_try_connect(self); @@ -2348,32 +2350,82 @@ _monitor_bridges_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_ } static void -_client_connect_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) +_ovsdb_connect_complete_with_fd(NMOvsdb *self, int fd_take) { - GSocketClient * client = G_SOCKET_CLIENT(source_object); - NMOvsdb * self = NM_OVSDB(user_data); - NMOvsdbPrivate * priv; - GError * error = NULL; - GSocketConnection *conn; - - conn = g_socket_client_connect_finish(client, res, &error); - if (conn == NULL) { - if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - _LOGI("%s", error->message); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + gs_unref_object GSocket *socket = NULL; + gs_free_error GError *error = NULL; + socket = g_socket_new_from_fd(nm_steal_fd(&fd_take), &error); + if (!socket) { + _LOGT("connect: failure to open socket for new FD: %s", error->message); ovsdb_disconnect(self, FALSE, FALSE); - g_clear_error(&error); return; } - priv = NM_OVSDB_GET_PRIVATE(self); - priv->conn = conn; - g_clear_object(&priv->cancellable); + priv->conn = g_socket_connection_factory_create_connection(socket); + g_clear_object(&priv->conn_cancellable); ovsdb_read(self); ovsdb_next_command(self); } +static void +_ovsdb_connect_priv_helper_cb(int fd_take, GError *error, gpointer user_data) +{ + nm_auto_close int fd = fd_take; + NMOvsdb * self; + + if (nm_utils_error_is_cancelled(error)) + return; + + self = user_data; + + if (error) { + _LOGT("connect: failure to get FD from nm-priv-helper: %s", error->message); + ovsdb_disconnect(self, FALSE, FALSE); + return; + } + + _LOGT("connect: connected successfully with FD from nm-priv-helper"); + _ovsdb_connect_complete_with_fd(self, nm_steal_fd(&fd)); +} + +static void +_ovsdb_connect_idle(gpointer user_data, GCancellable *cancellable) +{ + NMOvsdb * self; + NMOvsdbPrivate * priv; + nm_auto_close int fd = -1; + gs_free_error GError *error = NULL; + + if (g_cancellable_is_cancelled(cancellable)) + return; + + self = user_data; + priv = NM_OVSDB_GET_PRIVATE(self); + + fd = nm_priv_helper_utils_open_fd(NM_PRIV_HELPER_GET_FD_TYPE_OVSDB_SOCKET, &error); + if (fd == -ENOENT) { + _LOGT("connect: opening %s failed (\"%s\")", NM_OVSDB_SOCKET, error->message); + ovsdb_disconnect(self, FALSE, FALSE); + return; + } + if (fd < 0) { + _LOGT("connect: opening %s failed (\"%s\"). Retry with nm-priv-helper", + NM_OVSDB_SOCKET, + error->message); + nm_priv_helper_call_get_fd(NM_PRIV_HELPER_GET_FD_TYPE_OVSDB_SOCKET, + priv->conn_cancellable, + _ovsdb_connect_priv_helper_cb, + self); + return; + } + + _LOGT("connect: opening %s succeeded", NM_OVSDB_SOCKET); + _ovsdb_connect_complete_with_fd(self, nm_steal_fd(&fd)); +} + /** * ovsdb_try_connect: * @@ -2385,22 +2437,13 @@ static void ovsdb_try_connect(NMOvsdb *self) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - GSocketAddress *addr; - if (priv->client) + if (priv->conn || priv->conn_cancellable) return; - /* TODO: This should probably be made configurable via NetworkManager.conf */ - addr = g_unix_socket_address_new(RUNSTATEDIR "/openvswitch/db.sock"); - - priv->client = g_socket_client_new(); - priv->cancellable = g_cancellable_new(); - g_socket_client_connect_async(priv->client, - G_SOCKET_CONNECTABLE(addr), - priv->cancellable, - _client_connect_cb, - self); - g_object_unref(addr); + _LOGT("connect: start connecting socket %s on idle", NM_OVSDB_SOCKET); + priv->conn_cancellable = g_cancellable_new(); + nm_utils_invoke_on_idle(priv->conn_cancellable, _ovsdb_connect_idle, self); /* Queue a monitor call before any other command, ensuring that we have an up * to date view of existing bridged that we need for add and remove ops. */ @@ -2534,12 +2577,10 @@ nm_ovsdb_set_external_ids(NMOvsdb * self, gs_unref_hashtable GHashTable *exid_old = NULL; gs_unref_hashtable GHashTable *exid_new = NULL; - exid_old = s_exid_old - ? nm_utils_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_old)) - : NULL; - exid_new = s_exid_new - ? nm_utils_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_new)) - : NULL; + exid_old = + s_exid_old ? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_old)) : NULL; + exid_new = + s_exid_new ? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_new)) : NULL; ovsdb_call_method(self, NULL, diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index 0f1a8c4c..3398e467 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -20,6 +20,7 @@ #include "devices/nm-device-private.h" #include "libnm-platform/nm-platform.h" #include "nm-config.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" #include "nm-ip4-config.h" @@ -78,8 +79,6 @@ complete_connection(NMDevice * device, NMConnection *const *existing_connections, GError ** error) { - NMSettingTeam *s_team; - nm_utils_complete_generic(nm_device_get_platform(device), connection, NM_SETTING_TEAM_SETTING_NAME, @@ -90,11 +89,7 @@ complete_connection(NMDevice * device, NULL, TRUE); - s_team = nm_connection_get_setting_team(connection); - if (!s_team) { - s_team = (NMSettingTeam *) nm_setting_team_new(); - nm_connection_add_setting(connection, NM_SETTING(s_team)); - } + _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM); return TRUE; } @@ -168,15 +163,10 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceTeam * self = NM_DEVICE_TEAM(device); - NMSettingTeam * s_team = nm_connection_get_setting_team(connection); + NMSettingTeam * s_team = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); struct teamdctl * tdc = priv->tdc; - if (!s_team) { - s_team = (NMSettingTeam *) nm_setting_team_new(); - nm_connection_add_setting(connection, (NMSetting *) s_team); - } - /* Read the configuration only if not already set */ if (!priv->config && ensure_teamd_connection(device)) teamd_read_config(self); @@ -250,11 +240,7 @@ master_update_slave_connection(NMDevice * self, return FALSE; } - s_port = nm_connection_get_setting_team_port(connection); - if (!s_port) { - s_port = (NMSettingTeamPort *) nm_setting_team_port_new(); - nm_connection_add_setting(connection, NM_SETTING(s_port)); - } + s_port = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM_PORT); g_object_set(G_OBJECT(s_port), NM_SETTING_TEAM_PORT_CONFIG, port_config, NULL); g_free(port_config); diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 56338743..27a3188b 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -18,6 +18,7 @@ #include "libnm-glib-aux/nm-ref-string.h" #include "nm-iwd-manager.h" #include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nm-setting-8021x.h" #include "nm-setting-connection.h" #include "nm-setting-wireless-security.h" @@ -966,7 +967,7 @@ complete_connection(NMDevice * device, gboolean hidden = FALSE; const char * mode; - s_wifi = nm_connection_get_setting_wireless(connection); + s_wifi = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRELESS); mode = s_wifi ? nm_setting_wireless_get_mode(s_wifi) : NULL; @@ -1031,12 +1032,6 @@ complete_connection(NMDevice * device, } ssid = nm_wifi_ap_get_ssid(ap); - - /* Add a wifi setting if one doesn't exist yet */ - if (!s_wifi) { - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - } } if (ap) { @@ -2651,7 +2646,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) break; case PROP_ACCESS_POINTS: list = nm_wifi_aps_get_paths(&priv->aps_lst_head, TRUE); - g_value_take_boxed(value, nm_utils_strv_make_deep_copied(list)); + g_value_take_boxed(value, nm_strv_make_deep_copied(list)); break; case PROP_ACTIVE_ACCESS_POINT: nm_dbus_utils_g_value_set_object_path(value, priv->current_ap); diff --git a/src/core/devices/wifi/nm-device-olpc-mesh.c b/src/core/devices/wifi/nm-device-olpc-mesh.c index 040350d5..d829f9ae 100644 --- a/src/core/devices/wifi/nm-device-olpc-mesh.c +++ b/src/core/devices/wifi/nm-device-olpc-mesh.c @@ -28,6 +28,7 @@ #include "nm-setting-connection.h" #include "nm-setting-olpc-mesh.h" #include "nm-manager.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-platform/nm-platform.h" #define _NMLOG_DEVICE_TYPE NMDeviceOlpcMesh @@ -88,11 +89,7 @@ complete_connection(NMDevice * device, { NMSettingOlpcMesh *s_mesh; - s_mesh = nm_connection_get_setting_olpc_mesh(connection); - if (!s_mesh) { - s_mesh = (NMSettingOlpcMesh *) nm_setting_olpc_mesh_new(); - nm_connection_add_setting(connection, NM_SETTING(s_mesh)); - } + s_mesh = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_OLPC_MESH); if (!nm_setting_olpc_mesh_get_ssid(s_mesh)) { gs_unref_bytes GBytes *ssid = NULL; diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index a8ea2ed7..67202a67 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -15,6 +15,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "nm-act-request.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-glib-aux/nm-ref-string.h" #include "nm-ip4-config.h" @@ -302,10 +303,7 @@ complete_connection(NMDevice * device, } /* Add a Wi-Fi P2P setting if one doesn't exist yet */ - if (!s_wifi_p2p) { - s_wifi_p2p = NM_SETTING_WIFI_P2P(nm_setting_wifi_p2p_new()); - nm_connection_add_setting(connection, NM_SETTING(s_wifi_p2p)); - } + s_wifi_p2p = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIFI_P2P); g_object_set(G_OBJECT(s_wifi_p2p), NM_SETTING_WIFI_P2P_PEER, setting_peer, NULL); @@ -560,14 +558,39 @@ act_stage3_ip_config_start(NMDevice * device, gpointer * out_config, NMDeviceStateReason *out_failure_reason) { - gboolean indicate_addressing_running; - NMConnection *connection; - const char * method; + NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device); + gboolean indicate_addressing_running; + NMConnection * connection; + const char * method; connection = nm_device_get_applied_connection(device); method = nm_utils_get_ip_config_method(connection, addr_family); + /* We may have an address assigned by the group owner */ + if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface + && !nm_supplicant_interface_get_p2p_group_owner(priv->group_iface)) { + in_addr_t addr; + guint8 plen; + + if (nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, &addr, &plen)) { + NMPlatformIP4Address address = { + .addr_source = NM_IP_CONFIG_SOURCE_DHCP, + }; + gs_unref_object NMIP4Config *ip4_config = NULL; + + nm_platform_ip4_address_set_addr(&address, addr, plen); + + ip4_config = nm_device_ip4_config_new(device); + nm_ip4_config_add_address(ip4_config, &address); + + nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG(ip4_config)); + + /* This just disables the addressing indicator. */ + method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + } + } + if (addr_family == AF_INET) indicate_addressing_running = NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO); else { @@ -622,6 +645,11 @@ get_auto_ip_config_method(NMDevice *device, int addr_family) NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); + if (addr_family == AF_INET && priv->group_iface + && !nm_supplicant_interface_get_p2p_group_owner(priv->group_iface) + && nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, NULL, NULL)) + return NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + /* Override the AUTO method to mean shared if we are group owner. */ if (priv->group_iface && nm_supplicant_interface_get_p2p_group_owner(priv->group_iface)) { if (addr_family == AF_INET) @@ -1163,7 +1191,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) switch (prop_id) { case PROP_PEERS: list = nm_wifi_p2p_peers_get_paths(&priv->peers_lst_head); - g_value_take_boxed(value, nm_utils_strv_make_deep_copied(list)); + g_value_take_boxed(value, nm_strv_make_deep_copied(list)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index fca2fde5..82896c77 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -17,6 +17,7 @@ #include "nm-device-wifi-p2p.h" #include "nm-wifi-ap.h" #include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "devices/nm-device.h" #include "devices/nm-device-private.h" #include "nm-dbus-manager.h" @@ -321,7 +322,7 @@ _scan_request_ssids_track(NMDeviceWifiPrivate *priv, const GPtrArray *ssids) now_msec = nm_utils_get_monotonic_timestamp_msec(); if (!priv->scan_request_ssids_hash) - priv->scan_request_ssids_hash = g_hash_table_new(nm_pgbytes_hash, nm_pgbytes_equal); + priv->scan_request_ssids_hash = g_hash_table_new(nm_pg_bytes_hash, nm_pg_bytes_equal); /* Do a little dance. New elements shall keep their order as in @ssids, but all * new elements should be sorted in the list preexisting elements of the list. @@ -1205,10 +1206,7 @@ complete_connection(NMDevice * device, } /* Add a wifi setting if one doesn't exist yet */ - if (!s_wifi) { - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - } + s_wifi = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRELESS); if (ap) ssid = nm_wifi_ap_get_ssid(ap); @@ -1571,7 +1569,7 @@ _scan_request_ssids_build_hidden(NMDeviceWifi *self, if (ssids) { if (ssids->len < max_scan_ssids) { /* Add wildcard SSID using a static wildcard SSID used for every scan */ - g_ptr_array_insert(ssids, 0, g_bytes_ref(nm_gbytes_get_empty())); + g_ptr_array_insert(ssids, 0, g_bytes_ref(nm_g_bytes_get_empty())); } if (ssids->len >= max_scan_ssids) { /* there is no more space. Use what we have. */ @@ -1592,10 +1590,10 @@ _scan_request_ssids_build_hidden(NMDeviceWifi *self, if (!ssids) { ssids = g_ptr_array_new_full(max_scan_ssids, (GDestroyNotify) g_bytes_unref); /* Add wildcard SSID using a static wildcard SSID used for every scan */ - g_ptr_array_insert(ssids, 0, g_bytes_ref(nm_gbytes_get_empty())); + g_ptr_array_insert(ssids, 0, g_bytes_ref(nm_g_bytes_get_empty())); } - unique_ssids = g_hash_table_new(nm_gbytes_hash, nm_gbytes_equal); + unique_ssids = g_hash_table_new(nm_g_bytes_hash, nm_g_bytes_equal); for (i = 1; i < ssids->len; i++) { if (!g_hash_table_add(unique_ssids, ssids->pdata[i])) nm_assert_not_reached(); @@ -1673,12 +1671,7 @@ _scan_supplicant_request_scan_cb(NMSupplicantInterface *supp_iface, * Artificially keep the scanning state on, for another SCAN_EXTRA_DELAY_MSEC msec. */ nm_clear_g_source_inst(&priv->scan_request_delay_source); priv->scan_request_delay_source = - nm_g_source_attach(nm_g_timeout_source_new(SCAN_EXTRA_DELAY_MSEC, - G_PRIORITY_DEFAULT, - _scan_request_delay_cb, - self, - NULL), - NULL); + nm_g_timeout_add_source(SCAN_EXTRA_DELAY_MSEC, _scan_request_delay_cb, self); g_clear_object(&priv->scan_request_cancellable); _scan_notify_is_scanning(self); @@ -3646,7 +3639,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) break; case PROP_ACCESS_POINTS: list = nm_wifi_aps_get_paths(&priv->aps_lst_head, TRUE); - g_value_take_boxed(value, nm_utils_strv_make_deep_copied(list)); + g_value_take_boxed(value, nm_strv_make_deep_copied(list)); break; case PROP_ACTIVE_ACCESS_POINT: nm_dbus_utils_g_value_set_object_path(value, priv->current_ap); diff --git a/src/core/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index 20ed6833..72a60885 100644 --- a/src/core/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -669,7 +669,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_uint(value, priv->rsn_flags); break; case PROP_SSID: - g_value_take_variant(value, nm_utils_gbytes_to_variant_ay(priv->ssid)); + g_value_take_variant(value, nm_g_bytes_to_variant_ay(priv->ssid)); break; case PROP_FREQUENCY: g_value_set_uint(value, priv->freq); diff --git a/src/core/devices/wifi/nm-wifi-common.c b/src/core/devices/wifi/nm-wifi-common.c index b98ef222..d029ce7f 100644 --- a/src/core/devices/wifi/nm-wifi-common.c +++ b/src/core/devices/wifi/nm-wifi-common.c @@ -13,7 +13,7 @@ #include "nm-dbus-manager.h" #if WITH_IWD - #include "nm-device-iwd.h" +#include "nm-device-iwd.h" #endif /*****************************************************************************/ diff --git a/src/core/devices/wifi/nm-wifi-p2p-peer.c b/src/core/devices/wifi/nm-wifi-p2p-peer.c index 433c2833..ac13952d 100644 --- a/src/core/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.c @@ -168,7 +168,7 @@ nm_wifi_p2p_peer_set_name(NMWifiP2PPeer *peer, const char *str) { NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); - if (!nm_utils_strdup_reset(&priv->name, str)) + if (!nm_strdup_reset(&priv->name, str)) return FALSE; _notify(peer, PROP_NAME); return TRUE; @@ -187,7 +187,7 @@ nm_wifi_p2p_peer_set_manufacturer(NMWifiP2PPeer *peer, const char *str) { NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); - if (!nm_utils_strdup_reset(&priv->manufacturer, str)) + if (!nm_strdup_reset(&priv->manufacturer, str)) return FALSE; _notify(peer, PROP_MANUFACTURER); return TRUE; @@ -206,7 +206,7 @@ nm_wifi_p2p_peer_set_model(NMWifiP2PPeer *peer, const char *str) { NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); - if (!nm_utils_strdup_reset(&priv->model, str)) + if (!nm_strdup_reset(&priv->model, str)) return FALSE; _notify(peer, PROP_MODEL); return TRUE; @@ -225,7 +225,7 @@ nm_wifi_p2p_peer_set_model_number(NMWifiP2PPeer *peer, const char *str) { NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); - if (!nm_utils_strdup_reset(&priv->model_number, str)) + if (!nm_strdup_reset(&priv->model_number, str)) return FALSE; _notify(peer, PROP_MODEL_NUMBER); return TRUE; @@ -244,7 +244,7 @@ nm_wifi_p2p_peer_set_serial(NMWifiP2PPeer *peer, const char *str) { NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); - if (!nm_utils_strdup_reset(&priv->serial, str)) + if (!nm_strdup_reset(&priv->serial, str)) return FALSE; _notify(peer, PROP_SERIAL); return TRUE; @@ -268,7 +268,7 @@ nm_wifi_p2p_peer_set_wfd_ies(NMWifiP2PPeer *peer, GBytes *wfd_ies) priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); - if (nm_gbytes_equal0(priv->wfd_ies, wfd_ies)) + if (nm_g_bytes_equal0(priv->wfd_ies, wfd_ies)) return FALSE; wfd_ies_old = g_steal_pointer(&priv->wfd_ies); @@ -408,9 +408,9 @@ nm_wifi_p2p_peer_update_from_properties(NMWifiP2PPeer *peer, const NMSupplicantP /* We currently only use the groups information internally to check if * the peer is still joined. */ - if (!nm_utils_strv_equal(priv->groups, peer_info->groups)) { + if (!nm_strv_equal(priv->groups, peer_info->groups)) { g_free(priv->groups); - priv->groups = nm_utils_strv_dup_packed(peer_info->groups, -1); + priv->groups = nm_strv_dup_packed(peer_info->groups, -1); changed |= TRUE; } @@ -509,7 +509,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_string(value, priv->serial); break; case PROP_WFD_IES: - g_value_take_variant(value, nm_utils_gbytes_to_variant_ay(priv->wfd_ies)); + g_value_take_variant(value, nm_g_bytes_to_variant_ay(priv->wfd_ies)); break; case PROP_HW_ADDRESS: g_value_set_string(value, priv->address); diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 15ced990..4939e786 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -13,6 +13,7 @@ #include "nm-utils.h" #include "libnm-core-intern/nm-core-internal.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-aux-intern/nm-common-macros.h" #include "libnm-base/nm-config-base.h" @@ -679,10 +680,7 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, } /* Everything else requires security */ - if (!s_wsec) { - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - } + s_wsec = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec); auth_alg = nm_setting_wireless_security_get_auth_alg(s_wsec); @@ -825,21 +823,11 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, "open", NULL); } else if (nm_streq0(key_mgmt, "sae") || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) { - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "sae", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, - "open", - NULL); + g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); } else if (nm_streq0(key_mgmt, "owe") || NM_FLAGS_ANY(ap_rsn_flags, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "owe", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, - "open", - NULL); + g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "owe", NULL); } else if (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK || ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) { g_object_set(s_wsec, @@ -853,12 +841,7 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, */ } else if (nm_streq0(key_mgmt, "wpa-eap-suite-b-192") || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)) { - g_object_set(s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "wpa-eap-suite-b-192", - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, - "open", - NULL); + g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap-suite-b-192", NULL); } else { g_set_error_literal(error, NM_CONNECTION_ERROR, diff --git a/src/core/devices/wifi/tests/test-devices-wifi.c b/src/core/devices/wifi/tests/test-devices-wifi.c index dc278c94..5d1167cf 100644 --- a/src/core/devices/wifi/tests/test-devices-wifi.c +++ b/src/core/devices/wifi/tests/test-devices-wifi.c @@ -1445,7 +1445,7 @@ do_test_ssids_options_to_ptrarray(const char *const *ssids) const char *ssid = ssids[i]; GBytes * bytes = ssids_arr->pdata[i]; - g_assert(nm_utils_gbytes_equal_mem(bytes, ssid, strlen(ssid))); + g_assert(nm_g_bytes_equal_mem(bytes, ssid, strlen(ssid))); } } diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index 4d892e6f..1b285469 100644 --- a/src/core/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -616,18 +616,20 @@ act_stage3_ip_config_start(NMDevice * device, gpointer * out_config, NMDeviceStateReason *out_failure_reason) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - - nm_assert_addr_family(addr_family); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); + gboolean autoip4 = FALSE; + NMActStageReturn ret; - if (addr_family == AF_INET) { - return nm_modem_stage3_ip4_config_start(priv->modem, - device, - NM_DEVICE_CLASS(nm_device_modem_parent_class), - out_failure_reason); - } else { + if (!NM_IS_IPv4(addr_family)) return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); - } + + ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason); + + if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4) + return ret; + + return NM_DEVICE_CLASS(nm_device_modem_parent_class) + ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); } static void diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index 0872a8a1..a5139f08 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -11,6 +11,7 @@ #include #include +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" @@ -829,11 +830,7 @@ complete_connection(NMModem * modem, if (MODEM_CAPS_3GPP2(modem_caps)) { NMSettingCdma *s_cdma; - s_cdma = nm_connection_get_setting_cdma(connection); - if (!s_cdma) { - s_cdma = (NMSettingCdma *) nm_setting_cdma_new(); - nm_connection_add_setting(connection, NM_SETTING(s_cdma)); - } + s_cdma = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_CDMA); if (!nm_setting_cdma_get_number(s_cdma)) g_object_set(G_OBJECT(s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); diff --git a/src/core/devices/wwan/nm-modem-manager.c b/src/core/devices/wwan/nm-modem-manager.c index 4fb9a378..8d087d13 100644 --- a/src/core/devices/wwan/nm-modem-manager.c +++ b/src/core/devices/wwan/nm-modem-manager.c @@ -12,9 +12,9 @@ #include #if HAVE_LIBSYSTEMD - #include +#include #else - #define sd_booted() FALSE +#define sd_booted() FALSE #endif #include "libnm-std-aux/nm-dbus-compat.h" @@ -22,7 +22,7 @@ #include "nm-modem-broadband.h" #if WITH_OFONO - #include "nm-modem-ofono.h" +#include "nm-modem-ofono.h" #endif #define MODEM_POKE_INTERVAL 120 diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index 15baa677..ccea69db 100644 --- a/src/core/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -526,48 +526,6 @@ static void ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) { NMModem *self = NM_MODEM(user_data); - guint32 i, num; - guint32 bad_dns1 = htonl(0x0A0B0C0D); - guint32 good_dns1 = htonl(0x04020201); /* GTE nameserver */ - guint32 bad_dns2 = htonl(0x0A0B0C0E); - guint32 good_dns2 = htonl(0x04020202); /* GTE nameserver */ - gboolean dns_workaround = FALSE; - - /* Work around a PPP bug (#1732) which causes many mobile broadband - * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. - * Apparently fixed in ppp-2.4.5 but we've had some reports that this is - * not the case. - * - * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6 - * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e - */ - - num = nm_ip4_config_get_num_nameservers(config); - if (num == 2) { - gboolean found1 = FALSE, found2 = FALSE; - - for (i = 0; i < num; i++) { - guint32 ns = nm_ip4_config_get_nameserver(config, i); - - if (ns == bad_dns1) - found1 = TRUE; - else if (ns == bad_dns2) - found2 = TRUE; - } - - /* Be somewhat conservative about substitutions; the "bad" nameservers - * could actually be valid in some cases, so only substitute if ppp - * returns *only* the two bad nameservers. - */ - dns_workaround = (found1 && found2); - } - - if (!num || dns_workaround) { - _LOGW("compensating for invalid PPP-provided nameservers"); - nm_ip4_config_reset_nameservers(config); - nm_ip4_config_add_nameserver(config, good_dns1); - nm_ip4_config_add_nameserver(config, good_dns2); - } g_signal_emit(self, signals[IP4_CONFIG_RESULT], 0, config, NULL); } @@ -727,7 +685,7 @@ ppp_stage3_ip_config_start(NMModem * self, NMActStageReturn nm_modem_stage3_ip4_config_start(NMModem * self, NMDevice * device, - NMDeviceClass * device_class, + gboolean * out_autoip4, NMDeviceStateReason *out_failure_reason) { NMModemPrivate * priv; @@ -740,7 +698,7 @@ nm_modem_stage3_ip4_config_start(NMModem * self, g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail(NM_IS_DEVICE(device), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail(NM_IS_DEVICE_CLASS(device_class), NM_ACT_STAGE_RETURN_FAILURE); + nm_assert(out_autoip4 && !*out_autoip4); req = nm_device_get_act_request(device); g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); @@ -774,7 +732,8 @@ nm_modem_stage3_ip4_config_start(NMModem * self, break; case NM_MODEM_IP_METHOD_AUTO: _LOGD("MODEM_IP_METHOD_AUTO"); - ret = device_class->act_stage3_ip_config_start(device, AF_INET, NULL, out_failure_reason); + *out_autoip4 = TRUE; + ret = NM_ACT_STAGE_RETURN_SUCCESS; break; default: _LOGI("IPv4 configuration disabled"); diff --git a/src/core/devices/wwan/nm-modem.h b/src/core/devices/wwan/nm-modem.h index 87162cfc..4bc81ff8 100644 --- a/src/core/devices/wwan/nm-modem.h +++ b/src/core/devices/wwan/nm-modem.h @@ -210,7 +210,7 @@ void nm_modem_act_stage2_config(NMModem *modem); NMActStageReturn nm_modem_stage3_ip4_config_start(NMModem * modem, NMDevice * device, - NMDeviceClass * device_class, + gboolean * out_autoip4, NMDeviceStateReason *out_failure_reason); NMActStageReturn nm_modem_stage3_ip6_config_start(NMModem * modem, diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index ab8243d0..f88c79c0 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -28,7 +28,7 @@ /*****************************************************************************/ -enum { SIGNAL_STATE_CHANGED, SIGNAL_PREFIX_DELEGATED, LAST_SIGNAL }; +enum { SIGNAL_NOTIFY, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; @@ -78,6 +78,7 @@ typedef struct _NMDhcpClientPrivate { NMDhcpHostnameFlags hostname_flags; NMDhcpClientFlags client_flags; bool iaid_explicit : 1; + bool is_stopped : 1; } NMDhcpClientPrivate; G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) @@ -91,6 +92,33 @@ G_STATIC_ASSERT(!(((pid_t) -1) > 0)); /*****************************************************************************/ +static void +_emit_notify(NMDhcpClient *self, const NMDhcpClientNotifyData *notify_data) +{ + g_signal_emit(G_OBJECT(self), signals[SIGNAL_NOTIFY], 0, notify_data); +} + +static void +_emit_notify_state_changed(NMDhcpClient *self, + NMDhcpState dhcp_state, + NMIPConfig * ip_config, + GHashTable * options) +{ + const NMDhcpClientNotifyData notify_data = { + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED, + .state_changed = + { + .dhcp_state = dhcp_state, + .ip_config = ip_config, + .options = options, + }, + }; + + _emit_notify(self, ¬ify_data); +} + +/*****************************************************************************/ + pid_t nm_dhcp_client_get_pid(NMDhcpClient *self) { @@ -352,8 +380,7 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_dhcp_state_to_string, NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_NOOP, "noop"), NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_TERMINATED, "terminated"), NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_TIMEOUT, "timeout"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_UNKNOWN, "unknown"), - NM_UTILS_LOOKUP_ITEM_IGNORE(__NM_DHCP_STATE_MAX), ); + NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_UNKNOWN, "unknown"), ); static NMDhcpState reason_to_state(NMDhcpClient *self, const char *iface, const char *reason) @@ -469,7 +496,7 @@ nm_dhcp_client_set_state(NMDhcpClient *self, gs_free const char **keys = NULL; guint i, nkeys; - keys = nm_utils_strdict_get_keys(options, TRUE, &nkeys); + keys = nm_strdict_get_keys(options, TRUE, &nkeys); for (i = 0; i < nkeys; i++) { _LOGD("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i])); } @@ -497,7 +524,8 @@ nm_dhcp_client_set_state(NMDhcpClient *self, } priv->state = new_state; - g_signal_emit(G_OBJECT(self), signals[SIGNAL_STATE_CHANGED], 0, new_state, ip_config, options); + + _emit_notify_state_changed(self, new_state, ip_config, options); } static gboolean @@ -607,6 +635,20 @@ nm_dhcp_client_accept(NMDhcpClient *self, GError **error) return TRUE; } +gboolean +nm_dhcp_client_can_accept(NMDhcpClient *self) +{ + gboolean can_accept; + + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); + + can_accept = !!(NM_DHCP_CLIENT_GET_CLASS(self)->accept); + + nm_assert(can_accept == (!!(NM_DHCP_CLIENT_GET_CLASS(self)->decline))); + + return can_accept; +} + gboolean nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error) { @@ -733,6 +775,11 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + if (priv->is_stopped) + return; + + priv->is_stopped = TRUE; + /* Kill the DHCP client */ old_pid = priv->pid; NM_DHCP_CLIENT_GET_CLASS(self)->stop(self, release); @@ -855,7 +902,15 @@ maybe_add_option(NMDhcpClient *self, GHashTable *hash, const char *key, GVariant void nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient *self, const NMPlatformIP6Address *prefix) { - g_signal_emit(G_OBJECT(self), signals[SIGNAL_PREFIX_DELEGATED], 0, prefix); + const NMDhcpClientNotifyData notify_data = { + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED, + .prefix_delegated = + { + .prefix = prefix, + }, + }; + + _emit_notify(self, ¬ify_data); } gboolean @@ -1124,7 +1179,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps break; case PROP_REJECT_SERVERS: /* construct-only */ - priv->reject_servers = nm_utils_strv_dup_packed(g_value_get_boxed(value), -1); + priv->reject_servers = nm_strv_dup_packed(g_value_get_boxed(value), -1); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -1142,8 +1197,6 @@ nm_dhcp_client_init(NMDhcpClient *self) priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_DHCP_CLIENT, NMDhcpClientPrivate); self->_priv = priv; - c_list_init(&self->dhcp_client_lst); - priv->pid = -1; } @@ -1175,12 +1228,7 @@ dispose(GObject *object) NMDhcpClient * self = NM_DHCP_CLIENT(object); NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - /* Stopping the client is left up to the controlling device - * explicitly since we may want to quit NetworkManager but not terminate - * the DHCP client. - */ - - nm_assert(c_list_is_empty(&self->dhcp_client_lst)); + nm_dhcp_client_stop(self, FALSE); watch_cleanup(self); timeout_cleanup(self); @@ -1369,27 +1417,15 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class) g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - signals[SIGNAL_STATE_CHANGED] = g_signal_new(NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 3, - G_TYPE_UINT, - G_TYPE_OBJECT, - G_TYPE_HASH_TABLE); - - signals[SIGNAL_PREFIX_DELEGATED] = g_signal_new(NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); + signals[SIGNAL_NOTIFY] = + g_signal_new(NM_DHCP_CLIENT_NOTIFY, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER /* const NMDhcpClientNotifyData *notify_data */); } diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index 3fe1b34e..2e7e0216 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -44,8 +44,7 @@ #define NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER "vendor-class-identifier" #define NM_DHCP_CLIENT_REJECT_SERVERS "reject-servers" -#define NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED "state-changed" -#define NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED "prefix-delegated" +#define NM_DHCP_CLIENT_NOTIFY "dhcp-notify" typedef enum { NM_DHCP_STATE_UNKNOWN = 0, @@ -57,10 +56,27 @@ typedef enum { NM_DHCP_STATE_FAIL, /* failed for some reason */ NM_DHCP_STATE_TERMINATED, /* client is no longer running */ NM_DHCP_STATE_NOOP, /* state is a non operation for NetworkManager */ - __NM_DHCP_STATE_MAX, - NM_DHCP_STATE_MAX = __NM_DHCP_STATE_MAX - 1, } NMDhcpState; +typedef enum _nm_packed { + NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED, + NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED, +} NMDhcpClientNotifyType; + +typedef struct { + NMDhcpClientNotifyType notify_type; + union { + struct { + NMIPConfig *ip_config; + GHashTable *options; + NMDhcpState dhcp_state; + } state_changed; + struct { + const NMPlatformIP6Address *prefix; + } prefix_delegated; + }; +} NMDhcpClientNotifyData; + const char *nm_dhcp_state_to_string(NMDhcpState state); struct _NMDhcpClientPrivate; @@ -68,7 +84,6 @@ struct _NMDhcpClientPrivate; typedef struct { GObject parent; struct _NMDhcpClientPrivate *_priv; - CList dhcp_client_lst; } NMDhcpClient; typedef enum _nm_packed { @@ -173,6 +188,7 @@ gboolean nm_dhcp_client_start_ip6(NMDhcpClient * self, GError ** error); gboolean nm_dhcp_client_accept(NMDhcpClient *self, GError **error); +gboolean nm_dhcp_client_can_accept(NMDhcpClient *self); gboolean nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error); @@ -217,11 +233,13 @@ gboolean nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer *****************************************************************************/ typedef struct { - GType (*get_type)(void); - GType (*get_type_per_addr_family)(int addr_family); + GType (*get_type_4)(void); + GType (*get_type_6)(void); const char *name; const char *(*get_path)(void); - bool experimental : 1; + + /* whether this plugin is an undocumented, internal plugin. */ + bool undocumented : 1; } NMDhcpClientFactory; GType nm_dhcp_nettools_get_type(void); diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c index 4284a852..341ac7b2 100644 --- a/src/core/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c @@ -59,7 +59,7 @@ grab_request_options(GPtrArray *store, const char *line) gsize i; /* Grab each 'request' or 'also request' option and save for later */ - line_v = nm_utils_strsplit_set(line, "\t ,"); + line_v = nm_strsplit_set(line, "\t ,"); for (i = 0; line_v && line_v[i]; i++) { const char *ss = nm_str_skip_leading_spaces(line_v[i]); gsize l; @@ -282,7 +282,7 @@ read_interface(const char *line, char *interface, guint size) if (ptr[0] == '\0' || strlen(ptr) + 1 > size) return FALSE; - snprintf(interface, size, "%s", ptr); + g_snprintf(interface, size, "%s", ptr); return TRUE; } @@ -330,7 +330,7 @@ nm_dhcp_dhclient_create_config(const char * interface, g_string_append_printf(new_contents, _("# Merged from %s\n\n"), orig_path); intf[0] = '\0'; - lines = nm_utils_strsplit_set(orig_contents, "\n\r"); + lines = nm_strsplit_set(orig_contents, "\n\r"); for (line_i = 0; lines && lines[line_i]; line_i++) { const char *line = nm_str_skip_leading_spaces(lines[line_i]); const char *p; @@ -620,7 +620,7 @@ nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error) if (!g_file_get_contents(leasefile, &contents, NULL, error)) return NULL; - contents_v = nm_utils_strsplit_set(contents, "\n\r"); + contents_v = nm_strsplit_set(contents, "\n\r"); for (i = 0; contents_v && contents_v[i]; i++) { const char *p = nm_str_skip_leading_spaces(contents_v[i]); GBytes * duid; @@ -671,7 +671,7 @@ nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error) return FALSE; } - lines = nm_utils_strsplit_set_with_empty(contents, "\n\r"); + lines = nm_strsplit_set_with_empty(contents, "\n\r"); } s = g_string_sized_new(len + 50); diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c index 4a11250f..970a51f5 100644 --- a/src/core/dhcp/nm-dhcp-dhclient.c +++ b/src/core/dhcp/nm-dhcp-dhclient.c @@ -14,21 +14,21 @@ #if WITH_DHCLIENT - #include - #include - #include - #include - #include - #include - - #include "libnm-glib-aux/nm-dedup-multi.h" - - #include "nm-utils.h" - #include "nm-dhcp-dhclient-utils.h" - #include "nm-dhcp-manager.h" - #include "NetworkManagerUtils.h" - #include "nm-dhcp-listener.h" - #include "nm-dhcp-client-logging.h" +#include +#include +#include +#include +#include +#include + +#include "libnm-glib-aux/nm-dedup-multi.h" + +#include "nm-utils.h" +#include "nm-dhcp-dhclient-utils.h" +#include "nm-dhcp-manager.h" +#include "NetworkManagerUtils.h" +#include "nm-dhcp-listener.h" +#include "nm-dhcp-client-logging.h" /*****************************************************************************/ @@ -41,16 +41,15 @@ _addr_family_to_path_part(int addr_family) /*****************************************************************************/ - #define NM_TYPE_DHCP_DHCLIENT (nm_dhcp_dhclient_get_type()) - #define NM_DHCP_DHCLIENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclient)) - #define NM_DHCP_DHCLIENT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) - #define NM_IS_DHCP_DHCLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCLIENT)) - #define NM_IS_DHCP_DHCLIENT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCLIENT)) - #define NM_DHCP_DHCLIENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) +#define NM_TYPE_DHCP_DHCLIENT (nm_dhcp_dhclient_get_type()) +#define NM_DHCP_DHCLIENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclient)) +#define NM_DHCP_DHCLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) +#define NM_IS_DHCP_DHCLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCLIENT)) +#define NM_IS_DHCP_DHCLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCLIENT)) +#define NM_DHCP_DHCLIENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) typedef struct _NMDhcpDhclient NMDhcpDhclient; typedef struct _NMDhcpDhclientClass NMDhcpDhclientClass; @@ -78,8 +77,8 @@ struct _NMDhcpDhclientClass { G_DEFINE_TYPE(NMDhcpDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) - #define NM_DHCP_DHCLIENT_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMDhcpDhclient, NM_IS_DHCP_DHCLIENT) +#define NM_DHCP_DHCLIENT_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDhcpDhclient, NM_IS_DHCP_DHCLIENT) /*****************************************************************************/ @@ -731,9 +730,10 @@ nm_dhcp_dhclient_class_init(NMDhcpDhclientClass *dhclient_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient = { - .name = "dhclient", - .get_type = nm_dhcp_dhclient_get_type, - .get_path = nm_dhcp_dhclient_get_path, + .name = "dhclient", + .get_type_4 = nm_dhcp_dhclient_get_type, + .get_type_6 = nm_dhcp_dhclient_get_type, + .get_path = nm_dhcp_dhclient_get_path, }; #endif /* WITH_DHCLIENT */ diff --git a/src/core/dhcp/nm-dhcp-dhcpcanon.c b/src/core/dhcp/nm-dhcp-dhcpcanon.c index f3a52ea9..f993ffb9 100644 --- a/src/core/dhcp/nm-dhcp-dhcpcanon.c +++ b/src/core/dhcp/nm-dhcp-dhcpcanon.c @@ -7,25 +7,24 @@ #if WITH_DHCPCANON - #include - #include - - #include "nm-utils.h" - #include "nm-dhcp-manager.h" - #include "NetworkManagerUtils.h" - #include "nm-dhcp-listener.h" - #include "nm-dhcp-client-logging.h" - - #define NM_TYPE_DHCP_DHCPCANON (nm_dhcp_dhcpcanon_get_type()) - #define NM_DHCP_DHCPCANON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanon)) - #define NM_DHCP_DHCPCANON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) - #define NM_IS_DHCP_DHCPCANON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCPCANON)) - #define NM_IS_DHCP_DHCPCANON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCPCANON)) - #define NM_DHCP_DHCPCANON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) +#include +#include + +#include "nm-utils.h" +#include "nm-dhcp-manager.h" +#include "NetworkManagerUtils.h" +#include "nm-dhcp-listener.h" +#include "nm-dhcp-client-logging.h" + +#define NM_TYPE_DHCP_DHCPCANON (nm_dhcp_dhcpcanon_get_type()) +#define NM_DHCP_DHCPCANON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanon)) +#define NM_DHCP_DHCPCANON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) +#define NM_IS_DHCP_DHCPCANON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCPCANON)) +#define NM_IS_DHCP_DHCPCANON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCPCANON)) +#define NM_DHCP_DHCPCANON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) typedef struct _NMDhcpDhcpcanon NMDhcpDhcpcanon; typedef struct _NMDhcpDhcpcanonClass NMDhcpDhcpcanonClass; @@ -53,8 +52,8 @@ struct _NMDhcpDhcpcanonClass { G_DEFINE_TYPE(NMDhcpDhcpcanon, nm_dhcp_dhcpcanon, NM_TYPE_DHCP_CLIENT) - #define NM_DHCP_DHCPCANON_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMDhcpDhcpcanon, NM_IS_DHCP_DHCPCANON) +#define NM_DHCP_DHCPCANON_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDhcpDhcpcanon, NM_IS_DHCP_DHCPCANON) /*****************************************************************************/ @@ -232,9 +231,9 @@ nm_dhcp_dhcpcanon_class_init(NMDhcpDhcpcanonClass *dhcpcanon_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon = { - .name = "dhcpcanon", - .get_type = nm_dhcp_dhcpcanon_get_type, - .get_path = nm_dhcp_dhcpcanon_get_path, + .name = "dhcpcanon", + .get_type_4 = nm_dhcp_dhcpcanon_get_type, + .get_path = nm_dhcp_dhcpcanon_get_path, }; #endif /* WITH_DHCPCANON */ diff --git a/src/core/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c index 605fb84d..7522156b 100644 --- a/src/core/dhcp/nm-dhcp-dhcpcd.c +++ b/src/core/dhcp/nm-dhcp-dhcpcd.c @@ -8,29 +8,28 @@ #if WITH_DHCPCD - #include - #include - #include - #include - #include - - #include "nm-dhcp-manager.h" - #include "nm-utils.h" - #include "NetworkManagerUtils.h" - #include "nm-dhcp-listener.h" - #include "nm-dhcp-client-logging.h" +#include +#include +#include +#include +#include + +#include "nm-dhcp-manager.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-dhcp-listener.h" +#include "nm-dhcp-client-logging.h" /*****************************************************************************/ - #define NM_TYPE_DHCP_DHCPCD (nm_dhcp_dhcpcd_get_type()) - #define NM_DHCP_DHCPCD(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcd)) - #define NM_DHCP_DHCPCD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) - #define NM_IS_DHCP_DHCPCD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCPCD)) - #define NM_IS_DHCP_DHCPCD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCPCD)) - #define NM_DHCP_DHCPCD_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) +#define NM_TYPE_DHCP_DHCPCD (nm_dhcp_dhcpcd_get_type()) +#define NM_DHCP_DHCPCD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcd)) +#define NM_DHCP_DHCPCD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) +#define NM_IS_DHCP_DHCPCD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCPCD)) +#define NM_IS_DHCP_DHCPCD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCPCD)) +#define NM_DHCP_DHCPCD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) typedef struct _NMDhcpDhcpcd NMDhcpDhcpcd; typedef struct _NMDhcpDhcpcdClass NMDhcpDhcpcdClass; @@ -54,7 +53,7 @@ struct _NMDhcpDhcpcdClass { G_DEFINE_TYPE(NMDhcpDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) - #define NM_DHCP_DHCPCD_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpDhcpcd, NM_IS_DHCP_DHCPCD) +#define NM_DHCP_DHCPCD_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpDhcpcd, NM_IS_DHCP_DHCPCD) /*****************************************************************************/ @@ -233,9 +232,9 @@ nm_dhcp_dhcpcd_class_init(NMDhcpDhcpcdClass *dhcpcd_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd = { - .name = "dhcpcd", - .get_type = nm_dhcp_dhcpcd_get_type, - .get_path = nm_dhcp_dhcpcd_get_path, + .name = "dhcpcd", + .get_type_4 = nm_dhcp_dhcpcd_get_type, + .get_path = nm_dhcp_dhcpcd_get_path, }; #endif /* WITH_DHCPCD */ diff --git a/src/core/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c index 56d20101..fd666676 100644 --- a/src/core/dhcp/nm-dhcp-helper.c +++ b/src/core/dhcp/nm-dhcp-helper.c @@ -16,9 +16,9 @@ /*****************************************************************************/ #if NM_MORE_LOGGING - #define _NMLOG_ENABLED(level) TRUE +#define _NMLOG_ENABLED(level) TRUE #else - #define _NMLOG_ENABLED(level) ((level) <= LOG_ERR) +#define _NMLOG_ENABLED(level) ((level) <= LOG_ERR) #endif #define _NMLOG(always_enabled, level, ...) \ diff --git a/src/core/dhcp/nm-dhcp-listener.c b/src/core/dhcp/nm-dhcp-listener.c index b8bb3c33..ae2c40f1 100644 --- a/src/core/dhcp/nm-dhcp-listener.c +++ b/src/core/dhcp/nm-dhcp-listener.c @@ -26,8 +26,9 @@ /*****************************************************************************/ const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = { + /* the order here matters, as we will try the plugins in this order to find - * the first available plugin. */ + * the first available plugin. */ #if WITH_DHCPCANON &_nm_dhcp_client_factory_dhcpcanon, diff --git a/src/core/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c index 44b8ede2..3cb89393 100644 --- a/src/core/dhcp/nm-dhcp-manager.c +++ b/src/core/dhcp/nm-dhcp-manager.c @@ -27,7 +27,6 @@ typedef struct { const NMDhcpClientFactory *client_factory; char * default_hostname; - CList dhcp_client_lst_head; } NMDhcpManagerPrivate; struct _NMDhcpManager { @@ -45,14 +44,6 @@ G_DEFINE_TYPE(NMDhcpManager, nm_dhcp_manager, G_TYPE_OBJECT) /*****************************************************************************/ -static void client_state_changed(NMDhcpClient * client, - NMDhcpState state, - GObject * ip_config, - GVariant * options, - NMDhcpManager *self); - -/*****************************************************************************/ - /* default to installed helper, but can be modified for testing */ const char *nm_dhcp_helper_path = LIBEXECDIR "/nm-dhcp-helper"; @@ -63,9 +54,9 @@ _client_factory_find_by_name(const char *name) { int i; - g_return_val_if_fail(name, NULL); + nm_assert(name); - for (i = 0; i < G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { + for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { const NMDhcpClientFactory *f = _nm_dhcp_manager_factories[i]; if (f && nm_streq(f->name, name)) @@ -85,11 +76,10 @@ _client_factory_available(const NMDhcpClientFactory *client_factory) static GType _client_factory_get_gtype(const NMDhcpClientFactory *client_factory, int addr_family) { - GType gtype; - nm_auto_unref_gtypeclass NMDhcpClientClass *klass = NULL; + GType gtype; + GType (*get_type_fcn)(void); nm_assert(client_factory); - nm_assert_addr_family(addr_family); /* currently, the chosen DHCP plugin for IPv4 and IPv6 is configured in NetworkManager.conf * and cannot be reloaded. It would be nice to configure the plugin per address family @@ -111,29 +101,22 @@ _client_factory_get_gtype(const NMDhcpClientFactory *client_factory, int addr_fa * to those plugins. But we don't intend to do so. The internal plugin is the way forward and * not extending other plugins. */ - if (client_factory->get_type_per_addr_family) - gtype = client_factory->get_type_per_addr_family(addr_family); + if (NM_IS_IPv4(addr_family)) + get_type_fcn = client_factory->get_type_4; else - gtype = client_factory->get_type(); - - if (client_factory == &_nm_dhcp_client_factory_internal) { - /* we are already using the internal plugin. Nothing to do. */ - goto out; + get_type_fcn = client_factory->get_type_6; + + if (!get_type_fcn) { + /* If the factory does not support the address family, we always + * fallback to the internal. */ + if (NM_IS_IPv4(addr_family)) + get_type_fcn = _nm_dhcp_client_factory_internal.get_type_4; + else + get_type_fcn = _nm_dhcp_client_factory_internal.get_type_6; } - klass = g_type_class_ref(gtype); - - nm_assert(NM_IS_DHCP_CLIENT_CLASS(klass)); + gtype = get_type_fcn(); - if (addr_family == AF_INET6) { - if (!klass->ip6_start) - gtype = _client_factory_get_gtype(&_nm_dhcp_client_factory_internal, addr_family); - } else { - if (!klass->ip4_start) - gtype = _client_factory_get_gtype(&_nm_dhcp_client_factory_internal, addr_family); - } - -out: nm_assert(g_type_is_a(gtype, NM_TYPE_DHCP_CLIENT)); nm_assert(({ nm_auto_unref_gtypeclass NMDhcpClientClass *k = g_type_class_ref(gtype); @@ -146,56 +129,6 @@ out: /*****************************************************************************/ -static NMDhcpClient * -get_client_for_ifindex(NMDhcpManager *manager, int addr_family, int ifindex) -{ - NMDhcpManagerPrivate *priv; - NMDhcpClient * client; - - g_return_val_if_fail(NM_IS_DHCP_MANAGER(manager), NULL); - g_return_val_if_fail(ifindex > 0, NULL); - - priv = NM_DHCP_MANAGER_GET_PRIVATE(manager); - - c_list_for_each_entry (client, &priv->dhcp_client_lst_head, dhcp_client_lst) { - if (nm_dhcp_client_get_ifindex(client) == ifindex - && nm_dhcp_client_get_addr_family(client) == addr_family) - return client; - } - - return NULL; -} - -static void -remove_client(NMDhcpManager *self, NMDhcpClient *client) -{ - g_signal_handlers_disconnect_by_func(client, client_state_changed, self); - c_list_unlink(&client->dhcp_client_lst); - - /* Stopping the client is left up to the controlling device - * explicitly since we may want to quit NetworkManager but not terminate - * the DHCP client. - */ -} - -static void -remove_client_unref(NMDhcpManager *self, NMDhcpClient *client) -{ - remove_client(self, client); - g_object_unref(client); -} - -static void -client_state_changed(NMDhcpClient * client, - NMDhcpState state, - GObject * ip_config, - GVariant * options, - NMDhcpManager *self) -{ - if (state >= NM_DHCP_STATE_TIMEOUT) - remove_client_unref(self, client); -} - static NMDhcpClient * client_start(NMDhcpManager * self, int addr_family, @@ -226,10 +159,10 @@ client_start(NMDhcpManager * self, GError ** error) { NMDhcpManagerPrivate *priv; - NMDhcpClient * client; - gboolean success = FALSE; - gsize hwaddr_len; - GType gtype; + gs_unref_object NMDhcpClient *client = NULL; + gboolean success = FALSE; + gsize hwaddr_len; + GType gtype; g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL); g_return_val_if_fail(iface, NULL); @@ -278,20 +211,6 @@ client_start(NMDhcpManager * self, priv = NM_DHCP_MANAGER_GET_PRIVATE(self); - /* Kill any old client instance */ - client = get_client_for_ifindex(self, addr_family, ifindex); - if (client) { - /* FIXME: we cannot just call synchronously "stop()" and forget about the client. - * We need to wait for the client to be fully stopped because most/all clients - * cannot quit right away. - * - * FIXME(shutdown): also fix this during shutdown, to wait for all DHCP clients - * to be fully stopped. */ - remove_client(self, client); - nm_dhcp_client_stop(client, FALSE); - g_object_unref(client); - } - gtype = _client_factory_get_gtype(priv->client_factory, addr_family); nm_log_trace(LOGD_DHCP, @@ -340,12 +259,6 @@ client_start(NMDhcpManager * self, NM_DHCP_CLIENT_ANYCAST_ADDRESS, anycast_address, NULL); - nm_assert(client && c_list_is_empty(&client->dhcp_client_lst)); - c_list_link_tail(&priv->dhcp_client_lst_head, &client->dhcp_client_lst); - g_signal_connect(client, - NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_CALLBACK(client_state_changed), - self); /* unfortunately, our implementations work differently per address-family regarding client-id/DUID. * @@ -385,12 +298,10 @@ client_start(NMDhcpManager * self, error); } - if (!success) { - remove_client_unref(self, client); + if (!success) return NULL; - } - return g_object_ref(client); + return g_steal_pointer(&client); } /* Caller owns a reference to the NMDhcpClient on return */ @@ -596,9 +507,7 @@ nm_dhcp_manager_init(NMDhcpManager *self) int i; const NMDhcpClientFactory *client_factory = NULL; - c_list_init(&priv->dhcp_client_lst_head); - - for (i = 0; i < G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { + for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { const NMDhcpClientFactory *f = _nm_dhcp_manager_factories[i]; if (!f) @@ -608,7 +517,7 @@ nm_dhcp_manager_init(NMDhcpManager *self) "dhcp-init: enabled DHCP client '%s'%s%s", f->name, _client_factory_available(f) ? "" : " (not available)", - f->experimental ? " (undocumented internal plugin)" : ""); + f->undocumented ? " (undocumented internal plugin)" : ""); } /* Client-specific setup */ @@ -644,7 +553,7 @@ nm_dhcp_manager_init(NMDhcpManager *self) } } if (!client_factory) { - for (i = 0; i < G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { + for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { client_factory = _client_factory_available(_nm_dhcp_manager_factories[i]); if (client_factory) break; @@ -668,10 +577,6 @@ dispose(GObject *object) { NMDhcpManager * self = NM_DHCP_MANAGER(object); NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(self); - NMDhcpClient * client, *client_safe; - - c_list_for_each_entry_safe (client, client_safe, &priv->dhcp_client_lst_head, dhcp_client_lst) - remove_client_unref(self, client); G_OBJECT_CLASS(nm_dhcp_manager_parent_class)->dispose(object); diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index 4bb6c833..56b485dd 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -601,7 +601,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_str_buf_append_len0(&sbuf, (const char *) l_data, l_data_len); /* Multiple domains sometimes stuffed into option 15 "Domain Name". */ - domains = nm_utils_strsplit_set(nm_str_buf_get_str(&sbuf), " "); + domains = nm_strsplit_set(nm_str_buf_get_str(&sbuf), " "); nm_str_buf_reset(&sbuf); if (domains) { @@ -997,9 +997,7 @@ nettools_create(NMDhcpNettools *self, GError **error) n_dhcp4_client_get_fd(priv->client, &fd); - priv->event_source = - nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, dhcp4_event_cb, self, NULL); - g_source_attach(priv->event_source, NULL); + priv->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, dhcp4_event_cb, self); return TRUE; } @@ -1221,7 +1219,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) return FALSE; } - _LOGT("dhcp-client4: start %p", (gpointer) priv->client); + _LOGT("dhcp-client4: start " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(priv->client)); nm_dhcp_client_start_timeout(client); return TRUE; @@ -1235,7 +1233,7 @@ stop(NMDhcpClient *client, gboolean release) NM_DHCP_CLIENT_CLASS(nm_dhcp_nettools_parent_class)->stop(client, release); - _LOGT("dhcp-client4: stop %p", (gpointer) priv->client); + _LOGT("dhcp-client4: stop " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(priv->client)); priv->probe = n_dhcp4_client_probe_free(priv->probe); } @@ -1276,6 +1274,6 @@ nm_dhcp_nettools_class_init(NMDhcpNettoolsClass *class) const NMDhcpClientFactory _nm_dhcp_client_factory_nettools = { .name = "nettools", - .get_type = nm_dhcp_nettools_get_type, - .experimental = TRUE, + .get_type_4 = nm_dhcp_nettools_get_type, + .undocumented = TRUE, }; diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index c789aaee..af1d2238 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -592,7 +592,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) return FALSE; } - _LOGT("dhcp-client4: set %p", sd_client); + _LOGT("dhcp-client4: set " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(sd_client)); r = sd_dhcp_client_attach_event(sd_client, NULL, 0); if (r < 0) { @@ -1124,23 +1124,15 @@ nm_dhcp_systemd_class_init(NMDhcpSystemdClass *sdhcp_class) const NMDhcpClientFactory _nm_dhcp_client_factory_systemd = { .name = "systemd", - .get_type = nm_dhcp_systemd_get_type, - .experimental = TRUE, + .get_type_4 = nm_dhcp_systemd_get_type, + .get_type_6 = nm_dhcp_systemd_get_type, + .undocumented = TRUE, }; /*****************************************************************************/ -static GType -_get_type_per_addr_family(int addr_family) -{ - nm_assert_addr_family(addr_family); - - if (addr_family == AF_INET) - return nm_dhcp_nettools_get_type(); - return nm_dhcp_systemd_get_type(); -} - const NMDhcpClientFactory _nm_dhcp_client_factory_internal = { - .name = "internal", - .get_type_per_addr_family = _get_type_per_addr_family, + .name = "internal", + .get_type_4 = nm_dhcp_nettools_get_type, + .get_type_6 = nm_dhcp_systemd_get_type, }; diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 7fd18b0a..3cc6987a 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -35,7 +35,7 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface, const char ** r; gboolean have_routes = FALSE; - routes = nm_utils_strsplit_set(str, " "); + routes = nm_strsplit_set(str, " "); if (!routes) return FALSE; @@ -164,7 +164,7 @@ ip4_process_dhclient_rfc3442_routes(const char * iface, const char *const * o; gboolean have_routes = FALSE; - octets = nm_utils_strsplit_set_with_empty(str, " ."); + octets = nm_strsplit_set_with_empty(str, " ."); if (NM_PTRARRAY_LEN(octets) < 5) { _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); return FALSE; @@ -296,7 +296,7 @@ process_classful_routes(const char * iface, if (!str) return; - searches = nm_utils_strsplit_set(str, " "); + searches = nm_strsplit_set(str, " "); if (!searches) return; @@ -376,7 +376,7 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint return; } - searches = nm_utils_strsplit_set(unescaped, " "); + searches = nm_strsplit_set(unescaped, " "); for (s = searches; searches && *s; s++) { _LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s); add_func((gpointer) *s, user_data); @@ -450,7 +450,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, */ str = g_hash_table_lookup(options, "routers"); if (str) { - gs_free const char **routers = nm_utils_strsplit_set(str, " "); + gs_free const char **routers = nm_strsplit_set(str, " "); const char ** s; for (s = routers; routers && *s; s++) { @@ -491,7 +491,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, str = g_hash_table_lookup(options, "domain_name_servers"); if (str) { - gs_free const char **dns = nm_utils_strsplit_set(str, " "); + gs_free const char **dns = nm_strsplit_set(str, " "); const char ** s; for (s = dns; dns && *s; s++) { @@ -507,7 +507,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, str = g_hash_table_lookup(options, "domain_name"); if (str) { - gs_free const char **domains = nm_utils_strsplit_set(str, " "); + gs_free const char **domains = nm_strsplit_set(str, " "); const char ** s; for (s = domains; domains && *s; s++) { @@ -522,7 +522,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, str = g_hash_table_lookup(options, "netbios_name_servers"); if (str) { - gs_free const char **nbns = nm_utils_strsplit_set(str, " "); + gs_free const char **nbns = nm_strsplit_set(str, " "); const char ** s; for (s = nbns; nbns && *s; s++) { @@ -557,7 +557,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, str = g_hash_table_lookup(options, "nis_servers"); if (str) { - gs_free const char **nis = nm_utils_strsplit_set(str, " "); + gs_free const char **nis = nm_strsplit_set(str, " "); const char ** s; for (s = nis; nis && *s; s++) { @@ -689,7 +689,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx, str = g_hash_table_lookup(options, "dhcp6_name_servers"); if (str) { - gs_free const char **dns = nm_utils_strsplit_set(str, " "); + gs_free const char **dns = nm_strsplit_set(str, " "); const char ** s; for (s = dns; dns && *s; s++) { diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c index e9a62096..9c6865cc 100644 --- a/src/core/dhcp/tests/test-dhcp-dhclient.c +++ b/src/core/dhcp/tests/test-dhcp-dhclient.c @@ -830,7 +830,7 @@ test_one_duid(const char *escaped, const guint8 *unescaped, guint len) t1 = nm_dhcp_dhclient_unescape_duid(escaped); g_assert(t1); - g_assert(nm_utils_gbytes_equal_mem(t1, unescaped, len)); + g_assert(nm_g_bytes_equal_mem(t1, unescaped, len)); t2 = g_bytes_new(unescaped, len); w = nm_dhcp_dhclient_escape_duid(t2); @@ -879,7 +879,7 @@ test_read_duid_from_leasefile(void) duid = nm_dhcp_dhclient_read_duid(TEST_DIR "/test-dhclient-duid.leases", &error); nmtst_assert_success(duid, error); - g_assert(nm_utils_gbytes_equal_mem(duid, expected, G_N_ELEMENTS(expected))); + g_assert(nm_g_bytes_equal_mem(duid, expected, G_N_ELEMENTS(expected))); } static void diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 4c498c82..f0ec0c89 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -19,7 +19,7 @@ #include #if WITH_LIBPSL - #include +#include #endif #include "libnm-glib-aux/nm-str-buf.h" @@ -42,17 +42,17 @@ #define HASH_LEN NM_UTILS_CHECKSUM_LENGTH_SHA1 #ifndef RESOLVCONF_PATH - #define RESOLVCONF_PATH "/sbin/resolvconf" - #define HAS_RESOLVCONF 0 +#define RESOLVCONF_PATH "/sbin/resolvconf" +#define HAS_RESOLVCONF 0 #else - #define HAS_RESOLVCONF 1 +#define HAS_RESOLVCONF 1 #endif #ifndef NETCONFIG_PATH - #define NETCONFIG_PATH "/sbin/netconfig" - #define HAS_NETCONFIG 0 +#define NETCONFIG_PATH "/sbin/netconfig" +#define HAS_NETCONFIG 0 #else - #define HAS_NETCONFIG 1 +#define HAS_NETCONFIG 1 #endif /*****************************************************************************/ @@ -272,7 +272,7 @@ _dns_config_ip_data_new(NMDnsConfigData * data, g_signal_connect(ip_config, NM_IS_IP4_CONFIG(ip_config) ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY : "notify::" NM_IP6_CONFIG_DNS_PRIORITY, - (GCallback) _ip_config_dns_priority_changed, + G_CALLBACK(_ip_config_dns_priority_changed), ip_data); _ASSERT_dns_config_ip_data(ip_data); @@ -1327,7 +1327,7 @@ get_ip_rdns_domains(NMIPConfig *ip_config) /* Free the array and return NULL if the only element was the ending NULL */ strv = (char **) g_ptr_array_free(domains, (domains->len == 1)); - return _nm_utils_strv_cleanup(strv, FALSE, FALSE, TRUE); + return nm_strv_cleanup(strv, FALSE, FALSE, TRUE); } static gboolean @@ -1744,8 +1744,8 @@ plugin_skip:; nameservers = g_new0(char *, 2); nameservers[0] = g_strdup(lladdr); - need_edns0 = nm_utils_strv_find_first(options, -1, NM_SETTING_DNS_OPTION_EDNS0) < 0; - need_trust = nm_utils_strv_find_first(options, -1, NM_SETTING_DNS_OPTION_TRUST_AD) < 0; + need_edns0 = nm_strv_find_first(options, -1, NM_SETTING_DNS_OPTION_EDNS0) < 0; + need_trust = nm_strv_find_first(options, -1, NM_SETTING_DNS_OPTION_TRUST_AD) < 0; if (need_edns0 || need_trust) { gsize len; @@ -2128,10 +2128,7 @@ _resolvconf_resolved_managed(void) * We want to handle that, because systemd-resolved might not * have started yet. */ full_path = g_file_read_link(_PATH_RESCONF, NULL); - if (nm_utils_strv_find_first((char **) RESOLVED_PATHS, - G_N_ELEMENTS(RESOLVED_PATHS), - full_path) - >= 0) + if (nm_strv_find_first(RESOLVED_PATHS, G_N_ELEMENTS(RESOLVED_PATHS), full_path) >= 0) return TRUE; /* see if resolv.conf is a symlink that resolves exactly one @@ -2143,10 +2140,7 @@ _resolvconf_resolved_managed(void) * We want to handle that, because systemd-resolved might not * have started yet. */ real_path = realpath(_PATH_RESCONF, NULL); - if (nm_utils_strv_find_first((char **) RESOLVED_PATHS, - G_N_ELEMENTS(RESOLVED_PATHS), - real_path) - >= 0) + if (nm_strv_find_first(RESOLVED_PATHS, G_N_ELEMENTS(RESOLVED_PATHS), real_path) >= 0) return TRUE; /* fall-through and resolve the symlink, to check the file diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h index 501085f7..1972a5dd 100644 --- a/src/core/dns/nm-dns-manager.h +++ b/src/core/dns/nm-dns-manager.h @@ -21,11 +21,6 @@ typedef enum { NM_DNS_IP_CONFIG_TYPE_VPN, } NMDnsIPConfigType; -enum { - NM_DNS_PRIORITY_DEFAULT_NORMAL = 100, - NM_DNS_PRIORITY_DEFAULT_VPN = 50, -}; - /*****************************************************************************/ struct _NMDnsConfigData; diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index 4b8c4f94..445f8498 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -36,6 +36,7 @@ /* define a variable, so that we can compare the operation with pointer equality. */ static const char *const DBUS_OP_SET_LINK_DEFAULT_ROUTE = "SetLinkDefaultRoute"; +static const char *const DBUS_OP_SET_LINK_DNS_OVER_TLS = "SetLinkDNSOverTLS"; /*****************************************************************************/ @@ -86,7 +87,12 @@ typedef struct { bool try_start_blocked : 1; bool dbus_initied : 1; bool send_updates_waiting : 1; - NMTernary has_link_default_route : 3; + /* These two variables ensure that the log is not spammed with + * API (not) supported messages. + * They can be removed when no distro uses systemd-resolved < v240 anymore + */ + NMTernary has_link_default_route : 3; + NMTernary has_link_dns_over_tls : 3; } NMDnsSystemdResolvedPrivate; struct _NMDnsSystemdResolved { @@ -201,16 +207,26 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) priv->has_link_default_route = NM_TERNARY_TRUE; _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API supported"); } + if (request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS + && priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT) { + priv->has_link_dns_over_tls = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API supported"); + } priv->send_updates_warn_ratelimited = FALSE; return; } - if (request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE - && nm_g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) { - if (priv->has_link_default_route == NM_TERNARY_DEFAULT) { + if (nm_g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) { + if (priv->has_link_default_route == NM_TERNARY_DEFAULT + && request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) { priv->has_link_default_route = NM_TERNARY_FALSE; _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported"); } + if (priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT + && request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) { + priv->has_link_dns_over_tls = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API not supported"); + } return; } @@ -286,14 +302,15 @@ free_pending_updates(NMDnsSystemdResolved *self) static gboolean prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) { - GVariantBuilder dns; - GVariantBuilder domains; - NMCListElem * elem; - NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; - const char * mdns_arg = NULL, *llmnr_arg = NULL; - gboolean has_config = FALSE; - gboolean has_default_route = FALSE; + GVariantBuilder dns; + GVariantBuilder domains; + NMCListElem * elem; + NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + const char * mdns_arg = NULL, *llmnr_arg = NULL, *dns_over_tls_arg = NULL; + gboolean has_config = FALSE; + gboolean has_default_route = FALSE; g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))")); g_variant_builder_add(&dns, "i", ic->ifindex); @@ -315,6 +332,8 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) if (NM_IS_IP4_CONFIG(ip_config)) { mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_IP4_CONFIG(ip_config))); llmnr = NM_MAX(llmnr, nm_ip4_config_llmnr_get(NM_IP4_CONFIG(ip_config))); + dns_over_tls = + NM_MAX(dns_over_tls, nm_ip4_config_dns_over_tls_get(NM_IP4_CONFIG(ip_config))); } } @@ -353,7 +372,24 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) } nm_assert(llmnr_arg); - if (!nm_str_is_empty(mdns_arg) || !nm_str_is_empty(llmnr_arg)) + switch (dns_over_tls) { + case NM_SETTING_CONNECTION_DNS_OVER_TLS_NO: + dns_over_tls_arg = "no"; + break; + case NM_SETTING_CONNECTION_DNS_OVER_TLS_OPPORTUNISTIC: + dns_over_tls_arg = "opportunistic"; + break; + case NM_SETTING_CONNECTION_DNS_OVER_TLS_YES: + dns_over_tls_arg = "yes"; + break; + case NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT: + dns_over_tls_arg = ""; + break; + } + nm_assert(dns_over_tls_arg); + + if (!nm_str_is_empty(mdns_arg) || !nm_str_is_empty(llmnr_arg) + || !nm_str_is_empty(dns_over_tls_arg)) has_config = TRUE; _request_item_append(self, "SetLinkDomains", ic->ifindex, g_variant_builder_end(&domains)); @@ -370,6 +406,10 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) ic->ifindex, g_variant_new("(is)", ic->ifindex, llmnr_arg ?: "")); _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); + _request_item_append(self, + DBUS_OP_SET_LINK_DNS_OVER_TLS, + ic->ifindex, + g_variant_new("(is)", ic->ifindex, dns_over_tls_arg ?: "")); return has_config; } @@ -422,12 +462,7 @@ ensure_resolved_running(NMDnsSystemdResolved *self) priv->try_start_blocked = TRUE; priv->try_start_timeout_source = - nm_g_source_attach(nm_g_timeout_source_new(4000, - G_PRIORITY_DEFAULT, - _ensure_resolved_running_timeout, - self, - NULL), - NULL); + nm_g_timeout_add_source(4000, _ensure_resolved_running_timeout, self); nm_dbus_connection_call_start_service_by_name(priv->dbus_connection, SYSTEMD_RESOLVED_DBUS_SERVICE, @@ -468,15 +503,18 @@ send_updates(NMDnsSystemdResolved *self) priv->send_updates_waiting = FALSE; - _LOGT("send-updates: start %lu requests", c_list_length(&priv->request_queue_lst_head)); + _LOGT("send-updates: start %zu requests", c_list_length(&priv->request_queue_lst_head)); c_list_for_each_entry (request_item, &priv->request_queue_lst_head, request_queue_lst) { gs_free char *ss = NULL; - if (request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE - && priv->has_link_default_route == NM_TERNARY_FALSE) { + if ((request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE + && priv->has_link_default_route == NM_TERNARY_FALSE) + || (request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS + && priv->has_link_dns_over_tls == NM_TERNARY_FALSE)) { /* The "SetLinkDefaultRoute" API is only supported since v240. - * We detected that it is not supported, and skip the call. There + * The "SetLinkDNSOverTLS" API is only supported since v239. + * We detected whether they are supported, and skip the calls. There * is no special workaround, because in this case we rely on systemd-resolved * to do the right thing automatically. */ continue; @@ -601,13 +639,15 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner) nm_clear_g_source_inst(&priv->try_start_timeout_source); - nm_utils_strdup_reset(&priv->dbus_owner, owner); + nm_strdup_reset(&priv->dbus_owner, owner); if (owner) { priv->try_start_blocked = FALSE; priv->send_updates_waiting = TRUE; - } else + } else { priv->has_link_default_route = NM_TERNARY_DEFAULT; + priv->has_link_dns_over_tls = NM_TERNARY_DEFAULT; + } send_updates(self); } @@ -821,19 +861,13 @@ _resolve_start(NMDnsSystemdResolved *self, NMDnsSystemdResolvedResolveHandle *ha _LOG2T(handle, "systemd-resolved not running. Failing on idle..."); nm_assert(!handle->timeout_source); handle->is_failing_on_idle = TRUE; - handle->timeout_source = nm_g_source_attach( - nm_g_idle_source_new(G_PRIORITY_DEFAULT, _resolve_failing_on_idle, handle, NULL), - NULL); + handle->timeout_source = nm_g_idle_add_source(_resolve_failing_on_idle, handle); return; } if (!handle->timeout_source) { - handle->timeout_source = nm_g_source_attach(nm_g_timeout_source_new(handle->timeout_msec, - G_PRIORITY_DEFAULT, - _resolve_handle_timeout, - handle, - NULL), - NULL); + handle->timeout_source = + nm_g_timeout_add_source(handle->timeout_msec, _resolve_handle_timeout, handle); } if (is_running == NM_TERNARY_DEFAULT) { @@ -929,6 +963,7 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); priv->has_link_default_route = NM_TERNARY_DEFAULT; + priv->has_link_dns_over_tls = NM_TERNARY_DEFAULT; c_list_init(&priv->request_queue_lst_head); c_list_init(&priv->handle_lst_head); diff --git a/src/core/main-utils.c b/src/core/main-utils.c index 9bc497ca..48f143c3 100644 --- a/src/core/main-utils.c +++ b/src/core/main-utils.c @@ -14,7 +14,6 @@ #include #include -#include #include "main-utils.h" #include "NetworkManagerUtils.h" diff --git a/src/core/main.c b/src/core/main.c index 3cb5c07f..7d448a59 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -38,7 +38,7 @@ #include "nm-netns.h" #if !defined(NM_DIST_VERSION) - #define NM_DIST_VERSION VERSION +#define NM_DIST_VERSION VERSION #endif #define NM_DEFAULT_PID_FILE NMRUNDIR "/NetworkManager.pid" @@ -326,6 +326,7 @@ main(int argc, char *argv[]) if (global_opt.show_version) { fprintf(stdout, NM_DIST_VERSION "\n"); + nm_config_cmd_line_options_free(config_cli); exit(0); } @@ -374,6 +375,7 @@ main(int argc, char *argv[]) fprintf(stderr, _("%s. Please use --help to see a list of valid options.\n"), error->message); + nm_config_cmd_line_options_free(config_cli); exit(1); } diff --git a/src/core/meson.build b/src/core/meson.build index f4d7af64..6e00928e 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -51,6 +51,7 @@ libNetworkManagerBase = static_library( 'nm-netns.c', 'nm-l3-config-data.c', 'nm-l3-ipv4ll.c', + 'nm-l3-ipv6ll.c', 'nm-l3cfg.c', 'nm-ip-config.c', 'nm-ip4-config.c', @@ -172,6 +173,7 @@ libNetworkManager = static_library( 'nm-rfkill-manager.c', 'nm-session-monitor.c', 'nm-sleep-monitor.c', + 'nm-priv-helper-call.c', ), dependencies: nm_deps, link_with: [ diff --git a/src/core/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c index f11178f8..552b0e4b 100644 --- a/src/core/ndisc/nm-lndp-ndisc.c +++ b/src/core/ndisc/nm-lndp-ndisc.c @@ -85,14 +85,14 @@ send_rs(NMNDisc *ndisc, GError **error) static NMIcmpv6RouterPref _route_preference_coerce(enum ndp_route_preference pref) { -#define _ASSERT_ENUM(v1, v2) \ - G_STMT_START \ - { \ - G_STATIC_ASSERT((NMIcmpv6RouterPref) (v1) == (v2)); \ - G_STATIC_ASSERT((enum ndp_route_preference) (v2) == (v1)); \ - G_STATIC_ASSERT((gint64) (v1) == (v2)); \ - G_STATIC_ASSERT((gint64) (v2) == (v1)); \ - } \ +#define _ASSERT_ENUM(v1, v2) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT((NMIcmpv6RouterPref) (v1) == (v2)); \ + G_STATIC_ASSERT((enum ndp_route_preference)(v2) == (v1)); \ + G_STATIC_ASSERT((gint64) (v1) == (v2)); \ + G_STATIC_ASSERT((gint64) (v2) == (v1)); \ + } \ G_STMT_END switch (pref) { @@ -599,9 +599,7 @@ start(NMNDisc *ndisc) fd = ndp_get_eventfd(priv->ndp); - priv->event_source = - nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, event_ready, ndisc, NULL); - g_source_attach(priv->event_source, NULL); + priv->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, event_ready, ndisc); /* Flush any pending messages to avoid using obsolete information */ event_ready(fd, 0, ndisc); @@ -666,69 +664,6 @@ stop(NMNDisc *ndisc) /*****************************************************************************/ -static int -ipv6_sysctl_get(NMPlatform *platform, - const char *ifname, - const char *property, - int min, - int max, - int defval) -{ - return nm_platform_sysctl_ip_conf_get_int_checked(platform, - AF_INET6, - ifname, - property, - 10, - min, - max, - defval); -} - -void -nm_lndp_ndisc_get_sysctl(NMPlatform *platform, - const char *ifname, - int * out_max_addresses, - int * out_router_solicitations, - int * out_router_solicitation_interval, - guint32 * out_default_ra_timeout) -{ - int router_solicitation_interval = 0; - int router_solicitations = 0; - - if (out_max_addresses) { - *out_max_addresses = ipv6_sysctl_get(platform, - ifname, - "max_addresses", - 0, - G_MAXINT32, - NM_NDISC_MAX_ADDRESSES_DEFAULT); - } - if (out_router_solicitations || out_default_ra_timeout) { - router_solicitations = ipv6_sysctl_get(platform, - ifname, - "router_solicitations", - 1, - G_MAXINT32, - NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT); - NM_SET_OUT(out_router_solicitations, router_solicitations); - } - if (out_router_solicitation_interval || out_default_ra_timeout) { - router_solicitation_interval = ipv6_sysctl_get(platform, - ifname, - "router_solicitation_interval", - 1, - G_MAXINT32, - NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL); - NM_SET_OUT(out_router_solicitation_interval, router_solicitation_interval); - } - if (out_default_ra_timeout) { - *out_default_ra_timeout = - NM_MAX((((gint64) router_solicitations) * router_solicitation_interval) + 1, 30); - } -} - -/*****************************************************************************/ - static void nm_lndp_ndisc_init(NMLndpNDisc *lndp_ndisc) {} diff --git a/src/core/ndisc/nm-lndp-ndisc.h b/src/core/ndisc/nm-lndp-ndisc.h index 96fc9737..151f4bf7 100644 --- a/src/core/ndisc/nm-lndp-ndisc.h +++ b/src/core/ndisc/nm-lndp-ndisc.h @@ -36,11 +36,4 @@ NMNDisc *nm_lndp_ndisc_new(NMPlatform * platform, guint32 ra_timeout, GError ** error); -void nm_lndp_ndisc_get_sysctl(NMPlatform *platform, - const char *ifname, - int * out_max_addresses, - int * out_router_solicitations, - int * out_router_solicitation_interval, - guint32 * out_default_ra_timeout); - #endif /* __NETWORKMANAGER_LNDP_NDISC_H__ */ diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index cf1b58ec..d7b1a2e1 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -23,6 +23,9 @@ #define RFC7559_IRT ((gint32) 4) /* RFC7559, Initial Retransmission Time, in seconds */ #define RFC7559_MRT ((gint32) 3600) /* RFC7559, Maximum Retransmission Time, in seconds */ +#define NM_NDISC_PRE_EXPIRY_TIME_MSEC 60000 +#define NM_NDISC_PRE_EXPIRY_MIN_LIFETIME_MSEC 120000 + #define _SIZE_MAX_GATEWAYS 100u #define _SIZE_MAX_ADDRESSES 100u #define _SIZE_MAX_ROUTES 1000u @@ -44,6 +47,7 @@ struct _NMNDiscPrivate { gint32 last_ra; gint32 solicit_retransmit_time_msec; + gint64 last_rs_msec; GSource *solicit_timer_source; @@ -96,6 +100,16 @@ static gboolean timeout_expire_cb(gpointer user_data); /*****************************************************************************/ +NM_UTILS_LOOKUP_STR_DEFINE(nm_ndisc_dhcp_level_to_string, + NMNDiscDHCPLevel, + NM_UTILS_LOOKUP_DEFAULT("INVALID"), + NM_UTILS_LOOKUP_STR_ITEM(NM_NDISC_DHCP_LEVEL_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_NDISC_DHCP_LEVEL_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM(NM_NDISC_DHCP_LEVEL_OTHERCONF, "otherconf"), + NM_UTILS_LOOKUP_STR_ITEM(NM_NDISC_DHCP_LEVEL_MANAGED, "managed"), ); + +/*****************************************************************************/ + NML3ConfigData * nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, int ifindex, @@ -112,9 +126,7 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, guint i; const gint32 now_sec = nm_utils_get_monotonic_timestamp_sec(); - l3cd = nm_l3_config_data_new(multi_idx, ifindex); - - nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_NDISC); + l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_NDISC); nm_l3_config_data_set_ip6_privacy(l3cd, ip6_privacy); @@ -468,12 +480,12 @@ complete_address(NMNDisc *ndisc, NMNDiscAddress *addr) priv = NM_NDISC_GET_PRIVATE(ndisc); if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { - if (!nm_utils_ipv6_addr_set_stable_privacy(priv->stable_type, - &addr->address, - priv->ifname, - priv->network_id, - addr->dad_counter++, - &error)) { + if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(priv->stable_type, + &addr->address, + priv->ifname, + priv->network_id, + addr->dad_counter++, + &error)) { _LOGW("complete-address: failed to generate an stable-privacy address: %s", error->message); g_clear_error(&error); @@ -490,7 +502,7 @@ complete_address(NMNDisc *ndisc, NMNDiscAddress *addr) if (addr->address.s6_addr32[2] == 0x0 && addr->address.s6_addr32[3] == 0x0) { _LOGD("complete-address: adding an EUI-64 address"); - nm_utils_ipv6_addr_set_interface_identifier(&addr->address, priv->iid); + nm_utils_ipv6_addr_set_interface_identifier(&addr->address, &priv->iid); return TRUE; } @@ -832,6 +844,8 @@ solicit_timer_cb(gpointer user_data) else { _LOGT("solicit: router solicitation sent"); nm_clear_g_free(&priv->last_error); + + priv->last_rs_msec = nm_utils_get_monotonic_timestamp_msec(); } /* https://tools.ietf.org/html/rfc4861#section-6.3.7 describes how to send solicitations: @@ -1213,21 +1227,6 @@ config_map_to_string(NMNDiscConfigMap map, char *p) *p = '\0'; } -static const char * -dhcp_level_to_string(NMNDiscDHCPLevel dhcp_level) -{ - switch (dhcp_level) { - case NM_NDISC_DHCP_LEVEL_NONE: - return "none"; - case NM_NDISC_DHCP_LEVEL_OTHERCONF: - return "otherconf"; - case NM_NDISC_DHCP_LEVEL_MANAGED: - return "managed"; - default: - return "INVALID"; - } -} - static void _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed) { @@ -1250,7 +1249,7 @@ _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed) config_map_to_string(changed, changedstr); _LOGD("neighbor discovery configuration changed [%s]:", changedstr); - _LOGD(" dhcp-level %s", dhcp_level_to_string(priv->rdata.public.dhcp_level)); + _LOGD(" dhcp-level %s", nm_ndisc_dhcp_level_to_string(priv->rdata.public.dhcp_level)); if (rdata->public.hop_limit) _LOGD(" hop limit : %d", rdata->public.hop_limit); @@ -1508,33 +1507,6 @@ check_timestamps(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed) ndisc); } - /* When we receive an RA, we don't disable solicitations entirely. Instead, - * we set the interval the maximum (RFC7559_MRT). - * - * This contradicts https://tools.ietf.org/html/rfc7559#section-2.1, which says - * that we SHOULD stop sending RS if we receive an RA -- but only on a multicast - * capable link and if the RA has a valid router lifetime. - * - * But we really want to recover from a dead router on the network, so we - * don't want to cease sending RS entirely. - * - * But we only re-schedule the timer if the current interval is not already - * "RFC7559_MRT * 1000". Otherwise, we already have a slow interval counter - * pending. */ - if (priv->solicit_retransmit_time_msec != RFC7559_MRT * 1000) { - gint32 timeout_msec; - - priv->solicit_retransmit_time_msec = RFC7559_MRT * 1000; - timeout_msec = solicit_retransmit_time_jitter(priv->solicit_retransmit_time_msec); - - _LOGD("solicit: schedule sending next (slow) solicitation in about %.3f seconds", - ((double) timeout_msec) / 1000); - - nm_clear_g_source_inst(&priv->solicit_timer_source); - priv->solicit_timer_source = - nm_g_timeout_add_source_approx(timeout_msec, 0, solicit_timer_cb, ndisc); - } - if (changed != NM_NDISC_CONFIG_NONE) nm_ndisc_emit_config_change(ndisc, changed); } @@ -1546,14 +1518,111 @@ timeout_expire_cb(gpointer user_data) return G_SOURCE_CONTINUE; } +/* Calculate the earliest time where some part of the advertised data is about + * to expire. + * + * Entities are considered about to expire NM_NDISC_PRE_EXPIRY_TIME_MSEC before + * their expiration time. + * + * However, data which has a lifetime (as calculated from the time the last + * RS has been sent) shorter than NM_NDISC_PRE_EXPIRY_MIN_LIFETIME_MSEC, is + * ignored. This is because when we send out RSs because some data is about + * to expire, and the received RAs neither extend the lifetime nor remove + * the offending data, the data would be considered about to expire again, + * triggering more RS in an endless loop until it expired for good. + */ + +static void +_calc_pre_expiry_rs_msec_worker(gint64 *earliest_expiry_msec, + gint64 last_rs_msec, + gint64 expiry_msec) +{ + if (expiry_msec == NM_NDISC_EXPIRY_INFINITY) + return; + + if (expiry_msec < last_rs_msec + NM_NDISC_PRE_EXPIRY_MIN_LIFETIME_MSEC) + return; + + *earliest_expiry_msec = NM_MIN(*earliest_expiry_msec, expiry_msec); +} + +static gint64 +calc_pre_expiry_rs_msec(NMNDisc *ndisc) +{ + NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + NMNDiscDataInternal *rdata = &priv->rdata; + gint64 expiry_msec = NM_NDISC_EXPIRY_INFINITY; + guint i; + + for (i = 0; i < rdata->gateways->len; i++) { + _calc_pre_expiry_rs_msec_worker( + &expiry_msec, + priv->last_rs_msec, + g_array_index(rdata->gateways, NMNDiscGateway, i).expiry_msec); + } + + for (i = 0; i < rdata->addresses->len; i++) { + _calc_pre_expiry_rs_msec_worker( + &expiry_msec, + priv->last_rs_msec, + g_array_index(rdata->addresses, NMNDiscAddress, 0).expiry_msec); + } + + for (i = 0; i < rdata->routes->len; i++) { + _calc_pre_expiry_rs_msec_worker(&expiry_msec, + priv->last_rs_msec, + g_array_index(rdata->routes, NMNDiscRoute, 0).expiry_msec); + } + + for (i = 0; i < rdata->dns_servers->len; i++) { + _calc_pre_expiry_rs_msec_worker( + &expiry_msec, + priv->last_rs_msec, + g_array_index(rdata->dns_servers, NMNDiscDNSServer, 0).expiry_msec); + } + + for (i = 0; i < rdata->dns_domains->len; i++) { + _calc_pre_expiry_rs_msec_worker( + &expiry_msec, + priv->last_rs_msec, + g_array_index(rdata->dns_domains, NMNDiscDNSDomain, 0).expiry_msec); + } + + return expiry_msec - solicit_retransmit_time_jitter(NM_NDISC_PRE_EXPIRY_TIME_MSEC); +} + void nm_ndisc_ra_received(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed) { NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); + gint64 pre_expiry_msec; + gint32 timeout_msec; nm_clear_g_source_inst(&priv->ra_timeout_source); nm_clear_g_free(&priv->last_error); check_timestamps(ndisc, now_msec, changed); + + /* When we receive an RA, we don't disable solicitations. + * + * This contradicts https://tools.ietf.org/html/rfc7559#section-2.1, which + * says that we SHOULD stop sending RS if we receive an RA -- but only on + * a multicast capable link and if the RA has a valid router lifetime. + * + * But there are routers out in the wild that won't send unsolicited RAs. + * So we begin sending out RS again when entities are about to expire. + */ + pre_expiry_msec = NM_CLAMP(calc_pre_expiry_rs_msec(ndisc), + priv->last_rs_msec + RFC7559_IRT * 1000, + priv->last_rs_msec + RFC7559_MRT * 1000); + timeout_msec = NM_CLAMP(pre_expiry_msec - now_msec, (gint64) 0, (gint64) G_MAXINT32); + + _LOGD("solicit: schedule sending next (slow) solicitation in about %.3f seconds", + ((double) timeout_msec) / 1000); + + priv->solicit_retransmit_time_msec = 0; + nm_clear_g_source_inst(&priv->solicit_timer_source); + priv->solicit_timer_source = + nm_g_timeout_add_source_approx(timeout_msec, 0, solicit_timer_cb, ndisc); } void @@ -1567,6 +1636,69 @@ nm_ndisc_rs_received(NMNDisc *ndisc) /*****************************************************************************/ +static int +ipv6_sysctl_get(NMPlatform *platform, + const char *ifname, + const char *property, + int min, + int max, + int defval) +{ + return nm_platform_sysctl_ip_conf_get_int_checked(platform, + AF_INET6, + ifname, + property, + 10, + min, + max, + defval); +} + +void +nm_ndisc_get_sysctl(NMPlatform *platform, + const char *ifname, + int * out_max_addresses, + int * out_router_solicitations, + int * out_router_solicitation_interval, + guint32 * out_default_ra_timeout) +{ + int router_solicitation_interval = 0; + int router_solicitations = 0; + + if (out_max_addresses) { + *out_max_addresses = ipv6_sysctl_get(platform, + ifname, + "max_addresses", + 0, + G_MAXINT32, + NM_NDISC_MAX_ADDRESSES_DEFAULT); + } + if (out_router_solicitations || out_default_ra_timeout) { + router_solicitations = ipv6_sysctl_get(platform, + ifname, + "router_solicitations", + 1, + G_MAXINT32, + NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT); + NM_SET_OUT(out_router_solicitations, router_solicitations); + } + if (out_router_solicitation_interval || out_default_ra_timeout) { + router_solicitation_interval = ipv6_sysctl_get(platform, + ifname, + "router_solicitation_interval", + 1, + G_MAXINT32, + NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL); + NM_SET_OUT(out_router_solicitation_interval, router_solicitation_interval); + } + if (out_default_ra_timeout) { + *out_default_ra_timeout = + NM_MAX((((gint64) router_solicitations) * router_solicitation_interval) + 1, 30); + } +} + +/*****************************************************************************/ + static void dns_domain_free(gpointer data) { diff --git a/src/core/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h index 15f95d20..5b827528 100644 --- a/src/core/ndisc/nm-ndisc.h +++ b/src/core/ndisc/nm-ndisc.h @@ -48,6 +48,8 @@ typedef enum { NM_NDISC_DHCP_LEVEL_MANAGED } NMNDiscDHCPLevel; +const char *nm_ndisc_dhcp_level_to_string(NMNDiscDHCPLevel level); + #define NM_NDISC_INFINITY_U32 ((uint32_t) -1) /* It's important that this is G_MAXINT64, so that we can meaningfully do @@ -239,7 +241,7 @@ static inline gboolean nm_ndisc_dad_addr_is_fail_candidate_event(NMPlatformSignalChangeType change_type, const NMPlatformIP6Address *addr) { - return !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TEMPORARY) + return !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_SECONDARY) && ((change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED) || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE)); @@ -253,7 +255,7 @@ nm_ndisc_dad_addr_is_fail_candidate(NMPlatform *platform, const NMPObject *obj) addr = NMP_OBJECT_CAST_IP6_ADDRESS( nm_platform_lookup_obj(platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)); if (addr - && (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TEMPORARY) + && (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_SECONDARY) || !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_DADFAILED))) { /* the address still/again exists and is not in DADFAILED state. Skip it. */ return FALSE; @@ -264,6 +266,15 @@ nm_ndisc_dad_addr_is_fail_candidate(NMPlatform *platform, const NMPObject *obj) /*****************************************************************************/ +void nm_ndisc_get_sysctl(NMPlatform *platform, + const char *ifname, + int * out_max_addresses, + int * out_router_solicitations, + int * out_router_solicitation_interval, + guint32 * out_default_ra_timeout); + +/*****************************************************************************/ + struct _NML3ConfigData; struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, diff --git a/src/core/ndisc/tests/test-ndisc-linux.c b/src/core/ndisc/tests/test-ndisc-linux.c index c84ee142..57021606 100644 --- a/src/core/ndisc/tests/test-ndisc-linux.c +++ b/src/core/ndisc/tests/test-ndisc-linux.c @@ -49,12 +49,12 @@ main(int argc, char **argv) return EXIT_FAILURE; } - nm_lndp_ndisc_get_sysctl(NM_PLATFORM_GET, - ifname, - &max_addresses, - &router_solicitations, - &router_solicitation_interval, - &ra_timeout); + nm_ndisc_get_sysctl(NM_PLATFORM_GET, + ifname, + &max_addresses, + &router_solicitations, + &router_solicitation_interval, + &ra_timeout); ndisc = nm_lndp_ndisc_new(NM_PLATFORM_GET, ifindex, diff --git a/src/core/nm-active-connection.c b/src/core/nm-active-connection.c index 40fe3c96..4cd6d488 100644 --- a/src/core/nm-active-connection.c +++ b/src/core/nm-active-connection.c @@ -208,12 +208,12 @@ _set_settings_connection(NMActiveConnection *self, NMSettingsConnection *sett_co if (sett_conn) { g_signal_connect(sett_conn, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, - (GCallback) _settings_connection_updated, + G_CALLBACK(_settings_connection_updated), self); if (nm_active_connection_get_activation_type(self) == NM_ACTIVATION_TYPE_EXTERNAL) g_signal_connect(sett_conn, NM_SETTINGS_CONNECTION_FLAGS_CHANGED, - (GCallback) _settings_connection_flags_changed, + G_CALLBACK(_settings_connection_flags_changed), self); } @@ -858,7 +858,7 @@ nm_active_connection_set_master(NMActiveConnection *self, NMActiveConnection *ma priv->master = g_object_ref(master); g_signal_connect(priv->master, "notify::" NM_ACTIVE_CONNECTION_STATE, - (GCallback) master_state_cb, + G_CALLBACK(master_state_cb), self); check_master_ready(self); @@ -890,7 +890,7 @@ _set_activation_type(NMActiveConnection *self, NMActivationType activation_type) if (activation_type == NM_ACTIVATION_TYPE_EXTERNAL) g_signal_connect(priv->settings_connection.obj, NM_SETTINGS_CONNECTION_FLAGS_CHANGED, - (GCallback) _settings_connection_flags_changed, + G_CALLBACK(_settings_connection_flags_changed), self); else g_signal_handlers_disconnect_by_func(priv->settings_connection.obj, @@ -1025,7 +1025,7 @@ unwatch_parent(NMActiveConnection *self, gboolean unref) { NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - g_signal_handlers_disconnect_by_func(priv->parent, (GCallback) parent_state_cb, self); + g_signal_handlers_disconnect_by_func(priv->parent, G_CALLBACK(parent_state_cb), self); if (unref) g_object_weak_unref((GObject *) priv->parent, parent_destroyed, self); priv->parent = NULL; @@ -1049,7 +1049,7 @@ nm_active_connection_set_parent(NMActiveConnection *self, NMActiveConnection *pa priv->parent = parent; g_signal_connect(priv->parent, "notify::" NM_ACTIVE_CONNECTION_STATE, - (GCallback) parent_state_cb, + G_CALLBACK(parent_state_cb), self); g_object_weak_ref((GObject *) priv->parent, parent_destroyed, self); } @@ -1529,7 +1529,7 @@ dispose(GObject *object) _device_cleanup(self); if (priv->master) { - g_signal_handlers_disconnect_by_func(priv->master, (GCallback) master_state_cb, self); + g_signal_handlers_disconnect_by_func(priv->master, G_CALLBACK(master_state_cb), self); } g_clear_object(&priv->master); diff --git a/src/core/nm-audit-manager.c b/src/core/nm-audit-manager.c index 2ef5d860..477e1798 100644 --- a/src/core/nm-audit-manager.c +++ b/src/core/nm-audit-manager.c @@ -8,7 +8,7 @@ #include "nm-audit-manager.h" #if HAVE_LIBAUDIT - #include +#include #endif #define NM_VALUE_TYPE_DEFINE_FUNCTIONS diff --git a/src/core/nm-auth-utils.c b/src/core/nm-auth-utils.c index 006264dd..da17b1a4 100644 --- a/src/core/nm-auth-utils.c +++ b/src/core/nm-auth-utils.c @@ -124,12 +124,8 @@ _cancellable_idle_cb(gpointer user_data) static void _cancellable_on_idle(NMAuthChain *self) { - if (self->cancellable_idle_source) - return; - - self->cancellable_idle_source = - nm_g_idle_source_new(G_PRIORITY_DEFAULT, _cancellable_idle_cb, self, NULL); - g_source_attach(self->cancellable_idle_source, NULL); + if (!self->cancellable_idle_source) + self->cancellable_idle_source = nm_g_idle_add_source(_cancellable_idle_cb, self); } GCancellable * diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index 0cbff027..1cb8a43c 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -271,7 +271,7 @@ nm_config_data_get_plugins(const NMConfigData *self, gboolean allow_default) NM_CONFIG_DEFAULT_MAIN_PLUGINS); list = g_key_file_get_string_list(kf, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", NULL, NULL); } - return _nm_utils_strv_cleanup(list, TRUE, TRUE, TRUE); + return nm_strv_cleanup(list, TRUE, TRUE, TRUE); } gboolean @@ -1026,7 +1026,7 @@ global_dns_config_seal_domains(NMGlobalDnsConfig *dns_config) if (g_hash_table_size(dns_config->domains) == 0) nm_clear_pointer(&dns_config->domains, g_hash_table_unref); else - dns_config->domain_list = nm_utils_strdict_get_keys(dns_config->domains, TRUE, NULL); + dns_config->domain_list = nm_strdict_get_keys(dns_config->domains, TRUE, NULL); } static NMGlobalDnsConfig * @@ -1060,7 +1060,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) NULL, NULL); if (strv) { - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + nm_strv_cleanup(strv, TRUE, TRUE, TRUE); if (!strv[0]) g_free(strv); else @@ -1073,7 +1073,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) NULL, NULL); if (strv) { - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + nm_strv_cleanup(strv, TRUE, TRUE, TRUE); for (i = 0, j = 0; strv[i]; i++) { if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, TRUE, NULL)) strv[j++] = strv[i]; @@ -1103,7 +1103,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) NULL, NULL); if (strv) { - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + nm_strv_cleanup(strv, TRUE, TRUE, TRUE); for (i = 0, j = 0; strv[i]; i++) { if (nm_utils_ipaddr_is_valid(AF_INET, strv[i]) || nm_utils_ipaddr_is_valid(AF_INET6, strv[i])) @@ -1128,7 +1128,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) NULL, NULL); if (strv) { - options = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + options = nm_strv_cleanup(strv, TRUE, TRUE, TRUE); if (!options[0]) nm_clear_g_free(&options); } @@ -1240,7 +1240,7 @@ global_dns_domain_from_dbus(char *name, GVariant *variant) while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) { if (nm_streq0(key, "servers") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + nm_strv_cleanup(strv, TRUE, TRUE, TRUE); for (i = 0, j = 0; strv && strv[i]; i++) { if (nm_utils_ipaddr_is_valid(AF_INET, strv[i]) || nm_utils_ipaddr_is_valid(AF_INET6, strv[i])) @@ -1258,7 +1258,7 @@ global_dns_domain_from_dbus(char *name, GVariant *variant) } else if (nm_streq0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); g_strfreev(domain->options); - domain->options = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + domain->options = nm_strv_cleanup(strv, TRUE, TRUE, TRUE); if (!domain->options[0]) nm_clear_g_free(&domain->options); } @@ -1305,10 +1305,10 @@ nm_global_dns_config_from_dbus(const GValue *value, GError **error) while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) { if (nm_streq0(key, "searches") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); - dns_config->searches = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + dns_config->searches = nm_strv_cleanup(strv, TRUE, TRUE, TRUE); } else if (nm_streq0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { strv = g_variant_dup_strv(val, NULL); - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); + nm_strv_cleanup(strv, TRUE, TRUE, TRUE); for (i = 0, j = 0; strv && strv[i]; i++) { if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, TRUE, NULL)) @@ -1370,8 +1370,7 @@ global_dns_equal(NMGlobalDnsConfig *old, NMGlobalDnsConfig *new) if (!old || !new) return FALSE; - if (!nm_utils_strv_equal(old->options, new->options) - || !nm_utils_strv_equal(old->searches, new->searches)) + if (!nm_strv_equal(old->options, new->options) || !nm_strv_equal(old->searches, new->searches)) return FALSE; if ((!old->domains || !new->domains) && old->domains != new->domains) @@ -1389,8 +1388,8 @@ global_dns_equal(NMGlobalDnsConfig *old, NMGlobalDnsConfig *new) domain_old = value_old; domain_new = value_new; - if (!nm_utils_strv_equal(domain_old->options, domain_new->options) - || !nm_utils_strv_equal(domain_old->servers, domain_new->servers)) + if (!nm_strv_equal(domain_old->options, domain_new->options) + || !nm_strv_equal(domain_old->servers, domain_new->servers)) return FALSE; } @@ -1681,7 +1680,7 @@ _match_section_info_init(MatchSectionInfo *connection_info, } keys = g_key_file_get_keys(keyfile, group, &n_keys, NULL); - nm_utils_strv_sort(keys, n_keys); + nm_strv_sort(keys, n_keys); vals = g_new(NMUtilsNamedValue, n_keys); @@ -1963,8 +1962,8 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps /* sort entries, remove duplicates and empty words. */ value_arr = len == 0 ? NULL : nm_memdup(value_arr_orig, sizeof(const char *) * (len + 1)); - nm_utils_strv_sort(value_arr, len); - _nm_utils_strv_cleanup((char **) value_arr, FALSE, TRUE, TRUE); + nm_strv_sort(value_arr, len); + nm_strv_cleanup((char **) value_arr, FALSE, TRUE, TRUE); len = NM_PTRARRAY_LEN(value_arr); j = 0; @@ -1988,7 +1987,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps specs = g_slist_prepend(specs, spec); } - priv->no_auto_default.arr = nm_utils_strv_dup(value_arr, j, TRUE); + priv->no_auto_default.arr = nm_strv_dup(value_arr, j, TRUE); priv->no_auto_default.specs = g_slist_reverse(specs); } break; diff --git a/src/core/nm-config-data.h b/src/core/nm-config-data.h index fa58d869..92a7cb5c 100644 --- a/src/core/nm-config-data.h +++ b/src/core/nm-config-data.h @@ -195,16 +195,16 @@ const char *nm_config_data_get_iwd_config_path(const NMConfigData *self); extern const char *__start_connection_defaults[]; extern const char *__stop_connection_defaults[]; -#define NM_CON_DEFAULT_NOP(name) \ - static const char *NM_UNIQ_T(connection_default, NM_UNIQ) \ - _nm_used _nm_section("connection_defaults") = "" name - -#define NM_CON_DEFAULT(name) \ - ({ \ - static const char *__con_default_prop _nm_used _nm_section("connection_defaults") = \ - "" name; \ - \ - name; \ +#define NM_CON_DEFAULT_NOP(name) \ + static const char * NM_UNIQ_T(connection_default, NM_UNIQ) \ + _nm_used _nm_retain _nm_section("connection_defaults") = "" name + +#define NM_CON_DEFAULT(name) \ + ({ \ + static const char *__con_default_prop _nm_used _nm_retain _nm_section( \ + "connection_defaults") = "" name; \ + \ + name; \ }) const char *nm_config_data_get_connection_default(const NMConfigData *self, diff --git a/src/core/nm-config.c b/src/core/nm-config.c index 817368d1..c41f5823 100644 --- a/src/core/nm-config.c +++ b/src/core/nm-config.c @@ -336,7 +336,7 @@ no_auto_default_from_file(const char *no_auto_default_file) gsize i; if (no_auto_default_file && g_file_get_contents(no_auto_default_file, &data, NULL, NULL)) - list = nm_utils_strsplit_set(data, "\n"); + list = nm_strsplit_set(data, "\n"); if (list) { for (i = 0; list[i]; i++) @@ -433,7 +433,7 @@ nm_config_set_no_auto_default_for_device(NMConfig *self, NMDevice *device) len = NM_PTRARRAY_LEN(no_auto_default_current); - idx = nm_utils_strv_find_binary_search(no_auto_default_current, len, spec); + idx = nm_strv_find_binary_search(no_auto_default_current, len, spec); if (idx >= 0) { /* @spec is already blocked. We don't have to update our in-memory representation. * Maybe we should write to no_auto_default_file anew, but let's save that too. */ @@ -1122,14 +1122,12 @@ read_config(GKeyFile * keyfile, /* merge the string lists, by omitting duplicates. */ for (iter_val = old_val; iter_val && *iter_val; iter_val++) { - if (last_char != '-' - || nm_utils_strv_find_first(new_val, -1, *iter_val) < 0) + if (last_char != '-' || nm_strv_find_first(new_val, -1, *iter_val) < 0) g_ptr_array_add(new, g_strdup(*iter_val)); } for (iter_val = new_val; iter_val && *iter_val; iter_val++) { /* don't add duplicates. That means an "option=a,b"; "option+=a,c" results in "option=a,b,c" */ - if (last_char == '+' - && nm_utils_strv_find_first(old_val, -1, *iter_val) < 0) + if (last_char == '+' && nm_strv_find_first(old_val, -1, *iter_val) < 0) g_ptr_array_add(new, *iter_val); else g_free(*iter_val); @@ -1147,7 +1145,7 @@ read_config(GKeyFile * keyfile, gs_free char * specs_joined = NULL; g_ptr_array_add(new, NULL); - specs = _nm_utils_strv_to_slist((char **) new->pdata, FALSE); + specs = nm_strv_to_gslist((char **) new->pdata, FALSE); specs_joined = nm_match_spec_join(specs); @@ -1333,9 +1331,8 @@ read_entire_config(const NMConfigCmdLineOptions *cli, const char *filename = system_confs->pdata[i]; /* if a same named file exists in config_dir or run_config_dir, skip it. */ - if (nm_utils_strv_find_first((char **) confs->pdata, confs->len, filename) >= 0 - || nm_utils_strv_find_first((char **) run_confs->pdata, run_confs->len, filename) - >= 0) { + if (nm_strv_ptrarray_find_first(confs, filename) >= 0 + || nm_strv_ptrarray_find_first(run_confs, filename) >= 0) { g_ptr_array_remove_index(system_confs, i); continue; } @@ -1349,7 +1346,7 @@ read_entire_config(const NMConfigCmdLineOptions *cli, const char *filename = run_confs->pdata[i]; /* if a same named file exists in config_dir, skip it. */ - if (nm_utils_strv_find_first((char **) confs->pdata, confs->len, filename) >= 0) { + if (nm_strv_ptrarray_find_first(confs, filename) >= 0) { g_ptr_array_remove_index(run_confs, i); continue; } diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c index 85d41b49..13fb0265 100644 --- a/src/core/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -10,10 +10,9 @@ #include "nm-connectivity.h" #if WITH_CONCHECK - #include +#include #endif #include -#include #include "c-list/src/c-list.h" #include "libnm-core-intern/nm-core-internal.h" @@ -509,15 +508,8 @@ multi_socket_cb(CURL *e_handle, curl_socket_t fd, int what, void *userdata, void else condition = 0; - if (condition) { - fdp->source = nm_g_unix_fd_source_new(fd, - condition, - G_PRIORITY_DEFAULT, - _con_curl_socketevent_cb, - fdp, - NULL); - g_source_attach(fdp->source, NULL); - } + if (condition) + fdp->source = nm_g_unix_fd_add_source(fd, condition, _con_curl_socketevent_cb, fdp); } return CURLM_OK; diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 8fdc7379..747e1c09 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -39,8 +39,8 @@ #include "nm-setting-wireless-security.h" #ifdef __NM_SD_UTILS_H__ - #error \ - "nm-core-utils.c should stay independent of systemd utils. Are you looking for NetworkMangerUtils.c? " +#error \ + "nm-core-utils.c should stay independent of systemd utils. Are you looking for NetworkMangerUtils.c? " #endif G_STATIC_ASSERT(sizeof(NMUtilsTestFlags) <= sizeof(int)); @@ -458,7 +458,7 @@ _kc_invoke_callback(pid_t pid, data->sync.success = success; data->sync.child_status = child_status; - g_idle_add(_kc_invoke_callback_idle, data); + nm_g_idle_add(_kc_invoke_callback_idle, data); } /* nm_utils_kill_child_async: @@ -2484,8 +2484,6 @@ out: typedef struct { NMUuid bin; - char - _nul_sentinel; /* just for safety, if somebody accidentally uses the binary in a string context. */ /* depending on whether the string is packed or not (with/without hyphens), * it's 32 or 36 characters long (plus the trailing NUL). @@ -2503,9 +2501,8 @@ _uuid_data_init(UuidData *uuid_data, gboolean packed, gboolean is_fake, const NM nm_assert(uuid_data); nm_assert(uuid); - uuid_data->bin = *uuid; - uuid_data->_nul_sentinel = '\0'; - uuid_data->is_fake = is_fake; + uuid_data->bin = *uuid; + uuid_data->is_fake = is_fake; if (packed) { G_STATIC_ASSERT_EXPR(sizeof(uuid_data->str) >= (sizeof(*uuid) * 2 + 1)); nm_utils_bin2hexstr_full(uuid, sizeof(*uuid), '\0', FALSE, uuid_data->str); @@ -2573,7 +2570,7 @@ again: if (is_fake) { const guint8 *seed_bin; - const char * hash_seed; + const NMUuid *hash_seed; gsize seed_len; if (!allow_fake) { @@ -2583,6 +2580,9 @@ again: } if (nm_utils_host_id_get(&seed_bin, &seed_len)) { + static const NMUuid u = + NM_UUID_INIT(ab, 08, 5f, 06, b6, 29, 46, d1, a5, 53, 84, ee, ba, 56, 83, b6); + /* We have no valid machine-id but we have a valid secrey_key. * Generate a fake machine ID by hashing the secret-key. The secret_key * is commonly persisted, so it should be stable across reboots (despite @@ -2595,8 +2595,11 @@ again: * will call _machine_id_get(FALSE), so it won't allow accessing a fake * machine-id, thus avoiding the problem. */ fake_type = "secret-key"; - hash_seed = "ab085f06-b629-46d1-a553-84eeba5683b6"; + hash_seed = &u; } else { + static const NMUuid u = + NM_UUID_INIT(7f, f0, c8, f5, 53, 99, 49, 01, ab, 63, 61, bf, 59, 4a, be, 8b); + /* the secret-key is not valid/persistent either. That happens when we fail * to read/write the secret-key to disk. Fallback to boot-id. The boot-id * itself may be fake and randomly generated ad-hoc, but that is as best @@ -2604,7 +2607,7 @@ again: seed_bin = (const guint8 *) nm_utils_boot_id_bin(); seed_len = sizeof(NMUuid); fake_type = "boot-id"; - hash_seed = "7ff0c8f5-5399-4901-ab63-61bf594abe8b"; + hash_seed = &u; } /* the fake machine-id is based on secret-key/boot-id, but we hash it @@ -2613,7 +2616,7 @@ again: (const char *) seed_bin, seed_len, NM_UUID_TYPE_VERSION5, - (gpointer) hash_seed); + hash_seed); } if (!g_once_init_enter(&lock)) @@ -2874,10 +2877,11 @@ typedef struct { bool timestamp_is_good : 1; } HostIdData; +static const HostIdData *volatile host_id_static; + static const HostIdData * _host_id_get(void) { - static const HostIdData *volatile host_id_static; const HostIdData *host_id; again: @@ -2938,6 +2942,78 @@ nm_utils_host_id_get_timestamp_ns(void) return _host_id_get()->timestamp_ns; } +static GArray * nmtst_host_id_stack = NULL; +static GMutex nmtst_host_id_lock; +const HostIdData *nmtst_host_id_static_0 = NULL; + +void +nmtst_utils_host_id_push(const guint8 *host_id, + gssize host_id_len, + gboolean is_good, + const gint64 *timestamp_ns) +{ + NM_G_MUTEX_LOCKED(&nmtst_host_id_lock); + gs_free char *str1_to_free = NULL; + HostIdData * h; + + g_assert(host_id_len >= -1); + + if (host_id_len < 0) + host_id_len = host_id ? strlen((const char *) host_id) : 0; + + nm_log_dbg(LOGD_CORE, + "nmtst: host-id push: \"%s\" (%zu), is-good=%d, timestamp=%" G_GINT64_FORMAT "%s", + nm_utils_buf_utf8safe_escape(host_id, + host_id_len, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &str1_to_free), + (gsize) host_id_len, + !!is_good, + timestamp_ns ? *timestamp_ns : 0, + timestamp_ns ? "" : " (not-good)"); + + if (!nmtst_host_id_stack) { + nmtst_host_id_stack = g_array_new(FALSE, FALSE, sizeof(HostIdData)); + nmtst_host_id_static_0 = g_atomic_pointer_get(&host_id_static); + } + + h = nm_g_array_append_new(nmtst_host_id_stack, HostIdData); + + *h = (HostIdData){ + .host_id = nm_memdup(host_id, host_id_len), + .host_id_len = host_id_len, + .timestamp_ns = timestamp_ns ? *timestamp_ns : 0, + .is_good = is_good, + .timestamp_is_good = !!timestamp_ns, + }; + + g_atomic_pointer_set(&host_id_static, h); +} + +void +nmtst_utils_host_id_pop(void) +{ + NM_G_MUTEX_LOCKED(&nmtst_host_id_lock); + HostIdData *h; + + g_assert(nmtst_host_id_stack); + g_assert(nmtst_host_id_stack->len > 0); + + nm_log_dbg(LOGD_CORE, "nmtst: host-id pop"); + + h = &g_array_index(nmtst_host_id_stack, HostIdData, nmtst_host_id_stack->len - 1); + + g_free((char *) h->host_id); + g_array_set_size(nmtst_host_id_stack, nmtst_host_id_stack->len - 1u); + + if (!g_atomic_pointer_compare_and_exchange( + &host_id_static, + h, + nmtst_host_id_stack->len == 0u ? nmtst_host_id_static_0 + : nm_g_array_last(nmtst_host_id_stack, HostIdData))) + g_assert_not_reached(); +} + /*****************************************************************************/ static const UuidData * @@ -3423,15 +3499,14 @@ _is_reserved_ipv6_iid(const guint8 *iid) return FALSE; } -static gboolean -_set_stable_privacy(NMUtilsStableType stable_type, - struct in6_addr * addr, - const char * ifname, - const char * network_id, - guint32 dad_counter, - const guint8 * host_id, - gsize host_id_len, - GError ** error) +void +nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NMUtilsStableType stable_type, + struct in6_addr * addr, + const char * ifname, + const char * network_id, + guint32 dad_counter, + const guint8 * host_id, + gsize host_id_len) { nm_auto_free_checksum GChecksum *sum = NULL; guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA256]; @@ -3480,30 +3555,29 @@ _set_stable_privacy(NMUtilsStableType stable_type, } memcpy(addr->s6_addr + 8, &digest[0], 8); - return TRUE; } -gboolean -nm_utils_ipv6_addr_set_stable_privacy_impl(NMUtilsStableType stable_type, - struct in6_addr * addr, - const char * ifname, - const char * network_id, - guint32 dad_counter, - guint8 * host_id, - gsize host_id_len, - GError ** error) +void +nm_utils_ipv6_addr_set_stable_privacy(NMUtilsStableType stable_type, + struct in6_addr * addr, + const char * ifname, + const char * network_id, + guint32 dad_counter) { - return _set_stable_privacy(stable_type, - addr, - ifname, - network_id, - dad_counter, - host_id, - host_id_len, - error); + const guint8 *host_id; + gsize host_id_len; + + nm_utils_host_id_get(&host_id, &host_id_len); + + nm_utils_ipv6_addr_set_stable_privacy_with_host_id(stable_type, + addr, + ifname, + network_id, + dad_counter, + host_id, + host_id_len); } -#define RFC7217_IDGEN_RETRIES 3 /** * nm_utils_ipv6_addr_set_stable_privacy: * @@ -3513,19 +3587,16 @@ nm_utils_ipv6_addr_set_stable_privacy_impl(NMUtilsStableType stable_type, * Returns: %TRUE on success, %FALSE if the address could not be generated. */ gboolean -nm_utils_ipv6_addr_set_stable_privacy(NMUtilsStableType stable_type, - struct in6_addr * addr, - const char * ifname, - const char * network_id, - guint32 dad_counter, - GError ** error) +nm_utils_ipv6_addr_set_stable_privacy_may_fail(NMUtilsStableType stable_type, + struct in6_addr * addr, + const char * ifname, + const char * network_id, + guint32 dad_counter, + GError ** error) { - const guint8 *host_id; - gsize host_id_len; - g_return_val_if_fail(network_id, FALSE); - if (dad_counter >= RFC7217_IDGEN_RETRIES) { + if (dad_counter >= NM_STABLE_PRIVACY_RFC7217_IDGEN_RETRIES) { g_set_error_literal(error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, @@ -3533,16 +3604,8 @@ nm_utils_ipv6_addr_set_stable_privacy(NMUtilsStableType stable_type, return FALSE; } - nm_utils_host_id_get(&host_id, &host_id_len); - - return _set_stable_privacy(stable_type, - addr, - ifname, - network_id, - dad_counter, - host_id, - host_id_len, - error); + nm_utils_ipv6_addr_set_stable_privacy(stable_type, addr, ifname, network_id, dad_counter); + return TRUE; } /*****************************************************************************/ @@ -4069,8 +4132,8 @@ nm_utils_get_reverse_dns_domains_ip_4(guint32 addr, guint8 plen, GPtrArray *doma len = len0; str = s = g_malloc(len); for (i = octets; i > 0; i--) - nm_utils_strbuf_append(&s, &len, "%u.", p[i - 1] & 0xff); - nm_utils_strbuf_append_str(&s, &len, "in-addr.arpa"); + nm_strbuf_append(&s, &len, "%u.", p[i - 1] & 0xff); + nm_strbuf_append_str(&s, &len, "in-addr.arpa"); g_ptr_array_add(domains, str); @@ -4121,8 +4184,8 @@ nm_utils_get_reverse_dns_domains_ip_6(const struct in6_addr *ip, guint8 plen, GP str = s = g_malloc(len); for (j = nibbles - 1; j >= 0; j--) - nm_utils_strbuf_append(&s, &len, "%x.", (addr.s6_addr[j / 2] >> N_SHIFT(j)) & 0xf); - nm_utils_strbuf_append_str(&s, &len, "ip6.arpa"); + nm_strbuf_append(&s, &len, "%x.", (addr.s6_addr[j / 2] >> N_SHIFT(j)) & 0xf); + nm_strbuf_append_str(&s, &len, "ip6.arpa"); g_ptr_array_add(domains, str); diff --git a/src/core/nm-core-utils.h b/src/core/nm-core-utils.h index 76c340d1..38f56adc 100644 --- a/src/core/nm-core-utils.h +++ b/src/core/nm-core-utils.h @@ -40,7 +40,7 @@ void _nm_singleton_instance_register_destruction(GObject *instance); /* By default, the getter will assert that the singleton will be created only once. You can * change this by redefining NM_DEFINE_SINGLETON_ALLOW_MULTIPLE. */ #ifndef NM_DEFINE_SINGLETON_ALLOW_MULTIPLE - #define NM_DEFINE_SINGLETON_ALLOW_MULTIPLE FALSE +#define NM_DEFINE_SINGLETON_ALLOW_MULTIPLE FALSE #endif #define NM_DEFINE_SINGLETON_GETTER(TYPE, GETTER, GTYPE, ...) \ @@ -247,6 +247,33 @@ const char *const * nm_utils_proc_cmdline_split(void); gboolean nm_utils_host_id_get(const guint8 **out_host_id, gsize *out_host_id_len); gint64 nm_utils_host_id_get_timestamp_ns(void); +void nmtst_utils_host_id_push(const guint8 *host_id, + gssize host_id_len, + gboolean is_good, + const gint64 *timestamp_ns); + +void nmtst_utils_host_id_pop(void); + +static inline void +_nmtst_auto_utils_host_id_context_pop(const char *const *unused) +{ + nmtst_utils_host_id_pop(); +} + +#define _NMTST_UTILS_HOST_ID_CONTEXT(uniq, host_id) \ + _nm_unused nm_auto(_nmtst_auto_utils_host_id_context_pop) \ + const char *const NM_UNIQ_T(_host_id_context_, uniq) = ({ \ + const gint64 _timestamp_ns = 1631000672; \ + \ + nmtst_utils_host_id_push((const guint8 *) "" host_id "", \ + NM_STRLEN(host_id), \ + TRUE, \ + &_timestamp_ns); \ + "" host_id ""; \ + }) + +#define NMTST_UTILS_HOST_ID_CONTEXT(host_id) _NMTST_UTILS_HOST_ID_CONTEXT(NM_UNIQ, host_id) + /*****************************************************************************/ int nm_utils_arp_type_detect_from_hwaddrlen(gsize hwaddr_len); @@ -271,6 +298,8 @@ typedef enum { NM_UTILS_STABLE_TYPE_RANDOM = 3, } NMUtilsStableType; +#define NM_UTILS_STABLE_TYPE_NONE ((NMUtilsStableType) -1) + NMUtilsStableType nm_utils_stable_id_parse(const char *stable_id, const char *deviceid, const char *hwaddr, @@ -281,21 +310,28 @@ NMUtilsStableType nm_utils_stable_id_parse(const char *stable_id, char *nm_utils_stable_id_random(void); char *nm_utils_stable_id_generated_complete(const char *msg); -gboolean nm_utils_ipv6_addr_set_stable_privacy_impl(NMUtilsStableType stable_type, - struct in6_addr * addr, - const char * ifname, - const char * network_id, - guint32 dad_counter, - guint8 * host_id, - gsize host_id_len, - GError ** error); - -gboolean nm_utils_ipv6_addr_set_stable_privacy(NMUtilsStableType id_type, - struct in6_addr * addr, - const char * ifname, - const char * network_id, - guint32 dad_counter, - GError ** error); +#define NM_STABLE_PRIVACY_RFC7217_IDGEN_RETRIES 3 + +void nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NMUtilsStableType stable_type, + struct in6_addr * addr, + const char * ifname, + const char * network_id, + guint32 dad_counter, + const guint8 * host_id, + gsize host_id_len); + +void nm_utils_ipv6_addr_set_stable_privacy(NMUtilsStableType stable_type, + struct in6_addr * addr, + const char * ifname, + const char * network_id, + guint32 dad_counter); + +gboolean nm_utils_ipv6_addr_set_stable_privacy_may_fail(NMUtilsStableType stable_type, + struct in6_addr * addr, + const char * ifname, + const char * network_id, + guint32 dad_counter, + GError ** error); char *nm_utils_hw_addr_gen_random_eth(const char *current_mac_address, const char *generate_mac_address_mask); diff --git a/src/core/nm-dbus-manager.c b/src/core/nm-dbus-manager.c index c47d4dbf..323d0a19 100644 --- a/src/core/nm-dbus-manager.c +++ b/src/core/nm-dbus-manager.c @@ -262,7 +262,7 @@ private_server_closed_connection(GDBusConnection *conn, /* Delay the close of connection to ensure that D-Bus signals * are handled */ - g_idle_add(close_connection_in_idle, info); + nm_g_idle_add(close_connection_in_idle, info); } static gboolean diff --git a/src/core/nm-dbus-object.c b/src/core/nm-dbus-object.c index 04149739..95077626 100644 --- a/src/core/nm-dbus-object.c +++ b/src/core/nm-dbus-object.c @@ -178,7 +178,7 @@ nm_dbus_object_unexport_on_idle(gpointer /* (NMDBusObject *) */ self_take) nm_shutdown_wait_obj_register_object(self, "unexport-dbus-obj-on-idle"); /* pass on ownership. */ - g_idle_add(_unexport_on_idle_cb, g_steal_pointer(&self)); + nm_g_idle_add(_unexport_on_idle_cb, g_steal_pointer(&self)); } /*****************************************************************************/ diff --git a/src/core/nm-dbus-utils.c b/src/core/nm-dbus-utils.c index d3e5612d..7f7b9fb9 100644 --- a/src/core/nm-dbus-utils.c +++ b/src/core/nm-dbus-utils.c @@ -97,27 +97,13 @@ nm_dbus_utils_get_property(GObject *obj, const char *signature, const char *prop void nm_dbus_utils_g_value_set_object_path(GValue *value, gpointer object) { - const char *path; - - g_return_if_fail(!object || NM_IS_DBUS_OBJECT(object)); - - if (object && (path = nm_dbus_object_get_path(object))) - g_value_set_string(value, path); - else - g_value_set_string(value, NULL); + g_value_set_string(value, object ? nm_dbus_object_get_path(object) : NULL); } void nm_dbus_utils_g_value_set_object_path_still_exported(GValue *value, gpointer object) { - const char *path; - - g_return_if_fail(!object || NM_IS_DBUS_OBJECT(object)); - - if (object && (path = nm_dbus_object_get_path_still_exported(object))) - g_value_set_string(value, path); - else - g_value_set_string(value, "/"); + g_value_set_string(value, object ? nm_dbus_object_get_path_still_exported(object) : "/"); } void @@ -152,7 +138,7 @@ nm_dbus_utils_g_value_set_object_path_from_hash( strv[i] = NULL; /* sort the names, to give a well-defined, stable order. */ - nm_utils_strv_sort(strv, i); + nm_strv_sort(strv, i); g_value_take_boxed(value, strv); } diff --git a/src/core/nm-dcb.c b/src/core/nm-dcb.c index 930a1023..f048d999 100644 --- a/src/core/nm-dcb.c +++ b/src/core/nm-dcb.c @@ -35,7 +35,7 @@ do_helper(const char *iface, cmdline = g_strdup_vprintf(fmt, args); va_end(args); - split = nm_utils_strsplit_set_with_empty(cmdline, " "); + split = nm_strsplit_set_with_empty(cmdline, " "); if (!split) { g_set_error(error, NM_MANAGER_ERROR, @@ -258,7 +258,8 @@ _fcoe_setup(const char * iface, flags = nm_setting_dcb_get_app_fcoe_flags(s_dcb); if (flags & NM_SETTING_DCB_FLAG_ENABLE) { - const char *mode = nm_setting_dcb_get_app_fcoe_mode(s_dcb); + const char *mode = + nm_setting_dcb_get_app_fcoe_mode(s_dcb) ?: NM_SETTING_DCB_FCOE_MODE_FABRIC; if (!do_helper(NULL, FCOEADM, run_func, user_data, error, "-m %s -c %s", mode, iface)) return FALSE; diff --git a/src/core/nm-dhcp-config.c b/src/core/nm-dhcp-config.c index 1cbad49e..8a029119 100644 --- a/src/core/nm-dhcp-config.c +++ b/src/core/nm-dhcp-config.c @@ -87,7 +87,7 @@ nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options) priv = NM_DHCP_CONFIG_GET_PRIVATE(self); nm_g_variant_unref(priv->options); - priv->options = g_variant_ref_sink(nm_utils_strdict_to_variant_asv(options)); + priv->options = g_variant_ref_sink(nm_strdict_to_variant_asv(options)); _notify(self, PROP_OPTIONS); } diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c index 32c9db62..b7719786 100644 --- a/src/core/nm-dispatcher.c +++ b/src/core/nm-dispatcher.c @@ -448,17 +448,17 @@ dispatcher_done_cb(GObject *source, GAsyncResult *result, gpointer user_data) dispatcher_call_id_free(call_id); } -static const char *action_table[] = {[NM_DISPATCHER_ACTION_HOSTNAME] = NMD_ACTION_HOSTNAME, - [NM_DISPATCHER_ACTION_PRE_UP] = NMD_ACTION_PRE_UP, - [NM_DISPATCHER_ACTION_UP] = NMD_ACTION_UP, - [NM_DISPATCHER_ACTION_PRE_DOWN] = NMD_ACTION_PRE_DOWN, - [NM_DISPATCHER_ACTION_DOWN] = NMD_ACTION_DOWN, - [NM_DISPATCHER_ACTION_VPN_PRE_UP] = NMD_ACTION_VPN_PRE_UP, - [NM_DISPATCHER_ACTION_VPN_UP] = NMD_ACTION_VPN_UP, - [NM_DISPATCHER_ACTION_VPN_PRE_DOWN] = NMD_ACTION_VPN_PRE_DOWN, - [NM_DISPATCHER_ACTION_VPN_DOWN] = NMD_ACTION_VPN_DOWN, - [NM_DISPATCHER_ACTION_DHCP4_CHANGE] = NMD_ACTION_DHCP4_CHANGE, - [NM_DISPATCHER_ACTION_DHCP6_CHANGE] = NMD_ACTION_DHCP6_CHANGE, +static const char *action_table[] = {[NM_DISPATCHER_ACTION_HOSTNAME] = NMD_ACTION_HOSTNAME, + [NM_DISPATCHER_ACTION_PRE_UP] = NMD_ACTION_PRE_UP, + [NM_DISPATCHER_ACTION_UP] = NMD_ACTION_UP, + [NM_DISPATCHER_ACTION_PRE_DOWN] = NMD_ACTION_PRE_DOWN, + [NM_DISPATCHER_ACTION_DOWN] = NMD_ACTION_DOWN, + [NM_DISPATCHER_ACTION_VPN_PRE_UP] = NMD_ACTION_VPN_PRE_UP, + [NM_DISPATCHER_ACTION_VPN_UP] = NMD_ACTION_VPN_UP, + [NM_DISPATCHER_ACTION_VPN_PRE_DOWN] = NMD_ACTION_VPN_PRE_DOWN, + [NM_DISPATCHER_ACTION_VPN_DOWN] = NMD_ACTION_VPN_DOWN, + [NM_DISPATCHER_ACTION_DHCP_CHANGE_4] = NMD_ACTION_DHCP4_CHANGE, + [NM_DISPATCHER_ACTION_DHCP_CHANGE_6] = NMD_ACTION_DHCP6_CHANGE, [NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE] = NMD_ACTION_CONNECTIVITY_CHANGE}; diff --git a/src/core/nm-dispatcher.h b/src/core/nm-dispatcher.h index d588de4e..8e4f01cb 100644 --- a/src/core/nm-dispatcher.h +++ b/src/core/nm-dispatcher.h @@ -19,11 +19,14 @@ typedef enum { NM_DISPATCHER_ACTION_VPN_UP, NM_DISPATCHER_ACTION_VPN_PRE_DOWN, NM_DISPATCHER_ACTION_VPN_DOWN, - NM_DISPATCHER_ACTION_DHCP4_CHANGE, - NM_DISPATCHER_ACTION_DHCP6_CHANGE, + NM_DISPATCHER_ACTION_DHCP_CHANGE_4, + NM_DISPATCHER_ACTION_DHCP_CHANGE_6, NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE } NMDispatcherAction; +#define NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4) \ + ((IS_IPv4) ? NM_DISPATCHER_ACTION_DHCP_CHANGE_4 : NM_DISPATCHER_ACTION_DHCP_CHANGE_6) + typedef struct NMDispatcherCallId NMDispatcherCallId; typedef void (*NMDispatcherFunc)(NMDispatcherCallId *call_id, gpointer user_data); diff --git a/src/core/nm-firewalld-manager.c b/src/core/nm-firewalld-manager.c index 7866894a..43ab278a 100644 --- a/src/core/nm-firewalld-manager.c +++ b/src/core/nm-firewalld-manager.c @@ -487,7 +487,7 @@ name_owner_changed(NMFirewalldManager *self, const char *owner) just_initied = !priv->dbus_inited; priv->dbus_inited = TRUE; - name_owner_changed = nm_utils_strdup_reset(&priv->name_owner, owner); + name_owner_changed = nm_strdup_reset(&priv->name_owner, owner); now_running = _get_running(priv); diff --git a/src/core/nm-hostname-manager.c b/src/core/nm-hostname-manager.c index 91e9baaa..32dc2db9 100644 --- a/src/core/nm-hostname-manager.c +++ b/src/core/nm-hostname-manager.c @@ -10,8 +10,8 @@ #include #if HAVE_SELINUX - #include - #include +#include +#include #endif #include "libnm-core-aux-intern/nm-common-macros.h" @@ -37,17 +37,17 @@ #if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) \ + defined(HOSTNAME_PERSIST_GENTOO)) \ > 1 - #error "Can only define one of HOSTNAME_PERSIST_*" +#error "Can only define one of HOSTNAME_PERSIST_*" #endif #if defined(HOSTNAME_PERSIST_SUSE) - #define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME +#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME #elif defined(HOSTNAME_PERSIST_SLACKWARE) - #define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME +#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME #elif defined(HOSTNAME_PERSIST_GENTOO) - #define HOSTNAME_FILE HOSTNAME_FILE_GENTOO +#define HOSTNAME_FILE HOSTNAME_FILE_GENTOO #else - #define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT +#define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT #endif /*****************************************************************************/ @@ -86,6 +86,19 @@ NM_DEFINE_SINGLETON_GETTER(NMHostnameManager, nm_hostname_manager_get, NM_TYPE_H /*****************************************************************************/ +static inline GFileMonitor * +_file_monitor_new(const char *path) +{ + gs_unref_object GFile *file = NULL; + + nm_assert(path); + + file = g_file_new_for_path(path); + return g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL); +} + +/*****************************************************************************/ + #if defined(HOSTNAME_PERSIST_GENTOO) static char * read_hostname_gentoo(const char *path) @@ -162,41 +175,6 @@ hostname_is_dynamic(void) } #endif -/* Returns an allocated string which the caller owns and must eventually free */ -char * -nm_hostname_manager_read_hostname(NMHostnameManager *self) -{ - NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); - char * hostname = NULL; - - if (priv->hostnamed_proxy) { - hostname = g_strdup(priv->current_hostname); - goto out; - } - -#if defined(HOSTNAME_PERSIST_SUSE) - if (priv->dhcp_monitor_id && hostname_is_dynamic()) - return NULL; -#endif - -#if defined(HOSTNAME_PERSIST_GENTOO) - hostname = read_hostname_gentoo(HOSTNAME_FILE); -#elif defined(HOSTNAME_PERSIST_SLACKWARE) - hostname = read_hostname_slackware(HOSTNAME_FILE); -#else - if (g_file_get_contents(HOSTNAME_FILE, &hostname, NULL, NULL)) - g_strchomp(hostname); -#endif - -out: - if (hostname && !hostname[0]) { - g_free(hostname); - return NULL; - } - - return hostname; -} - /*****************************************************************************/ const char * @@ -207,76 +185,78 @@ nm_hostname_manager_get_hostname(NMHostnameManager *self) } static void -_set_hostname_take(NMHostnameManager *self, char *hostname) +_set_hostname(NMHostnameManager *self, const char *hostname) { NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); + char * old_hostname; + + hostname = nm_str_not_empty(hostname); + + if (nm_streq0(hostname, priv->current_hostname)) + return; _LOGI("hostname changed from %s%s%s to %s%s%s", NM_PRINT_FMT_QUOTED(priv->current_hostname, "\"", priv->current_hostname, "\"", "(none)"), NM_PRINT_FMT_QUOTED(hostname, "\"", hostname, "\"", "(none)")); - g_free(priv->current_hostname); - priv->current_hostname = hostname; - _notify(self, PROP_HOSTNAME); -} - -static void -_set_hostname(NMHostnameManager *self, const char *hostname) -{ - NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); + old_hostname = priv->current_hostname; + priv->current_hostname = g_strdup(hostname); + g_free(old_hostname); - hostname = nm_str_not_empty(hostname); - if (!nm_streq0(hostname, priv->current_hostname)) - _set_hostname_take(self, g_strdup(hostname)); + _notify(self, PROP_HOSTNAME); } static void -_set_hostname_read(NMHostnameManager *self) +_set_hostname_read_file(NMHostnameManager *self) { - NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); - char * hostname; + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); + gs_free char * hostname = NULL; if (priv->hostnamed_proxy) { /* read-hostname returns the current hostname with hostnamed. */ return; } - hostname = nm_hostname_manager_read_hostname(self); - - if (nm_streq0(hostname, priv->current_hostname)) { - g_free(hostname); +#if defined(HOSTNAME_PERSIST_SUSE) + if (priv->dhcp_monitor_id && hostname_is_dynamic()) return; - } +#endif + +#if defined(HOSTNAME_PERSIST_GENTOO) + hostname = read_hostname_gentoo(HOSTNAME_FILE); +#elif defined(HOSTNAME_PERSIST_SLACKWARE) + hostname = read_hostname_slackware(HOSTNAME_FILE); +#else + if (g_file_get_contents(HOSTNAME_FILE, &hostname, NULL, NULL)) + g_strchomp(hostname); +#endif - _set_hostname_take(self, hostname); + _set_hostname(self, hostname); } /*****************************************************************************/ -typedef struct { - char * hostname; - NMHostnameManagerSetHostnameCb cb; - gpointer user_data; -} SetHostnameInfo; - static void set_transient_hostname_done(GObject *object, GAsyncResult *res, gpointer user_data) { - GDBusProxy *proxy = G_DBUS_PROXY(object); - gs_free SetHostnameInfo *info = user_data; - gs_unref_variant GVariant *result = NULL; - gs_free_error GError *error = NULL; + GDBusProxy * proxy = G_DBUS_PROXY(object); + gs_unref_variant GVariant *result = NULL; + gs_free_error GError * error = NULL; + gs_free char * hostname = NULL; + NMHostnameManagerSetHostnameCb cb; + gpointer cb_user_data; + + nm_utils_user_data_unpack(user_data, &hostname, &cb, &cb_user_data); result = g_dbus_proxy_call_finish(proxy, res, &error); if (error) { _LOGW("couldn't set the system hostname to '%s' using hostnamed: %s", - info->hostname, + hostname, error->message); } - info->cb(info->hostname, !error, info->user_data); - g_free(info->hostname); + cb(hostname, !error, cb_user_data); } void @@ -286,7 +266,6 @@ nm_hostname_manager_set_transient_hostname(NMHostnameManager * self, gpointer user_data) { NMHostnameManagerPrivate *priv; - SetHostnameInfo * info; g_return_if_fail(NM_IS_HOSTNAME_MANAGER(self)); @@ -297,11 +276,6 @@ nm_hostname_manager_set_transient_hostname(NMHostnameManager * self, return; } - info = g_new0(SetHostnameInfo, 1); - info->hostname = g_strdup(hostname); - info->cb = cb; - info->user_data = user_data; - g_dbus_proxy_call(priv->hostnamed_proxy, "SetHostname", g_variant_new("(sb)", hostname, FALSE), @@ -309,7 +283,7 @@ nm_hostname_manager_set_transient_hostname(NMHostnameManager * self, -1, NULL, set_transient_hostname_done, - info); + nm_utils_user_data_pack(g_strdup(hostname), cb, user_data)); } gboolean @@ -428,71 +402,63 @@ nm_hostname_manager_write_hostname(NMHostnameManager *self, const char *hostname return TRUE; } -gboolean -nm_hostname_manager_validate_hostname(const char *hostname) -{ - const char *p; - gboolean dot = TRUE; - - if (!hostname || !hostname[0]) - return FALSE; - - for (p = hostname; *p; p++) { - if (*p == '.') { - if (dot) - return FALSE; - dot = TRUE; - } else { - if (!g_ascii_isalnum(*p) && (*p != '-') && (*p != '_')) - return FALSE; - dot = FALSE; - } - } +/*****************************************************************************/ - if (dot) - return FALSE; +static void +hostnamed_properties_changed(GDBusProxy *proxy, + GVariant * changed_properties, + char ** invalidated_properties, + gpointer user_data) +{ + NMHostnameManager * self = user_data; + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); + gs_unref_variant GVariant *variant = NULL; - return (p - hostname <= HOST_NAME_MAX); + variant = g_dbus_proxy_get_cached_property(priv->hostnamed_proxy, "StaticHostname"); + if (variant && g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) + _set_hostname(self, g_variant_get_string(variant, NULL)); } +/*****************************************************************************/ + static void -hostname_file_changed_cb(GFileMonitor * monitor, - GFile * file, - GFile * other_file, - GFileMonitorEvent event_type, - gpointer user_data) +_file_monitors_file_changed_cb(GFileMonitor * monitor, + GFile * file, + GFile * other_file, + GFileMonitorEvent event_type, + gpointer user_data) { - _set_hostname_read(user_data); + _set_hostname_read_file(user_data); } -/*****************************************************************************/ - static void -hostnamed_properties_changed(GDBusProxy *proxy, - GVariant * changed_properties, - char ** invalidated_properties, - gpointer user_data) +_file_monitors_clear(NMHostnameManager *self) { - NMHostnameManager * self = user_data; NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); - GVariant * v_hostname; - v_hostname = g_dbus_proxy_get_cached_property(priv->hostnamed_proxy, "StaticHostname"); - if (v_hostname) { - _set_hostname(self, g_variant_get_string(v_hostname, NULL)); - g_variant_unref(v_hostname); + if (priv->monitor) { + nm_clear_g_signal_handler(priv->monitor, &priv->monitor_id); + g_file_monitor_cancel(priv->monitor); + g_clear_object(&priv->monitor); + } + + if (priv->dhcp_monitor) { + nm_clear_g_signal_handler(priv->dhcp_monitor, &priv->dhcp_monitor_id); + g_file_monitor_cancel(priv->dhcp_monitor); + g_clear_object(&priv->dhcp_monitor); } } static void -setup_hostname_file_monitors(NMHostnameManager *self) +_file_monitors_setup(NMHostnameManager *self) { NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self); GFileMonitor * monitor; const char * path = HOSTNAME_FILE; - char * link_path = NULL; + gs_free char * link_path = NULL; struct stat file_stat; - GFile * file; + + _file_monitors_clear(self); /* resolve the path to the hostname file if it is a symbolic link */ if (lstat(path, &file_stat) == 0 && S_ISLNK(file_stat.st_mode) @@ -505,29 +471,24 @@ setup_hostname_file_monitors(NMHostnameManager *self) } /* monitor changes to hostname file */ - file = g_file_new_for_path(path); - monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL); - g_object_unref(file); - g_free(link_path); + monitor = _file_monitor_new(path); if (monitor) { priv->monitor_id = - g_signal_connect(monitor, "changed", G_CALLBACK(hostname_file_changed_cb), self); + g_signal_connect(monitor, "changed", G_CALLBACK(_file_monitors_file_changed_cb), self); priv->monitor = monitor; } #if defined(HOSTNAME_PERSIST_SUSE) /* monitor changes to dhcp file to know whether the hostname is valid */ - file = g_file_new_for_path(CONF_DHCP); - monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL); - g_object_unref(file); + monitor = _file_monitor_new(CONF_DHCP); if (monitor) { priv->dhcp_monitor_id = - g_signal_connect(monitor, "changed", G_CALLBACK(hostname_file_changed_cb), self); + g_signal_connect(monitor, "changed", G_CALLBACK(_file_monitors_file_changed_cb), self); priv->dhcp_monitor = monitor; } #endif - _set_hostname_read(self); + _set_hostname_read_file(self); } /*****************************************************************************/ @@ -591,7 +552,7 @@ constructed(GObject *object) } if (!priv->hostnamed_proxy) - setup_hostname_file_monitors(self); + _file_monitors_setup(self); G_OBJECT_CLASS(nm_hostname_manager_parent_class)->constructed(object); } @@ -609,21 +570,7 @@ dispose(GObject *object) g_clear_object(&priv->hostnamed_proxy); } - if (priv->monitor) { - if (priv->monitor_id) - g_signal_handler_disconnect(priv->monitor, priv->monitor_id); - - g_file_monitor_cancel(priv->monitor); - g_clear_object(&priv->monitor); - } - - if (priv->dhcp_monitor) { - if (priv->dhcp_monitor_id) - g_signal_handler_disconnect(priv->dhcp_monitor, priv->dhcp_monitor_id); - - g_file_monitor_cancel(priv->dhcp_monitor); - g_clear_object(&priv->dhcp_monitor); - } + _file_monitors_clear(self); nm_clear_g_free(&priv->current_hostname); diff --git a/src/core/nm-hostname-manager.h b/src/core/nm-hostname-manager.h index 0fa13771..ff109e7e 100644 --- a/src/core/nm-hostname-manager.h +++ b/src/core/nm-hostname-manager.h @@ -36,8 +36,6 @@ NMHostnameManager *nm_hostname_manager_get(void); const char *nm_hostname_manager_get_hostname(NMHostnameManager *self); -char *nm_hostname_manager_read_hostname(NMHostnameManager *self); - gboolean nm_hostname_manager_write_hostname(NMHostnameManager *self, const char *hostname); void nm_hostname_manager_set_transient_hostname(NMHostnameManager * self, @@ -47,6 +45,4 @@ void nm_hostname_manager_set_transient_hostname(NMHostnameManager * s gboolean nm_hostname_manager_get_transient_hostname(NMHostnameManager *self, char **hostname); -gboolean nm_hostname_manager_validate_hostname(const char *hostname); - #endif /* __NM_HOSTNAME_MANAGER_H__ */ diff --git a/src/core/nm-iface-helper.c b/src/core/nm-iface-helper.c index 296bf091..83ae1b54 100644 --- a/src/core/nm-iface-helper.c +++ b/src/core/nm-iface-helper.c @@ -5,7 +5,6 @@ #include "src/core/nm-default-daemon.h" -#include #include #include #include @@ -31,7 +30,7 @@ #include "libnm-systemd-core/nm-sd.h" #if !defined(NM_DIST_VERSION) - #define NM_DIST_VERSION VERSION +#define NM_DIST_VERSION VERSION #endif #define NMIH_PID_FILE_FMT NMRUNDIR "/nm-iface-helper-%d.pid" @@ -93,24 +92,29 @@ static struct { /*****************************************************************************/ static void -dhcp4_state_changed(NMDhcpClient *client, - NMDhcpState state, - NMIP4Config * ip4_config, - GHashTable * options, - gpointer user_data) +_dhcp_client_notify_cb(NMDhcpClient * client, + const NMDhcpClientNotifyData *notify_data, + gpointer user_data) { static NMIP4Config *last_config = NULL; NMIP4Config * existing; gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; gs_free_error GError *error = NULL; + NMIP4Config * ip4_config; - g_return_if_fail(!ip4_config || NM_IS_IP4_CONFIG(ip4_config)); + if (!notify_data || notify_data->notify_type != NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED) + g_return_if_reached(); - _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", state); + nm_assert(!notify_data->state_changed.ip_config + || NM_IS_IP4_CONFIG(notify_data->state_changed.ip_config)); - switch (state) { + _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) notify_data->state_changed.dhcp_state); + + switch (notify_data->state_changed.dhcp_state) { case NM_DHCP_STATE_BOUND: case NM_DHCP_STATE_EXTENDED: + ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config); + g_assert(ip4_config); g_assert(nm_ip4_config_get_ifindex(ip4_config) == gl.ifindex); @@ -177,41 +181,33 @@ ndisc_config_changed(NMNDisc * ndisc, } if (changed & NM_NDISC_CONFIG_ADDRESSES) { - guint8 plen; guint32 ifa_flags; /* Check, whether kernel is recent enough to help user space handling RA. * If it's not supported, we have no ipv6-privacy and must add autoconf * addresses as /128. The reason for the /128 is to prevent the kernel * from adding a prefix route for this address. */ - ifa_flags = 0; - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) { - ifa_flags |= IFA_F_NOPREFIXROUTE; - if (NM_IN_SET(global_opt.tempaddr, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) - ifa_flags |= IFA_F_MANAGETEMPADDR; - plen = 64; - } else - plen = 128; + ifa_flags = IFA_F_NOPREFIXROUTE; + if (NM_IN_SET(global_opt.tempaddr, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) + ifa_flags |= IFA_F_MANAGETEMPADDR; nm_ip6_config_reset_addresses_ndisc(ndisc_config, rdata->addresses, rdata->addresses_n, - plen, + 64, ifa_flags); } if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) { - nm_ip6_config_reset_routes_ndisc( - ndisc_config, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - RT_TABLE_MAIN, - global_opt.priority_v6, - nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); + nm_ip6_config_reset_routes_ndisc(ndisc_config, + rdata->gateways, + rdata->gateways_n, + rdata->routes, + rdata->routes_n, + RT_TABLE_MAIN, + global_opt.priority_v6); } if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) { @@ -685,8 +681,8 @@ main(int argc, char *argv[]) g_error("failure to start DHCP: %s", error->message); g_signal_connect(dhcp4_client, - NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_CALLBACK(dhcp4_state_changed), + NM_DHCP_CLIENT_NOTIFY, + G_CALLBACK(_dhcp_client_notify_cb), NULL); } @@ -698,7 +694,9 @@ main(int argc, char *argv[]) guint32 default_ra_timeout; int max_addresses; - nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, gl.ifindex, TRUE); + nm_platform_link_set_inet6_addr_gen_mode(NM_PLATFORM_GET, + gl.ifindex, + NM_IN6_ADDR_GEN_MODE_NONE); if (global_opt.stable_id && (global_opt.stable_id[0] >= '0' && global_opt.stable_id[0] <= '9') @@ -710,12 +708,12 @@ main(int argc, char *argv[]) stable_id = &global_opt.stable_id[2]; } - nm_lndp_ndisc_get_sysctl(NM_PLATFORM_GET, - global_opt.ifname, - &max_addresses, - &router_solicitations, - &router_solicitation_interval, - &default_ra_timeout); + nm_ndisc_get_sysctl(NM_PLATFORM_GET, + global_opt.ifname, + &max_addresses, + &router_solicitations, + &router_solicitation_interval, + &default_ra_timeout); ndisc = nm_lndp_ndisc_new(NM_PLATFORM_GET, gl.ifindex, diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c index 52a8faa7..90398dcc 100644 --- a/src/core/nm-ip4-config.c +++ b/src/core/nm-ip4-config.c @@ -287,27 +287,28 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMIP4Config, PROP_DNS_PRIORITY, ); typedef struct { - bool metered : 1; - bool never_default : 1; - guint32 mtu; - int ifindex; - NMIPConfigSource mtu_source; - int dns_priority; - NMSettingConnectionMdns mdns; - NMSettingConnectionLlmnr llmnr; - GArray * nameservers; - GPtrArray * domains; - GPtrArray * searches; - GPtrArray * dns_options; - GArray * nis; - char * nis_domain; - GArray * wins; - GVariant * address_data_variant; - GVariant * addresses_variant; - GVariant * route_data_variant; - GVariant * routes_variant; - NMDedupMultiIndex * multi_idx; - const NMPObject * best_default_route; + bool metered : 1; + bool never_default : 1; + guint32 mtu; + int ifindex; + NMIPConfigSource mtu_source; + int dns_priority; + NMSettingConnectionMdns mdns; + NMSettingConnectionLlmnr llmnr; + NMSettingConnectionDnsOverTls dns_over_tls; + GArray * nameservers; + GPtrArray * domains; + GPtrArray * searches; + GPtrArray * dns_options; + GArray * nis; + char * nis_domain; + GArray * wins; + GVariant * address_data_variant; + GVariant * addresses_variant; + GVariant * route_data_variant; + GVariant * routes_variant; + NMDedupMultiIndex * multi_idx; + const NMPObject * best_default_route; union { NMIPConfigDedupMultiIdxType idx_ip4_addresses_; NMDedupMultiIdxType idx_ip4_addresses; @@ -408,11 +409,11 @@ _nm_ip_config_best_default_route_find_better(const NMPObject *obj_cur, const NMP NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) || NMP_OBJECT_GET_TYPE(obj_cur) == NMP_OBJECT_GET_TYPE(obj_cmp)); - nm_assert(!obj_cur || nmp_object_ip_route_is_best_defaut_route(obj_cur)); + nm_assert(!obj_cur || nmp_object_ip_route_is_best_default_route(obj_cur)); /* assumes that @obj_cur is already the best default route (or NULL). It checks whether * @obj_cmp is also a default route and returns the best of both. */ - if (obj_cmp && nmp_object_ip_route_is_best_defaut_route(obj_cmp)) { + if (obj_cmp && nmp_object_ip_route_is_best_default_route(obj_cmp)) { guint32 metric_cur, metric_cmp; if (!obj_cur) @@ -747,12 +748,13 @@ nm_ip4_config_commit(const NMIP4Config * self, } void -nm_ip4_config_merge_setting(NMIP4Config * self, - NMSettingIPConfig * setting, - NMSettingConnectionMdns mdns, - NMSettingConnectionLlmnr llmnr, - guint32 route_table, - guint32 route_metric) +nm_ip4_config_merge_setting(NMIP4Config * self, + NMSettingIPConfig * setting, + NMSettingConnectionMdns mdns, + NMSettingConnectionLlmnr llmnr, + NMSettingConnectionDnsOverTls dns_over_tls, + guint32 route_table, + guint32 route_metric) { guint naddresses, nroutes, nnameservers, nsearches; int i, priority; @@ -868,6 +870,7 @@ nm_ip4_config_merge_setting(NMIP4Config * self, nm_ip4_config_mdns_set(self, mdns); nm_ip4_config_llmnr_set(self, llmnr); + nm_ip4_config_dns_over_tls_set(self, dns_over_tls); nm_ip4_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting)); @@ -1112,6 +1115,10 @@ nm_ip4_config_merge(NMIP4Config * dst, /* LLMNR */ nm_ip4_config_llmnr_set(dst, NM_MAX(nm_ip4_config_llmnr_get(src), nm_ip4_config_llmnr_get(dst))); + /* dns_over_tls */ + nm_ip4_config_dns_over_tls_set( + dst, + NM_MAX(nm_ip4_config_dns_over_tls_get(src), nm_ip4_config_dns_over_tls_get(dst))); g_object_thaw_notify(G_OBJECT(dst)); } @@ -1357,6 +1364,10 @@ nm_ip4_config_subtract(NMIP4Config * dst, if (nm_ip4_config_llmnr_get(src) == nm_ip4_config_llmnr_get(dst)) nm_ip4_config_llmnr_set(dst, NM_SETTING_CONNECTION_LLMNR_DEFAULT); + /* dns_over_tls */ + if (nm_ip4_config_dns_over_tls_get(src) == nm_ip4_config_dns_over_tls_get(dst)) + nm_ip4_config_dns_over_tls_set(dst, NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); + g_object_thaw_notify(G_OBJECT(dst)); } @@ -1466,6 +1477,7 @@ skip_routes: /* ignore WINS */ /* ignore mdns */ /* ignore LLMNR */ + /* ignore dns_over_tls */ if (update_dst) g_object_thaw_notify(G_OBJECT(dst)); @@ -1777,6 +1789,11 @@ nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *releva has_relevant_changes = TRUE; } + if (src_priv->dns_over_tls != dst_priv->dns_over_tls) { + dst_priv->dns_over_tls = src_priv->dns_over_tls; + has_relevant_changes = TRUE; + } + /* DNS priority */ if (src_priv->dns_priority != dst_priv->dns_priority) { nm_ip4_config_set_dns_priority(dst, src_priv->dns_priority); @@ -2333,7 +2350,7 @@ _nm_ip_config_check_and_add_domain(GPtrArray *array, const char *domain) if (domain[len - 1] == '.') domain = copy = g_strndup(domain, len - 1); - if (nm_utils_strv_find_first((char **) array->pdata, array->len, domain) >= 0) { + if (nm_strv_ptrarray_find_first(array, domain) >= 0) { g_free(copy); return FALSE; } @@ -2521,6 +2538,18 @@ nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr) NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr = llmnr; } +NMSettingConnectionDnsOverTls +nm_ip4_config_dns_over_tls_get(const NMIP4Config *self) +{ + return NM_IP4_CONFIG_GET_PRIVATE(self)->dns_over_tls; +} + +void +nm_ip4_config_dns_over_tls_set(NMIP4Config *self, NMSettingConnectionDnsOverTls dns_over_tls) +{ + NM_IP4_CONFIG_GET_PRIVATE(self)->dns_over_tls = dns_over_tls; +} + /*****************************************************************************/ NMIPConfigFlags @@ -2901,6 +2930,10 @@ nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only) if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT) g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + val = nm_ip4_config_dns_over_tls_get(self); + if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + /* FIXME(ip-config-checksum): the DNS priority should be considered relevant * and added into the checksum as well, but this can't be done right now * because in the DNS manager we rely on the fact that an empty @@ -3095,14 +3128,15 @@ nm_ip4_config_init(NMIP4Config *self) nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_routes, NMP_OBJECT_TYPE_IP4_ROUTE); - priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; - priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32)); - priv->domains = g_ptr_array_new_with_free_func(g_free); - priv->searches = g_ptr_array_new_with_free_func(g_free); - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - priv->nis = g_array_new(FALSE, TRUE, sizeof(guint32)); - priv->wins = g_array_new(FALSE, TRUE, sizeof(guint32)); + priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + priv->dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32)); + priv->domains = g_ptr_array_new_with_free_func(g_free); + priv->searches = g_ptr_array_new_with_free_func(g_free); + priv->dns_options = g_ptr_array_new_with_free_func(g_free); + priv->nis = g_array_new(FALSE, TRUE, sizeof(guint32)); + priv->wins = g_array_new(FALSE, TRUE, sizeof(guint32)); } NMIP4Config * diff --git a/src/core/nm-ip4-config.h b/src/core/nm-ip4-config.h index fdaa6d46..2eb193b2 100644 --- a/src/core/nm-ip4-config.h +++ b/src/core/nm-ip4-config.h @@ -124,12 +124,13 @@ gboolean nm_ip4_config_commit(const NMIP4Config * self, NMPlatform * platform, NMIPRouteTableSyncMode route_table_sync); -void nm_ip4_config_merge_setting(NMIP4Config * self, - NMSettingIPConfig * setting, - NMSettingConnectionMdns mdns, - NMSettingConnectionLlmnr llmnr, - guint32 route_table, - guint32 route_metric); +void nm_ip4_config_merge_setting(NMIP4Config * self, + NMSettingIPConfig * setting, + NMSettingConnectionMdns mdns, + NMSettingConnectionLlmnr llmnr, + NMSettingConnectionDnsOverTls dns_over_tls, + guint32 route_table, + guint32 route_metric); NMSetting *nm_ip4_config_create_setting(const NMIP4Config *self); void nm_ip4_config_merge(NMIP4Config * dst, @@ -161,6 +162,8 @@ NMSettingConnectionMdns nm_ip4_config_mdns_get(const NMIP4Config *self); void nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns); NMSettingConnectionLlmnr nm_ip4_config_llmnr_get(const NMIP4Config *self); void nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr); +NMSettingConnectionDnsOverTls nm_ip4_config_dns_over_tls_get(const NMIP4Config *self); +void nm_ip4_config_dns_over_tls_set(NMIP4Config *self, NMSettingConnectionDnsOverTls dns_over_tls); void nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask); NMIPConfigFlags nm_ip4_config_get_config_flags(const NMIP4Config *self); @@ -275,7 +278,7 @@ NM_IS_IP_CONFIG_ADDR_FAMILY(gconstpointer config, int addr_family) } #if _NM_CC_SUPPORT_GENERIC - /* _NM_IS_IP_CONFIG() is a bit unusual. If _Generic() is supported, +/* _NM_IS_IP_CONFIG() is a bit unusual. If _Generic() is supported, * it checks whether @config is either NM_IS_IP4_CONFIG() or NM_IS_IP6_CONFIG(), * depending on the pointer type of @config. * @@ -286,10 +289,10 @@ NM_IS_IP_CONFIG_ADDR_FAMILY(gconstpointer config, int addr_family) * NMIP4Config *ptr = nm_ip4_config_new(...); * g_assert (_NM_IS_IP_CONFIG (ptr, ptr)); */ - #define _NM_IS_IP_CONFIG(typeexpr, config) \ - ({ \ - const void *const _config = (config); \ - _Generic ((typeexpr), \ +#define _NM_IS_IP_CONFIG(typeexpr, config) \ + ({ \ + const void *const _config = (config); \ + _Generic ((typeexpr), \ const void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ const void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \ @@ -306,9 +309,9 @@ NM_IS_IP_CONFIG_ADDR_FAMILY(gconstpointer config, int addr_family) const NMIP6Config * : (NM_IS_IP6_CONFIG (_config)), \ NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \ NMIP6Config * : (NM_IS_IP6_CONFIG (_config))); \ - }) + }) #else - #define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config) +#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config) #endif #define NM_IP_CONFIG_CAST(config) \ diff --git a/src/core/nm-ip6-config.c b/src/core/nm-ip6-config.c index 65e84737..5ec68bd2 100644 --- a/src/core/nm-ip6-config.c +++ b/src/core/nm-ip6-config.c @@ -1678,8 +1678,7 @@ nm_ip6_config_reset_routes_ndisc(NMIP6Config * self, const NMNDiscRoute * routes, guint routes_n, guint32 route_table, - guint32 route_metric, - gboolean kernel_support_rta_pref) + guint32 route_metric) { NMIP6ConfigPrivate *priv; guint i; @@ -1735,7 +1734,6 @@ nm_ip6_config_reset_routes_ndisc(NMIP6Config * self, .table_coerced = nm_platform_route_table_coerce(route_table), .metric = route_metric, }; - const NMIcmpv6RouterPref first_pref = gateways[0].preference; for (i = 0; i < gateways_n; i++) { r.gateway = gateways[i].address; @@ -1753,13 +1751,6 @@ nm_ip6_config_reset_routes_ndisc(NMIP6Config * self, changed = TRUE; new_best_default_route = _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new); - - if (first_pref != gateways[i].preference && !kernel_support_rta_pref) { - /* We are unable to configure a router preference. Hence, we skip all gateways - * with a different preference from the first gateway. Note, that the gateways - * are sorted in order of highest to lowest preference. */ - break; - } } } diff --git a/src/core/nm-ip6-config.h b/src/core/nm-ip6-config.h index 8694ab0c..a54040fc 100644 --- a/src/core/nm-ip6-config.h +++ b/src/core/nm-ip6-config.h @@ -198,8 +198,7 @@ void nm_ip6_config_reset_routes_ndisc(NMIP6Config * self, const struct _NMNDiscRoute * routes, guint routes_n, guint32 route_table, - guint32 route_metric, - gboolean kernel_support_rta_pref); + guint32 route_metric); void nm_ip6_config_update_routes_metric(NMIP6Config *self, gint64 metric); diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index f2ec040b..033c8942 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -131,6 +131,14 @@ struct _NML3ConfigData { guint32 ndisc_reachable_time_msec_val; guint32 ndisc_retrans_timer_msec_val; + union { + struct { + NMOptionBool never_default_6; + NMOptionBool never_default_4; + }; + NMOptionBool never_default_x[2]; + }; + NMTernary metered : 3; NMTernary proxy_browser_only : 3; @@ -323,7 +331,7 @@ _strv_ptrarray_merge(GPtrArray **p_dst, const GPtrArray *src) const char *s = src->pdata[i]; if (dst_initial_len > 0 - && nm_utils_strv_find_first((char **) ((*p_dst)->pdata), dst_initial_len, s) >= 0) + && nm_strv_find_first((const char *const *) ((*p_dst)->pdata), dst_initial_len, s) >= 0) continue; g_ptr_array_add(*p_dst, g_strdup(s)); @@ -439,27 +447,23 @@ nm_l3_config_data_log(const NML3ConfigData *self, const char *s_prefix = "ndisc: "; if (self->ndisc_hop_limit_set) { - nm_utils_strbuf_append(&p, - &l, - "%shop-limit=%d", - s_prefix, - self->ndisc_hop_limit_val); + nm_strbuf_append(&p, &l, "%shop-limit=%d", s_prefix, self->ndisc_hop_limit_val); s_prefix = ", "; } if (self->ndisc_reachable_time_msec_set) { - nm_utils_strbuf_append(&p, - &l, - "%sreachable-time-msec=%u", - s_prefix, - self->ndisc_reachable_time_msec_val); + nm_strbuf_append(&p, + &l, + "%sreachable-time-msec=%u", + s_prefix, + self->ndisc_reachable_time_msec_val); s_prefix = ", "; } if (self->ndisc_retrans_timer_msec_set) { - nm_utils_strbuf_append(&p, - &l, - "%sretrans-timer-msec=%u", - s_prefix, - self->ndisc_retrans_timer_msec_val); + nm_strbuf_append(&p, + &l, + "%sretrans-timer-msec=%u", + s_prefix, + self->ndisc_retrans_timer_msec_val); s_prefix = ", "; } _L("%s", sbuf); @@ -541,6 +545,9 @@ nm_l3_config_data_log(const NML3ConfigData *self, options[i].value_str); } } + + if (self->never_default_x[IS_IPv4] != NM_OPTION_BOOL_DEFAULT) + _L("never-default: %s", self->never_default_x[IS_IPv4] ? "yes" : "no"); } if (self->mdns != NM_SETTING_CONNECTION_MDNS_DEFAULT) { @@ -643,12 +650,14 @@ _idx_type_init(DedupMultiIdxType *idx_type, NMPObjectType obj_type) } NML3ConfigData * -nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex) +nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSource source) { NML3ConfigData *self; nm_assert(multi_idx); nm_assert(ifindex > 0); + nm_assert(source == NM_IP_CONFIG_SOURCE_UNKNOWN + || (source >= NM_IP_CONFIG_SOURCE_KERNEL && source <= NM_IP_CONFIG_SOURCE_USER)); self = g_slice_new(NML3ConfigData); *self = (NML3ConfigData){ @@ -663,7 +672,9 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex) .proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN, .route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, .route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE, - .source = NM_IP_CONFIG_SOURCE_UNKNOWN, + .never_default_6 = NM_OPTION_BOOL_DEFAULT, + .never_default_4 = NM_OPTION_BOOL_DEFAULT, + .source = source, .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, .ndisc_hop_limit_set = FALSE, .ndisc_reachable_time_msec_set = FALSE, @@ -691,17 +702,21 @@ nm_l3_config_data_ref(const NML3ConfigData *self) const NML3ConfigData * nm_l3_config_data_ref_and_seal(const NML3ConfigData *self) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - ((NML3ConfigData *) self)->is_sealed = TRUE; - ((NML3ConfigData *) self)->ref_count++; + if (self) { + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + ((NML3ConfigData *) self)->is_sealed = TRUE; + ((NML3ConfigData *) self)->ref_count++; + } return self; } const NML3ConfigData * nm_l3_config_data_seal(const NML3ConfigData *self) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - ((NML3ConfigData *) self)->is_sealed = TRUE; + if (self) { + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + ((NML3ConfigData *) self)->is_sealed = TRUE; + } return self; } @@ -871,6 +886,26 @@ nm_l3_config_data_lookup_obj(const NML3ConfigData *self, const NMPObject *obj) return nm_dedup_multi_index_lookup_obj(self->multi_idx, idx, obj); } +const NMPlatformIP4Address * +nm_l3_config_data_lookup_address_4(const NML3ConfigData *self, + in_addr_t addr, + guint8 plen, + in_addr_t peer_addr) +{ + const NMDedupMultiEntry *head; + NMPObject obj_stack; + + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + nmp_object_stackinit_id_ip4_address(&obj_stack, self->ifindex, addr, plen, peer_addr); + + head = nm_l3_config_data_lookup_obj(self, &obj_stack); + if (!head) + return NULL; + + return NMP_OBJECT_CAST_IP4_ADDRESS(head->obj); +} + const NMPlatformIP6Address * nm_l3_config_data_lookup_address_6(const NML3ConfigData *self, const struct in6_addr *addr) { @@ -879,7 +914,7 @@ nm_l3_config_data_lookup_address_6(const NML3ConfigData *self, const struct in6_ nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - /* this works only, because the primary key for a Ipv6 address is the + /* this works only, because the primary key for a IPv6 address is the * ifindex and the "struct in6_addr". */ nmp_object_stackinit_id_ip6_address(&obj_stack, self->ifindex, addr); @@ -1104,6 +1139,14 @@ _l3_config_data_add_obj(NMDedupMultiIndex * multi_idx, obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source; modified = TRUE; } + + /* OR assume_config_once flag */ + if (obj_new->ip_address.a_assume_config_once + && !obj_old->ip_address.a_assume_config_once) { + obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); + obj_new_stackinit.ip_address.a_assume_config_once = TRUE; + modified = TRUE; + } break; case NMP_OBJECT_TYPE_IP4_ROUTE: case NMP_OBJECT_TYPE_IP6_ROUTE: @@ -1113,6 +1156,14 @@ _l3_config_data_add_obj(NMDedupMultiIndex * multi_idx, obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source; modified = TRUE; } + + /* OR assume_config_once flag */ + if (obj_new->ip_route.r_assume_config_once + && !obj_old->ip_route.r_assume_config_once) { + obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); + obj_new_stackinit.ip_route.r_assume_config_once = TRUE; + modified = TRUE; + } break; default: nm_assert_not_reached(); @@ -1168,11 +1219,11 @@ _l3_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObj NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) || NMP_OBJECT_GET_TYPE(obj_cur) == NMP_OBJECT_GET_TYPE(obj_cmp)); - nm_assert(!obj_cur || nmp_object_ip_route_is_best_defaut_route(obj_cur)); + nm_assert(!obj_cur || nmp_object_ip_route_is_best_default_route(obj_cur)); /* assumes that @obj_cur is already the best default route (or NULL). It checks whether * @obj_cmp is also a default route and returns the best of both. */ - if (obj_cmp && nmp_object_ip_route_is_best_defaut_route(obj_cmp)) { + if (obj_cmp && nmp_object_ip_route_is_best_default_route(obj_cmp)) { guint32 metric_cur, metric_cmp; if (!obj_cur) @@ -1297,9 +1348,16 @@ const NMPObject * nm_l3_config_data_get_best_default_route(const NML3ConfigData *self, int addr_family) { nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - nm_assert_addr_family(addr_family); - return self->best_default_route_x[NM_IS_IPv4(addr_family)]; + switch (addr_family) { + case AF_INET: + return self->best_default_route_4; + case AF_INET6: + return self->best_default_route_6; + case AF_UNSPEC: + return self->best_default_route_4 ?: self->best_default_route_6; + } + return nm_assert_unreachable_val(NULL); } /*****************************************************************************/ @@ -1336,10 +1394,15 @@ _check_and_add_domain(GPtrArray **p_arr, const char *domain) gconstpointer nm_l3_config_data_get_nameservers(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return _garray_inaddr_get(self->nameservers_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1372,7 +1435,13 @@ nm_l3_config_data_clear_nameservers(NML3ConfigData *self, int addr_family) const in_addr_t * nm_l3_config_data_get_wins(const NML3ConfigData *self, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(out_len); + + if (!self) { + *out_len = 0; + return NULL; + } return _garray_inaddr_get(self->wins, out_len); } @@ -1420,10 +1489,15 @@ nm_l3_config_data_set_nis_domain(NML3ConfigData *self, const char *nis_domain) const char *const * nm_l3_config_data_get_domains(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return nm_strv_ptrarray_get_unsafe(self->domains_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1439,10 +1513,15 @@ nm_l3_config_data_add_domain(NML3ConfigData *self, int addr_family, const char * const char *const * nm_l3_config_data_get_searches(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return nm_strv_ptrarray_get_unsafe(self->searches_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1492,10 +1571,15 @@ nm_l3_config_data_add_dns_option(NML3ConfigData *self, int addr_family, const ch const char *const * nm_l3_config_data_get_dns_options(const NML3ConfigData *self, int addr_family, guint *out_len) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); nm_assert_addr_family(addr_family); nm_assert(out_len); + if (!self) { + *out_len = 0; + return NULL; + } + return nm_strv_ptrarray_get_unsafe(self->dns_options_x[NM_IS_IPv4(addr_family)], out_len); } @@ -1621,6 +1705,29 @@ nm_l3_config_data_set_route_table_sync(NML3ConfigData * self, return TRUE; } +NMTernary +nm_l3_config_data_get_never_default(const NML3ConfigData *self, int addr_family) +{ + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); + + return NM_TERNARY_FROM_OPTION_BOOL(self->never_default_x[NM_IS_IPv4(addr_family)]); +} + +gboolean +nm_l3_config_data_set_never_default(NML3ConfigData *self, int addr_family, NMTernary never_default) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMOptionBool v = NM_TERNARY_TO_OPTION_BOOL(never_default); + + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + + if (self->never_default_x[IS_IPv4] == v) + return FALSE; + + self->never_default_x[IS_IPv4] = v; + return TRUE; +} + NMTernary nm_l3_config_data_get_metered(const NML3ConfigData *self) { @@ -1682,22 +1789,13 @@ nm_l3_config_data_set_ip6_mtu(NML3ConfigData *self, guint32 ip6_mtu) return TRUE; } -gboolean -nm_l3_config_data_set_source(NML3ConfigData *self, NMIPConfigSource source) -{ - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - - if (self->source == source) - return FALSE; - - self->source = source; - return TRUE; -} - NMSettingIP6ConfigPrivacy nm_l3_config_data_get_ip6_privacy(const NML3ConfigData *self) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(!self || _NM_IS_L3_CONFIG_DATA(self, TRUE)); + + if (!self) + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; return self->ip6_privacy; } @@ -1799,7 +1897,7 @@ nm_l3_config_data_set_proxy_pac_script(NML3ConfigData *self, const char *value) gboolean nm_l3_config_data_get_ndisc_hop_limit(const NML3ConfigData *self, int *out_val) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); if (!self->ndisc_hop_limit_set) { NM_SET_OUT(out_val, 0); @@ -1822,7 +1920,7 @@ nm_l3_config_data_set_ndisc_hop_limit(NML3ConfigData *self, int val) gboolean nm_l3_config_data_get_ndisc_reachable_time_msec(const NML3ConfigData *self, guint32 *out_val) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); if (!self->ndisc_reachable_time_msec_set) { NM_SET_OUT(out_val, 0); @@ -1845,7 +1943,7 @@ nm_l3_config_data_set_ndisc_reachable_time_msec(NML3ConfigData *self, guint32 va gboolean nm_l3_config_data_get_ndisc_retrans_timer_msec(const NML3ConfigData *self, guint32 *out_val) { - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); if (!self->ndisc_retrans_timer_msec_set) { NM_SET_OUT(out_val, 0); @@ -1922,14 +2020,26 @@ nm_l3_config_data_set_dhcp_lease_from_options(NML3ConfigData *self, /*****************************************************************************/ static int -_dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObjectType obj_type) +_dedup_multi_index_cmp(const NML3ConfigData *a, + const NML3ConfigData *b, + NMPObjectType obj_type, + gboolean ignore_ifindex) { const NMDedupMultiHeadEntry *h_a = nm_l3_config_data_lookup_objs(a, obj_type); const NMDedupMultiHeadEntry *h_b = nm_l3_config_data_lookup_objs(b, obj_type); NMDedupMultiIter iter_a; NMDedupMultiIter iter_b; + /* We handle ignore_index via NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX flag, which is + * only implemented for certain types. */ + nm_assert(NM_IN_SET(obj_type, + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE)); + NM_CMP_SELF(h_a, h_b); + NM_CMP_DIRECT(h_a->len, h_b->len); nm_assert(h_a->len > 0); @@ -1952,7 +2062,10 @@ _dedup_multi_index_cmp(const NML3ConfigData *a, const NML3ConfigData *b, NMPObje have_b = nm_platform_dedup_multi_iter_next_obj(&iter_b, &obj_b, obj_type); nm_assert(have_b); - NM_CMP_RETURN(nmp_object_cmp(obj_a, obj_b)); + NM_CMP_RETURN(nmp_object_cmp_full(obj_a, + obj_b, + ignore_ifindex ? NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX + : NMP_OBJECT_CMP_FLAGS_NONE)); } } @@ -1961,25 +2074,30 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, const NML3ConfigData *b, NML3ConfigCmpFlags cmp_flags) { - int IS_IPv4; + int IS_IPv4; + gboolean ignore_ifindex; NM_CMP_SELF(a, b); - if (!NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX)) + ignore_ifindex = NM_FLAGS_HAS(cmp_flags, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX); + + if (!ignore_ifindex) NM_CMP_DIRECT(a->ifindex, b->ifindex); NM_CMP_DIRECT(a->flags, b->flags); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ADDRESS)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ADDRESS)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ROUTE)); - NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ROUTE)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ADDRESS, ignore_ifindex)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ADDRESS, ignore_ifindex)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP4_ROUTE, ignore_ifindex)); + NM_CMP_RETURN(_dedup_multi_index_cmp(a, b, NMP_OBJECT_TYPE_IP6_ROUTE, ignore_ifindex)); for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; - NM_CMP_RETURN( - nmp_object_cmp(a->best_default_route_x[IS_IPv4], b->best_default_route_x[IS_IPv4])); + NM_CMP_RETURN(nmp_object_cmp_full(a->best_default_route_x[IS_IPv4], + b->best_default_route_x[IS_IPv4], + ignore_ifindex ? NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX + : NMP_OBJECT_CMP_FLAGS_NONE)); NM_CMP_RETURN( _garray_inaddr_cmp(a->nameservers_x[IS_IPv4], b->nameservers_x[IS_IPv4], addr_family)); @@ -1999,6 +2117,7 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, NM_CMP_DIRECT(a->dns_priority_x[IS_IPv4], b->dns_priority_x[IS_IPv4]); NM_CMP_DIRECT(a->route_table_sync_x[IS_IPv4], b->route_table_sync_x[IS_IPv4]); + NM_CMP_DIRECT(a->never_default_x[IS_IPv4], b->never_default_x[IS_IPv4]); } NM_CMP_RETURN(_garray_inaddr_cmp(a->wins, b->wins, AF_INET)); @@ -2066,8 +2185,8 @@ _data_get_direct_route_for_host(const NML3ConfigData *self, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { const NMPlatformIPXRoute *item = NMP_OBJECT_CAST_IPX_ROUTE(item_obj); - if (nm_ip_addr_is_null(addr_family, - nm_platform_ip_route_get_gateway(addr_family, &item->rx))) + if (!nm_ip_addr_is_null(addr_family, + nm_platform_ip_route_get_gateway(addr_family, &item->rx))) continue; if (best_route && best_route->rx.plen > item->rx.plen) @@ -2114,7 +2233,7 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea const NMPObject * my_addr_obj; NMDedupMultiIter iter; - nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); /* For IPv6 slaac, we explicitly add the device-routes (onlink). * As we don't do that for IPv4 and manual IPv6 addresses. Add them here @@ -2125,9 +2244,6 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea in_addr_t network_4; NMPlatformIPXRoute rx; - if (my_addr->external) - continue; - nm_assert(my_addr->plen <= 32); if (my_addr->plen == 0) continue; @@ -2176,120 +2292,137 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea /*****************************************************************************/ void -nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, - int addr_family, - guint32 route_table, - guint32 route_metric, - gboolean is_vrf) +nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_family) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); gs_unref_ptrarray GPtrArray *extra_onlink_routes = NULL; - const NMPObject * my_addr_obj; - const NMPObject * my_route_obj; - NMPlatformIPXRoute rx; + const NMPObject * obj_src; NMDedupMultiIter iter; - in_addr_t network_4 = 0; + int IS_IPv4; guint i; + if (addr_family == AF_UNSPEC) { + nm_l3_config_data_add_dependent_onlink_routes(self, AF_INET); + nm_l3_config_data_add_dependent_onlink_routes(self, AF_INET6); + return; + } + + IS_IPv4 = NM_IS_IPv4(addr_family); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); - nm_assert_addr_family(addr_family); /* For IPv6 slaac, we explicitly add the device-routes (onlink). * As we don't do that for IPv4 and manual IPv6 addresses. Add them here * as dependent routes. */ - if (!IS_IPv4) { - /* Pre-generate multicast route */ - rx.r6 = (NMPlatformIP6Route){ - .ifindex = self->ifindex, - .network.s6_addr[0] = 0xffu, - .plen = 8, - .table_coerced = nm_platform_route_table_coerce(RT_TABLE_LOCAL), - .type_coerced = nm_platform_route_type_coerce(RTN_UNICAST), - .metric = 256, - }; - nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); - } + nm_l3_config_data_iter_obj_for_each (&iter, self, &obj_src, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { + const NMPlatformIPXRoute *route_src = NMP_OBJECT_CAST_IPX_ROUTE(obj_src); + NMPObject * new_route; + NMPlatformIPXRoute * new_r; + const NMIPAddr * p_gateway; - nm_l3_config_data_iter_obj_for_each (&iter, - self, - &my_addr_obj, - NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { - const NMPlatformIPXAddress *const my_addr = NMP_OBJECT_CAST_IPX_ADDRESS(my_addr_obj); + p_gateway = nm_platform_ip_route_get_gateway(addr_family, &route_src->rx); + + if (nm_ip_addr_is_null(addr_family, p_gateway)) + continue; - if (my_addr->ax.external) + if (_data_get_direct_route_for_host( + self, + addr_family, + p_gateway, + nm_platform_route_table_uncoerce(route_src->rx.table_coerced, TRUE))) continue; + new_route = nmp_object_clone(obj_src, FALSE); + new_r = NMP_OBJECT_CAST_IPX_ROUTE(new_route); if (IS_IPv4) { - nm_assert(my_addr->a4.plen <= 32); - if (my_addr->a4.plen == 0) - continue; + new_r->r4.network = route_src->r4.gateway; + new_r->r4.plen = 32; + new_r->r4.gateway = 0; + } else { + new_r->r6.network = route_src->r6.gateway; + new_r->r6.plen = 128; + new_r->r6.gateway = in6addr_any; } - if (IS_IPv4) { - rx.r4 = (NMPlatformIP4Route){ - .ifindex = self->ifindex, - .rt_source = NM_IP_CONFIG_SOURCE_KERNEL, - .network = my_addr->a4.address, - .plen = 32, - .pref_src = my_addr->a4.address, - .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), - .scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST), - .table_coerced = - nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL), - }; - } else { - rx.r6 = (NMPlatformIP6Route){ - .ifindex = self->ifindex, - .network = my_addr->a6.address, - .plen = 128, - .type_coerced = nm_platform_route_type_coerce(RTN_LOCAL), - .metric = 0, - .table_coerced = - nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL), - }; + /* we cannot add the route right away, because that invalidates the iteration. */ + if (!extra_onlink_routes) + extra_onlink_routes = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + g_ptr_array_add(extra_onlink_routes, new_route); + } + if (extra_onlink_routes) { + for (i = 0; i < extra_onlink_routes->len; i++) { + nm_l3_config_data_add_route_full(self, + addr_family, + extra_onlink_routes->pdata[i], + NULL, + NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, + NULL, + NULL); } - nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); + } +} - if (my_addr->ax.plen == 0) +void +nm_l3_config_data_add_dependent_device_routes(NML3ConfigData * self, + int addr_family, + guint32 route_table, + guint32 route_metric, + const NML3ConfigData *source) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMPObject * obj_src; + NMPlatformIPXRoute rx; + NMDedupMultiIter iter; + + nm_assert_addr_family(addr_family); + nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE)); + nm_assert(_NM_IS_L3_CONFIG_DATA(source, TRUE)); + nm_assert(self != source); + + /* For IPv6 slaac, we explicitly add the device-routes (onlink) and track them + * as regular routes in NML3ConfigData. + * + * For IPv4 and for manual IPv6 addresses we don't do that. Instead, add those + * routes automatically afterwards. + * + * As route-table/metric is associated with the source l3cd, we need to process + * all source l3cds separately. */ + + nm_l3_config_data_iter_obj_for_each (&iter, + source, + &obj_src, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { + const NMPlatformIPXAddress *const addr_src = NMP_OBJECT_CAST_IPX_ADDRESS(obj_src); + const NMPlatformIPXAddress * addr_dst; + + addr_dst = NMP_OBJECT_CAST_IPX_ADDRESS( + nm_dedup_multi_entry_get_obj(nm_l3_config_data_lookup_obj(self, obj_src))); + if (!addr_dst) continue; if (IS_IPv4) { - network_4 = - nm_utils_ip4_address_clear_host_address(my_addr->a4.peer_address, my_addr->a4.plen); + NMPlatformIPXRoute r_stack; + const NMPlatformIPRoute *r; - if (nm_utils_ip4_address_is_zeronet(network_4)) { - /* Kernel doesn't add device-routes for destinations that - * start with 0.x.y.z. Skip them. */ + if (addr_dst->a4.a_acd_not_ready) continue; - } - if (my_addr->a4.plen == 32 && my_addr->a4.address == my_addr->a4.peer_address) { - /* Kernel doesn't add device-routes for /32 addresses unless - * they have a peer. */ - continue; - } + r = (NMPlatformIPRoute *) nm_platform_ip4_address_generate_device_route(&addr_src->a4, + self->ifindex, + route_table, + route_metric, + &r_stack.r4); + if (r) + nm_l3_config_data_add_route(self, addr_family, NULL, r); } else { - if (NM_FLAGS_HAS(my_addr->a6.n_ifa_flags, IFA_F_NOPREFIXROUTE)) + const gboolean has_peer = !IN6_IS_ADDR_UNSPECIFIED(&addr_src->a6.peer_address); + int routes_i; + + if (addr_src->ax.plen == 0) continue; - } - if (IS_IPv4) { - rx.r4 = (NMPlatformIP4Route){ - .ifindex = self->ifindex, - .rt_source = NM_IP_CONFIG_SOURCE_KERNEL, - .network = network_4, - .plen = my_addr->a4.plen, - .pref_src = my_addr->a4.address, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, - .scope_inv = nm_platform_route_scope_inv(NM_RT_SCOPE_LINK), - }; - nm_platform_ip_route_normalize(addr_family, &rx.rx); - nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); - } else { - const gboolean has_peer = !IN6_IS_ADDR_UNSPECIFIED(&my_addr->a6.peer_address); - int routes_i; + if (NM_FLAGS_HAS(addr_src->a6.n_ifa_flags, IFA_F_NOPREFIXROUTE)) + continue; /* If we have an IPv6 peer, we add two /128 routes * (unless, both addresses are identical). */ @@ -2299,20 +2432,20 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, guint8 plen; if (routes_i == 1 && has_peer - && IN6_ARE_ADDR_EQUAL(&my_addr->a6.address, &my_addr->a6.peer_address)) + && IN6_ARE_ADDR_EQUAL(&addr_src->a6.address, &addr_src->a6.peer_address)) break; if (has_peer) { if (routes_i == 0) - a6 = &my_addr->a6.address; + a6 = &addr_src->a6.address; else - a6 = &my_addr->a6.peer_address; + a6 = &addr_src->a6.peer_address; plen = 128; } else { a6 = nm_utils_ip6_address_clear_host_address(&a6_stack, - &my_addr->a6.address, - my_addr->a6.plen); - plen = my_addr->a6.plen; + &addr_src->a6.address, + addr_src->a6.plen); + plen = addr_src->a6.plen; } rx.r6 = (NMPlatformIP6Route){ @@ -2328,73 +2461,16 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, } } } - - nm_l3_config_data_iter_obj_for_each (&iter, - self, - &my_route_obj, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { - const NMPlatformIPXRoute *my_route = NMP_OBJECT_CAST_IPX_ROUTE(my_route_obj); - NMPObject * new_route; - NMPlatformIPXRoute * new_r; - const NMIPAddr * p_gateway; - - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route) - || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rx.rt_source)) - continue; - - p_gateway = nm_platform_ip_route_get_gateway(addr_family, &my_route->rx); - - if (nm_ip_addr_is_null(addr_family, p_gateway)) - continue; - - if (_data_get_direct_route_for_host( - self, - addr_family, - p_gateway, - nm_platform_route_table_uncoerce(my_route->rx.table_coerced, TRUE))) - continue; - - new_route = nmp_object_clone(my_route_obj, FALSE); - new_r = NMP_OBJECT_CAST_IPX_ROUTE(new_route); - if (IS_IPv4) { - new_r->r4.network = my_route->r4.gateway; - new_r->r4.plen = 32; - new_r->r4.gateway = 0; - } else { - new_r->r6.network = my_route->r6.gateway; - new_r->r6.plen = 128; - new_r->r6.gateway = in6addr_any; - } - - /* we cannot add the route right away, because that invalidates the iteration. */ - if (!extra_onlink_routes) - extra_onlink_routes = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); - g_ptr_array_add(extra_onlink_routes, new_route); - } - if (extra_onlink_routes) { - for (i = 0; i < extra_onlink_routes->len; i++) { - nm_l3_config_data_add_route_full(self, - addr_family, - extra_onlink_routes->pdata[i], - NULL, - NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, - NULL, - NULL); - } - } } /*****************************************************************************/ static void -_init_from_connection_ip(NML3ConfigData *self, - int addr_family, - NMConnection * connection, - guint32 route_table, - guint32 route_metric) +_init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *connection) { const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; + gboolean never_default; guint naddresses; guint nroutes; guint nnameservers; @@ -2415,25 +2491,28 @@ _init_from_connection_ip(NML3ConfigData *self, if (!s_ip) return; - if (!nm_setting_ip_config_get_never_default(s_ip) - && (gateway_str = nm_setting_ip_config_get_gateway(s_ip)) + never_default = nm_setting_ip_config_get_never_default(s_ip); + + nm_l3_config_data_set_never_default(self, addr_family, !!never_default); + + if (!never_default && (gateway_str = nm_setting_ip_config_get_gateway(s_ip)) && inet_pton(addr_family, gateway_str, &gateway_bin) == 1 && !nm_ip_addr_is_null(addr_family, &gateway_bin)) { NMPlatformIPXRoute r; if (IS_IPv4) { r.r4 = (NMPlatformIP4Route){ - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .gateway = gateway_bin.addr4, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .gateway = gateway_bin.addr4, + .table_any = TRUE, + .metric_any = TRUE, }; } else { r.r6 = (NMPlatformIP6Route){ - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .gateway = gateway_bin.addr6, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = route_metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .gateway = gateway_bin.addr6, + .table_any = TRUE, + .metric_any = TRUE, }; } @@ -2488,6 +2567,7 @@ _init_from_connection_ip(NML3ConfigData *self, NMIPAddr next_hop_bin; gint64 metric64; guint32 metric; + gboolean metric_any; guint plen; nm_assert(nm_ip_route_get_family(s_route) == addr_family); @@ -2496,11 +2576,14 @@ _init_from_connection_ip(NML3ConfigData *self, nm_ip_route_get_next_hop_binary(s_route, &next_hop_bin); metric64 = nm_ip_route_get_metric(s_route); - if (metric64 < 0) - metric = route_metric; - else - metric = metric64; - metric = nm_utils_ip_route_metric_normalize(addr_family, metric); + if (metric64 < 0) { + metric_any = TRUE; + metric = 0; + } else { + metric_any = FALSE; + metric = metric64; + metric = nm_utils_ip_route_metric_normalize(addr_family, metric); + } plen = nm_ip_route_get_prefix(s_route); @@ -2508,25 +2591,27 @@ _init_from_connection_ip(NML3ConfigData *self, if (IS_IPv4) { r.r4 = (NMPlatformIP4Route){ - .network = network_bin.addr4, - .plen = nm_ip_route_get_prefix(s_route), - .gateway = next_hop_bin.addr4, - .metric = metric, - .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = network_bin.addr4, + .plen = nm_ip_route_get_prefix(s_route), + .gateway = next_hop_bin.addr4, + .metric_any = metric_any, + .metric = metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, }; nm_assert(r.r4.plen <= 32); } else { r.r6 = (NMPlatformIP6Route){ - .network = network_bin.addr6, - .plen = nm_ip_route_get_prefix(s_route), - .gateway = next_hop_bin.addr6, - .metric = metric, - .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = network_bin.addr6, + .plen = nm_ip_route_get_prefix(s_route), + .gateway = next_hop_bin.addr6, + .metric_any = metric_any, + .metric = metric, + .rt_source = NM_IP_CONFIG_SOURCE_USER, }; nm_assert(r.r6.plen <= 128); } - nm_utils_ip_route_attribute_to_platform(addr_family, s_route, &r.rx, route_table); + nm_utils_ip_route_attribute_to_platform(addr_family, s_route, &r.rx, -1); nm_l3_config_data_add_route(self, addr_family, NULL, &r.rx); } @@ -2550,34 +2635,36 @@ _init_from_connection_ip(NML3ConfigData *self, } idx = 0; - while ((idx = nm_setting_ip_config_next_valid_dns_option(s_ip, i)) >= 0) { + while ((idx = nm_setting_ip_config_next_valid_dns_option(s_ip, idx)) >= 0) { nm_l3_config_data_add_dns_option(self, addr_family, - nm_setting_ip_config_get_dns_option(s_ip, i)); + nm_setting_ip_config_get_dns_option(s_ip, idx)); idx++; } nm_l3_config_data_set_dns_priority(self, addr_family, nm_setting_ip_config_get_dns_priority(s_ip)); + + if (!IS_IPv4) { + nm_l3_config_data_set_ip6_privacy( + self, + nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip))); + } } NML3ConfigData * nm_l3_config_data_new_from_connection(NMDedupMultiIndex *multi_idx, int ifindex, - NMConnection * connection, - guint32 route_table_4, - guint32 route_table_6, - guint32 route_metric_4, - guint32 route_metric_6) + NMConnection * connection) { NML3ConfigData *self; NMSettingProxy *s_proxy; - self = nm_l3_config_data_new(multi_idx, ifindex); + self = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_USER); - _init_from_connection_ip(self, AF_INET, connection, route_table_4, route_metric_4); - _init_from_connection_ip(self, AF_INET6, connection, route_table_6, route_metric_6); + _init_from_connection_ip(self, AF_INET, connection); + _init_from_connection_ip(self, AF_INET6, connection); s_proxy = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PROXY); if (s_proxy) { @@ -2693,7 +2780,7 @@ nm_l3_config_data_new_from_platform(NMDedupMultiIndex * multi_idx, if (nm_platform_link_get_master(platform, ifindex) > 0) return NULL; - self = nm_l3_config_data_new(multi_idx, ifindex); + self = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_KERNEL); _init_from_platform(self, AF_INET, platform, ipv6_privacy_rfc4941); _init_from_platform(self, AF_INET6, platform, ipv6_privacy_rfc4941); @@ -2710,13 +2797,16 @@ nm_l3_config_data_merge(NML3ConfigData * self, const guint32 * default_route_table_x /* length 2, for IS_IPv4 */, const guint32 * default_route_metric_x /* length 2, for IS_IPv4 */, const guint32 * default_route_penalty_x /* length 2, for IS_IPv4 */, - NML3ConfigMergeHookAddObj hook_add_addr, + const int * default_dns_priority_x /* length 2, for IS_IPv4 */, + NML3ConfigMergeHookAddObj hook_add_obj, gpointer hook_user_data) { static const guint32 x_default_route_table_x[2] = {RT_TABLE_MAIN, RT_TABLE_MAIN}; static const guint32 x_default_route_metric_x[2] = {NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4}; static const guint32 x_default_route_penalty_x[2] = {0, 0}; + static const int x_default_dns_priority_x[2] = {NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_DNS_PRIORITY_DEFAULT_NORMAL}; NMDedupMultiIter iter; const NMPObject * obj; int IS_IPv4; @@ -2730,6 +2820,8 @@ nm_l3_config_data_merge(NML3ConfigData * self, default_route_metric_x = x_default_route_metric_x; if (!default_route_penalty_x) default_route_penalty_x = x_default_route_penalty_x; + if (!default_dns_priority_x) + default_dns_priority_x = x_default_dns_priority_x; nm_assert(default_route_table_x[0] != 0); nm_assert(default_route_table_x[1] != 0); @@ -2747,51 +2839,100 @@ nm_l3_config_data_merge(NML3ConfigData * self, src, &obj, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { - NMPlatformIPXAddress addr_stack; - const NMPlatformIPAddress *addr = NULL; - NMTernary ip4acd_not_ready = NM_TERNARY_DEFAULT; + const NMPlatformIPAddress *a_src = NMP_OBJECT_CAST_IP_ADDRESS(obj); + NMPlatformIPXAddress a; + NML3ConfigMergeHookResult hook_result = { + .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, + .assume_config_once = NM_OPTION_BOOL_DEFAULT, + }; + +#define _ensure_a() \ + G_STMT_START \ + { \ + if (a_src != &a.ax) { \ + if (IS_IPv4) \ + a.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS(obj); \ + else \ + a.a6 = *NMP_OBJECT_CAST_IP6_ADDRESS(obj); \ + a_src = &a.ax; \ + } \ + } \ + G_STMT_END - if (hook_add_addr && !hook_add_addr(src, obj, &ip4acd_not_ready, hook_user_data)) + if (hook_add_obj && !hook_add_obj(src, obj, &hook_result, hook_user_data)) continue; - if (IS_IPv4 && ip4acd_not_ready != NM_TERNARY_DEFAULT - && (!!ip4acd_not_ready) != NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready) { - addr_stack.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS(obj); - addr_stack.a4.ip4acd_not_ready = (!!ip4acd_not_ready); - addr = &addr_stack.ax; - } else - nm_assert(IS_IPv4 || ip4acd_not_ready == NM_TERNARY_DEFAULT); + nm_assert(IS_IPv4 || hook_result.ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT); + + if (a_src->ifindex != self->ifindex) { + _ensure_a(); + a.ax.ifindex = self->ifindex; + } + + if (hook_result.ip4acd_not_ready != NM_OPTION_BOOL_DEFAULT && IS_IPv4 + && (!!hook_result.ip4acd_not_ready) + != ((const NMPlatformIP4Address *) a_src)->a_acd_not_ready) { + _ensure_a(); + a.a4.a_acd_not_ready = (!!hook_result.ip4acd_not_ready); + } + + if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT + && (!!hook_result.assume_config_once) != a_src->a_assume_config_once) { + _ensure_a(); + a.ax.a_assume_config_once = (!!hook_result.assume_config_once); + } nm_l3_config_data_add_address_full(self, addr_family, - addr ? NULL : obj, - addr, + a_src == &a.ax ? NULL : obj, + a_src == &a.ax ? a_src : NULL, NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, NULL); } +#undef _ensure_a + if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES)) { nm_l3_config_data_iter_obj_for_each (&iter, src, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { - const NMPlatformIPRoute *r_src = NMP_OBJECT_CAST_IP_ROUTE(obj); - NMPlatformIPXRoute r; + const NMPlatformIPRoute * r_src = NMP_OBJECT_CAST_IP_ROUTE(obj); + NMPlatformIPXRoute r; + NML3ConfigMergeHookResult hook_result = { + .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, + .assume_config_once = NM_OPTION_BOOL_DEFAULT, + }; #define _ensure_r() \ G_STMT_START \ { \ if (r_src != &r.rx) { \ - r_src = &r.rx; \ if (IS_IPv4) \ r.r4 = *NMP_OBJECT_CAST_IP4_ROUTE(obj); \ else \ r.r6 = *NMP_OBJECT_CAST_IP6_ROUTE(obj); \ - r.rx.ifindex = self->ifindex; \ + r_src = &r.rx; \ } \ } \ G_STMT_END + if (hook_add_obj && !hook_add_obj(src, obj, &hook_result, hook_user_data)) + continue; + + nm_assert(hook_result.ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT); + + if (r_src->ifindex != self->ifindex) { + _ensure_r(); + r.rx.ifindex = self->ifindex; + } + + if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT + && (!!hook_result.assume_config_once) != r_src->r_assume_config_once) { + _ensure_r(); + r.rx.r_assume_config_once = (!!hook_result.assume_config_once); + } + if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) { if (r_src->table_any) { _ensure_r(); @@ -2848,12 +2989,20 @@ nm_l3_config_data_merge(NML3ConfigData * self, if (!NM_FLAGS_ANY(self->flags, has_dns_priority_flag) && NM_FLAGS_ANY(src->flags, has_dns_priority_flag)) { - self->dns_priority_x[IS_IPv4] = src->dns_priority_x[IS_IPv4]; + int p = src->dns_priority_x[IS_IPv4]; + + if (p == 0 && !NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) + p = default_dns_priority_x[IS_IPv4]; + + self->dns_priority_x[IS_IPv4] = p; self->flags |= has_dns_priority_flag; } if (self->route_table_sync_x[IS_IPv4] == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE) self->route_table_sync_x[IS_IPv4] = src->route_table_sync_x[IS_IPv4]; + + if (self->never_default_x[IS_IPv4] == NM_OPTION_BOOL_DEFAULT) + self->never_default_x[IS_IPv4] = src->never_default_x[IS_IPv4]; } if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS)) { @@ -2933,7 +3082,7 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) if (ifindex <= 0) ifindex = src->ifindex; - self = nm_l3_config_data_new(src->multi_idx, ifindex); + self = nm_l3_config_data_new(src->multi_idx, ifindex, src->source); nm_l3_config_data_merge(self, src, NM_L3_CONFIG_MERGE_FLAGS_CLONE, @@ -2941,9 +3090,15 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex) NULL, NULL, NULL, + NULL, NULL); - nm_assert(nm_l3_config_data_cmp_full(src, self, NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX) == 0); + nm_assert(nm_l3_config_data_cmp_full(src, + self, + src->ifindex != ifindex + ? NM_L3_CONFIG_CMP_FLAGS_IGNORE_IFINDEX + : NM_L3_CONFIG_CMP_FLAGS_NONE) + == 0); nm_assert(nm_l3_config_data_get_ifindex(self) == ifindex); return self; diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index 9bed47e0..1ad23c32 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -52,15 +52,6 @@ typedef enum { /** * NML3ConfigMergeFlags: * @NM_L3_CONFIG_MERGE_FLAGS_NONE: no flags set - * @NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD: if this merge flag is set, - * the the NML3ConfigData doesn't get merged and it's information won't be - * synced. The only purpose is to run ACD on its IPv4 addresses, but - * regardless whether ACD succeeds/fails, the IP addresses won't be configured. - * The point is to run ACD first (without configuring it), and only - * commit the settings if requested. That can either happen by - * nm_l3cfg_add_config() the same NML3Cfg again (with a different - * tag), or by calling nm_l3cfg_add_config() again with this flag - * cleared (and the same tag). * @NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES: don't merge routes * @NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES: don't merge default routes. * Note that if the respective NML3ConfigData has NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES @@ -71,18 +62,18 @@ typedef enum { */ typedef enum _nm_packed { NM_L3_CONFIG_MERGE_FLAGS_NONE = 0, - NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD = (1LL << 0), - NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES = (1LL << 1), - NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES = (1LL << 2), - NM_L3_CONFIG_MERGE_FLAGS_NO_DNS = (1LL << 3), - NM_L3_CONFIG_MERGE_FLAGS_CLONE = (1LL << 4), + NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES = (1LL << 0), + NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES = (1LL << 1), + NM_L3_CONFIG_MERGE_FLAGS_NO_DNS = (1LL << 2), + NM_L3_CONFIG_MERGE_FLAGS_CLONE = (1LL << 3), } NML3ConfigMergeFlags; /*****************************************************************************/ static inline gboolean NM_IS_L3_CONFIG_DATA(const NML3ConfigData *self); -NML3ConfigData * nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex); +NML3ConfigData * +nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSource source); const NML3ConfigData *nm_l3_config_data_ref(const NML3ConfigData *self); const NML3ConfigData *nm_l3_config_data_ref_and_seal(const NML3ConfigData *self); const NML3ConfigData *nm_l3_config_data_seal(const NML3ConfigData *self); @@ -137,21 +128,22 @@ NML3ConfigData *nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifind NML3ConfigData *nm_l3_config_data_new_from_connection(NMDedupMultiIndex *multi_idx, int ifindex, - NMConnection * connection, - guint32 route_table_4, - guint32 route_table_6, - guint32 route_metric_4, - guint32 route_metric_6); + NMConnection * connection); NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex * multi_idx, int ifindex, NMPlatform * platform, NMSettingIP6ConfigPrivacy ipv6_privacy_rfc4941); -typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData *l3cd, - const NMPObject * obj, - NMTernary * out_ip4acd_not_ready, - gpointer user_data); +typedef struct { + NMOptionBool ip4acd_not_ready; + NMOptionBool assume_config_once; +} NML3ConfigMergeHookResult; + +typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData * l3cd, + const NMPObject * obj, + NML3ConfigMergeHookResult *result, + gpointer user_data); void nm_l3_config_data_merge(NML3ConfigData * self, const NML3ConfigData *src, @@ -159,17 +151,20 @@ void nm_l3_config_data_merge(NML3ConfigData * self, const guint32 *default_route_table_x /* length 2, for IS_IPv4 */, const guint32 *default_route_metric_x /* length 2, for IS_IPv4 */, const guint32 *default_route_penalty_x /* length 2, for IS_IPv4 */, - NML3ConfigMergeHookAddObj hook_add_addr, + const int * default_dns_priority_x /* length 2, for IS_IPv4 */, + NML3ConfigMergeHookAddObj hook_add_obj, gpointer hook_user_data); GPtrArray *nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolean is_vrf); -void nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, - int addr_family, - guint32 route_table, - guint32 route_metric, - gboolean is_vrf); +void nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_family); + +void nm_l3_config_data_add_dependent_device_routes(NML3ConfigData * self, + int addr_family, + guint32 route_table, + guint32 route_metric, + const NML3ConfigData *source); /*****************************************************************************/ @@ -192,7 +187,7 @@ NM_IS_L3_CONFIG_DATA(const NML3ConfigData *self) * * Additionally, also call nm_l3_config_data_get_ifindex(), which does more * checks during nm_assert(). */ - nm_assert(nm_l3_config_data_get_ifindex(self) > 0); + nm_assert(!self || nm_l3_config_data_get_ifindex(self) > 0); return !!self; } @@ -229,6 +224,11 @@ const NMDedupMultiIdxType *nm_l3_config_data_lookup_index(const NML3ConfigData * const NMDedupMultiEntry *nm_l3_config_data_lookup_obj(const NML3ConfigData *self, const NMPObject * obj); +const NMPlatformIP4Address *nm_l3_config_data_lookup_address_4(const NML3ConfigData *self, + in_addr_t addr, + guint8 plen, + in_addr_t peer_addr); + const NMPlatformIP6Address *nm_l3_config_data_lookup_address_6(const NML3ConfigData * self, const struct in6_addr *addr); @@ -363,8 +363,6 @@ nm_l3_config_data_unset_flags(NML3ConfigData *self, NML3ConfigDatFlags flags) /*****************************************************************************/ -gboolean nm_l3_config_data_set_source(NML3ConfigData *self, NMIPConfigSource source); - const NMPObject *nm_l3_config_data_get_first_obj(const NML3ConfigData *self, NMPObjectType obj_type, gboolean (*predicate)(const NMPObject *obj)); @@ -455,6 +453,11 @@ gboolean nm_l3_config_data_set_route_table_sync(NML3ConfigData * self, int addr_family, NMIPRouteTableSyncMode route_table_sync); +NMTernary nm_l3_config_data_get_never_default(const NML3ConfigData *self, int addr_family); + +gboolean +nm_l3_config_data_set_never_default(NML3ConfigData *self, int addr_family, NMTernary never_default); + NMTernary nm_l3_config_data_get_metered(const NML3ConfigData *self); gboolean nm_l3_config_data_set_metered(NML3ConfigData *self, NMTernary metered); @@ -509,6 +512,17 @@ nm_l3_config_data_get_dns_options(const NML3ConfigData *self, int addr_family, g gboolean nm_l3_config_data_get_dns_priority(const NML3ConfigData *self, int addr_family, int *out_prio); +static inline int +nm_l3_config_data_get_dns_priority_or_default(const NML3ConfigData *self, int addr_family) +{ + int v; + + nm_assert_addr_family(addr_family); + if (!self || !nm_l3_config_data_get_dns_priority(self, addr_family, &v)) + return 0; + return v; +} + gboolean nm_l3_config_data_set_dns_priority(NML3ConfigData *self, int addr_family, int dns_priority); diff --git a/src/core/nm-l3-ipv4ll.c b/src/core/nm-l3-ipv4ll.c index 28ceb39e..eb9ceb9b 100644 --- a/src/core/nm-l3-ipv4ll.c +++ b/src/core/nm-l3-ipv4ll.c @@ -317,51 +317,32 @@ _acd_info_is_good(const NML3AcdAddrInfo *acd_info) /*****************************************************************************/ -static NMPlatformIP4Address * -_l3cd_config_plat_init_addr(NMPlatformIP4Address *a, int ifindex, in_addr_t addr) -{ - nm_assert(nm_utils_ip4_address_is_link_local(addr)); - - *a = (NMPlatformIP4Address){ - .ifindex = ifindex, - .address = addr, - .peer_address = addr, - .plen = ADDR_IPV4LL_PREFIX_LEN, - .addr_source = NM_IP_CONFIG_SOURCE_IP4LL, - }; - return a; -} - -static NMPlatformIP4Route * -_l3cd_config_plat_init_route(NMPlatformIP4Route *r, int ifindex) -{ - *r = (NMPlatformIP4Route){ - .ifindex = ifindex, - .network = htonl(0xE0000000u), - .plen = 4, - .rt_source = NM_IP_CONFIG_SOURCE_IP4LL, - .table_any = TRUE, - .metric_any = TRUE, - }; - return r; -} - static const NML3ConfigData * _l3cd_config_create(int ifindex, in_addr_t addr, NMDedupMultiIndex *multi_idx) { nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; - NMPlatformIP4Address a; - NMPlatformIP4Route r; nm_assert(nm_utils_ip4_address_is_link_local(addr)); nm_assert(ifindex > 0); nm_assert(multi_idx); - l3cd = nm_l3_config_data_new(multi_idx, ifindex); - nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_IP4LL); + l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_IP4LL); + + nm_l3_config_data_add_address_4( + l3cd, + NM_PLATFORM_IP4_ADDRESS_INIT(.ifindex = ifindex, + .address = addr, + .peer_address = addr, + .plen = ADDR_IPV4LL_PREFIX_LEN, + .addr_source = NM_IP_CONFIG_SOURCE_IP4LL)); - nm_l3_config_data_add_address_4(l3cd, _l3cd_config_plat_init_addr(&a, ifindex, addr)); - nm_l3_config_data_add_route_4(l3cd, _l3cd_config_plat_init_route(&r, ifindex)); + nm_l3_config_data_add_route_4(l3cd, + NM_PLATFORM_IP4_ROUTE_INIT(.ifindex = ifindex, + .network = htonl(0xE0000000u), + .plen = 4, + .rt_source = NM_IP_CONFIG_SOURCE_IP4LL, + .table_any = TRUE, + .metric_any = TRUE)); return nm_l3_config_data_seal(g_steal_pointer(&l3cd)); } @@ -610,15 +591,19 @@ _l3cd_config_add(NML3IPv4LL *self) NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, 0, 0, + NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_DNS_PRIORITY_DEFAULT_NORMAL, NM_L3_ACD_DEFEND_TYPE_ONCE, self->reg_timeout_msec, - NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD)) + NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD, + NM_L3_CONFIG_MERGE_FLAGS_NONE)) nm_assert_not_reached(); self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_ASSUME, - self->l3cfg_commit_handle); - nm_l3cfg_commit_on_idle_schedule(self->l3cfg); + self->l3cfg_commit_handle, + "ipv4ll"); + nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); } static gboolean @@ -640,7 +625,7 @@ _l3cd_config_remove(NML3IPv4LL *self) nm_assert_not_reached(); nm_l3cfg_commit_type_unregister(self->l3cfg, g_steal_pointer(&self->l3cfg_commit_handle)); - nm_l3cfg_commit_on_idle_schedule(self->l3cfg); + nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); return TRUE; } @@ -1044,7 +1029,7 @@ nm_l3_ipv4ll_unref(NML3IPv4LL *self) nm_assert_not_reached(); nm_l3cfg_commit_type_unregister(self->l3cfg, g_steal_pointer(&self->l3cfg_commit_handle)); - nm_l3cfg_commit_on_idle_schedule(self->l3cfg); + nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); } else nm_assert(!self->l3cfg_commit_handle); diff --git a/src/core/nm-l3-ipv6ll.c b/src/core/nm-l3-ipv6ll.c new file mode 100644 index 00000000..14387321 --- /dev/null +++ b/src/core/nm-l3-ipv6ll.c @@ -0,0 +1,717 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-l3-ipv6ll.h" + +#include + +#include "nm-core-utils.h" + +/*****************************************************************************/ + +/* FIXME(l3cfg): ensure that NML3IPv6LL generates the same stable privacy addresses + * as previous implementation. */ + +/*****************************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE(nm_l3_ipv6ll_state_to_string, + NML3IPv6LLState, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("???"), + NM_UTILS_LOOKUP_STR_ITEM(NM_L3_IPV6LL_STATE_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM(NM_L3_IPV6LL_STATE_DEFUNCT, "defunct"), + NM_UTILS_LOOKUP_STR_ITEM(NM_L3_IPV6LL_STATE_STARTING, "starting"), + NM_UTILS_LOOKUP_STR_ITEM(NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, + "dad-in-progress"), + NM_UTILS_LOOKUP_STR_ITEM(NM_L3_IPV6LL_STATE_READY, "ready"), + NM_UTILS_LOOKUP_STR_ITEM(NM_L3_IPV6LL_STATE_DAD_FAILED, "dad-failed"), ); + +/*****************************************************************************/ + +struct _NML3IPv6LL { + NML3Cfg * l3cfg; + NML3CfgCommitTypeHandle *l3cfg_commit_handle; + NML3IPv6LLNotifyFcn notify_fcn; + gpointer user_data; + GSource * starting_on_idle_source; + GSource * wait_for_addr_source; + GSource * emit_changed_idle_source; + gulong l3cfg_signal_notify_id; + NML3IPv6LLState state; + + /* if we have cur_lladdr set, then this might cache the last + * matching NMPObject from the platform cache. This only serves + * for optimizing the lookup to the platform cache. */ + const NMPlatformIP6Address *cur_lladdr_obj; + + struct in6_addr cur_lladdr; + + /* if we have cur_lladdr and _state_has_lladdr() indicates that + * the LL address is suitable, this is a NML3ConfigData instance + * with the configuration. */ + const NML3ConfigData *l3cd; + + /* "assume" means that we first look whether there is any suitable + * IPv6 address on the device, and in that case, try to use that + * instead of generating a new one. Otherwise, we always try to + * generate a new LL address. */ + bool assume : 1; + + struct { + NMUtilsStableType stable_type; + guint32 dad_counter; + struct { + const char *ifname; + const char *network_id; + } stable_privacy; + struct { + NMUtilsIPv6IfaceId iid; + } token; + } addrgen; +}; + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_IP6 +#define _NMLOG_PREFIX_NAME "ipv6ll" +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + nm_log((level), \ + (_NMLOG_DOMAIN), \ + NULL, \ + NULL, \ + _NMLOG_PREFIX_NAME "[" NM_HASH_OBFUSCATE_PTR_FMT \ + ",ifindex=%d]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_HASH_OBFUSCATE_PTR(self), \ + nm_l3cfg_get_ifindex((self)->l3cfg) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END + +/*****************************************************************************/ + +#define L3CD_TAG(self) (&(self)->notify_fcn) + +/*****************************************************************************/ + +#define _ASSERT(self) \ + G_STMT_START \ + { \ + NML3IPv6LL *const _self = (self); \ + \ + nm_assert(NM_IS_L3_IPV6LL(_self)); \ + } \ + G_STMT_END + +/*****************************************************************************/ + +static void _check(NML3IPv6LL *self); + +/*****************************************************************************/ + +NML3Cfg * +nm_l3_ipv6ll_get_l3cfg(NML3IPv6LL *self) +{ + nm_assert(NM_IS_L3_IPV6LL(self)); + + return self->l3cfg; +} + +int +nm_l3_ipv6ll_get_ifindex(NML3IPv6LL *self) +{ + nm_assert(NM_IS_L3_IPV6LL(self)); + + return nm_l3cfg_get_ifindex(self->l3cfg); +} + +NMPlatform * +nm_l3_ipv6ll_get_platform(NML3IPv6LL *self) +{ + nm_assert(NM_IS_L3_IPV6LL(self)); + + return nm_l3cfg_get_platform(self->l3cfg); +} + +/*****************************************************************************/ + +static gboolean +_state_has_lladdr(NML3IPv6LLState state) +{ + return NM_IN_SET(state, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, NM_L3_IPV6LL_STATE_READY); +} + +NML3IPv6LLState +nm_l3_ipv6ll_get_state(NML3IPv6LL *self, const struct in6_addr **out_lladdr) +{ + nm_assert(NM_IS_L3_IPV6LL(self)); + + NM_SET_OUT(out_lladdr, _state_has_lladdr(self->state) ? &self->cur_lladdr : NULL); + return self->state; +} + +static const NML3ConfigData * +_l3cd_config_create(int ifindex, const struct in6_addr *lladdr, NMDedupMultiIndex *multi_idx) +{ + NML3ConfigData *l3cd; + + nm_assert(ifindex > 0); + nm_assert(lladdr); + nm_assert(IN6_IS_ADDR_LINKLOCAL(lladdr)); + + l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_IP6LL); + + nm_l3_config_data_add_address_6( + l3cd, + NM_PLATFORM_IP6_ADDRESS_INIT(.address = *lladdr, + .plen = 64, + .addr_source = NM_IP_CONFIG_SOURCE_IP6LL)); + + nm_l3_config_data_add_route_6( + l3cd, + NM_PLATFORM_IP6_ROUTE_INIT(.network.s6_addr16[0] = htons(0xfe80u), + .plen = 64, + .metric_any = TRUE, + .table_any = TRUE, + .rt_source = NM_IP_CONFIG_SOURCE_IP6LL)); + + return nm_l3_config_data_seal(l3cd); +} + +const NML3ConfigData * +nm_l3_ipv6ll_get_l3cd(NML3IPv6LL *self) +{ + nm_assert(NM_IS_L3_IPV6LL(self)); + + if (!_state_has_lladdr(self->state)) { + nm_assert(!self->l3cd); + return NULL; + } + + if (!self->l3cd) { + self->l3cd = _l3cd_config_create(nm_l3_ipv6ll_get_ifindex(self), + &self->cur_lladdr, + nm_l3cfg_get_multi_idx(self->l3cfg)); + } + + return self->l3cd; +} + +/*****************************************************************************/ + +static gboolean +_emit_changed_on_idle_cb(gpointer user_data) +{ + NML3IPv6LL * self = user_data; + const struct in6_addr *lladdr; + NML3IPv6LLState state; + char sbuf[INET6_ADDRSTRLEN]; + + nm_clear_g_source_inst(&self->emit_changed_idle_source); + + state = nm_l3_ipv6ll_get_state(self, &lladdr); + + _LOGT("emit changed signal (state=%s%s%s)", + nm_l3_ipv6ll_state_to_string(state), + lladdr ? ", " : "", + lladdr ? _nm_utils_inet6_ntop(lladdr, sbuf) : ""); + + self->notify_fcn(self, state, lladdr, self->user_data); + + return G_SOURCE_CONTINUE; +} + +/*****************************************************************************/ + +static gboolean +_generate_new_address(NML3IPv6LL *self, struct in6_addr *out_lladdr) +{ + struct in6_addr lladdr; + + memset(&lladdr, 0, sizeof(struct in6_addr)); + lladdr.s6_addr16[0] = htons(0xfe80u); + + if (self->addrgen.stable_type == NM_UTILS_STABLE_TYPE_NONE) { + if (self->addrgen.dad_counter > 0) + return FALSE; + self->addrgen.dad_counter++; + nm_utils_ipv6_addr_set_interface_identifier(&lladdr, &self->addrgen.token.iid); + } else { + /* RFC7217 says we MUST limit the number of retries, and it SHOULD try + * at least IDGEN_RETRIES times (that is, 3 times). + * + * 3 times seems really low. Instead, let's try 6 times. */ + G_STATIC_ASSERT(NM_STABLE_PRIVACY_RFC7217_IDGEN_RETRIES == 3); + if (self->addrgen.dad_counter >= NM_STABLE_PRIVACY_RFC7217_IDGEN_RETRIES + 3) + return FALSE; + + nm_utils_ipv6_addr_set_stable_privacy(self->addrgen.stable_type, + &lladdr, + self->addrgen.stable_privacy.ifname, + self->addrgen.stable_privacy.network_id, + self->addrgen.dad_counter++); + } + + *out_lladdr = lladdr; + return TRUE; +} + +/*****************************************************************************/ + +static gboolean +_pladdr_is_ll_failed(const NMPlatformIP6Address *addr) +{ + nm_assert(addr); + nm_assert(IN6_IS_ADDR_LINKLOCAL(&addr->address)); + + return NM_FLAGS_ANY(addr->n_ifa_flags, IFA_F_DADFAILED | IFA_F_DEPRECATED); +} + +static gboolean +_pladdr_is_ll_tentative(const NMPlatformIP6Address *addr) +{ + nm_assert(addr); + nm_assert(IN6_IS_ADDR_LINKLOCAL(&addr->address)); + nm_assert(!_pladdr_is_ll_failed(addr)); + + return NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TENTATIVE) + && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_OPTIMISTIC); +} + +static const NMPlatformIP6Address * +_pladdr_find_ll(NML3IPv6LL *self, gboolean *out_cur_addr_failed) +{ + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPlatformIP6Address *pladdr1 = NULL; + const NMPObject * obj; + const NMPlatformIP6Address *pladdr_ready = NULL; + const NMPlatformIP6Address *pladdr_tentative = NULL; + gboolean cur_addr_check = TRUE; + gboolean cur_addr_failed = FALSE; + gboolean pladdr1_looked_up = FALSE; + + nm_assert(!self->cur_lladdr_obj + || IN6_ARE_ADDR_EQUAL(&self->cur_lladdr, &self->cur_lladdr_obj->address)); + + *out_cur_addr_failed = FALSE; + + if (self->state == NM_L3_IPV6LL_STATE_READY && self->cur_lladdr_obj) { + nm_assert(!_pladdr_is_ll_tentative(self->cur_lladdr_obj)); + pladdr1 = NMP_OBJECT_CAST_IP6_ADDRESS( + nm_platform_lookup_obj(nm_l3_ipv6ll_get_platform(self), + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + NMP_OBJECT_UP_CAST(self->cur_lladdr_obj))); + if (self->cur_lladdr_obj == pladdr1) { + /* Fast-path. We are ready and the cur_lladdr_obj is still in the cache. We + * got the result with a dictionary lookup without need to iterate over + * all addresses. */ + return self->cur_lladdr_obj; + } + pladdr1_looked_up = TRUE; + } + + if (!self->assume) { + /* We don't accept any suitable LL address, only he one we are waiting for. + * Let's do a dictionary lookup. */ + + if (IN6_IS_ADDR_LINKLOCAL(&self->cur_lladdr)) { + if (!pladdr1_looked_up) { + NMPObject needle; + + nmp_object_stackinit_id_ip6_address(&needle, + nm_l3_ipv6ll_get_ifindex(self), + &self->cur_lladdr); + pladdr1 = NMP_OBJECT_CAST_IP6_ADDRESS( + nm_platform_lookup_obj(nm_l3_ipv6ll_get_platform(self), + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + &needle)); + } + if (pladdr1) { + if (!_pladdr_is_ll_failed(pladdr1)) + return pladdr1; + *out_cur_addr_failed = TRUE; + } + } else + nm_assert(!pladdr1_looked_up); + + return NULL; + } + + if (!NM_IN_SET(self->state, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, NM_L3_IPV6LL_STATE_READY)) + cur_addr_check = FALSE; + + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, nm_l3_ipv6ll_get_ifindex(self)); + + nm_platform_iter_obj_for_each (&iter, nm_l3_ipv6ll_get_platform(self), &lookup, &obj) { + const NMPlatformIP6Address *pladdr = NMP_OBJECT_CAST_IP6_ADDRESS(obj); + + if (!IN6_IS_ADDR_LINKLOCAL(&pladdr->address)) + continue; + + if (_pladdr_is_ll_failed(pladdr)) { + if (cur_addr_check && IN6_ARE_ADDR_EQUAL(&self->cur_lladdr, &pladdr->address)) { + /* "pladdr" is the address we are currently doing DAD for. But it failed. + * We need to recognize and report to the caller, to stop waiting for this + * address. */ + cur_addr_failed = TRUE; + cur_addr_check = FALSE; + } + continue; + } + + if (_pladdr_is_ll_tentative(pladdr)) { + if (!pladdr_tentative) + pladdr_tentative = pladdr; + else if (pladdr == self->cur_lladdr_obj) + pladdr_tentative = pladdr; + else if (IN6_ARE_ADDR_EQUAL(&self->cur_lladdr, &pladdr->address)) + pladdr_tentative = pladdr; + continue; + } + + if (pladdr == self->cur_lladdr_obj) { + /* it doesn't get any better. We have our best address. */ + return pladdr; + } + if (!pladdr_ready) + pladdr_ready = pladdr; + else if (IN6_ARE_ADDR_EQUAL(&self->cur_lladdr, &pladdr->address)) + pladdr_ready = pladdr; + } + + *out_cur_addr_failed = cur_addr_failed; + return pladdr_ready ?: pladdr_tentative; +} + +/*****************************************************************************/ + +static void +_lladdr_handle_changed(NML3IPv6LL *self) +{ + const NML3ConfigData *l3cd; + gboolean changed = FALSE; + + /* We register the l3cd with l3cfg to start DAD. That is different from + * NML3IPv4LL, where we use NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD. The difference + * is that for IPv6 we let kernel do DAD, so we need to actually configure the + * address. For IPv4, we can run ACD without configuring anything in kernel, + * and let the user decide how to proceed. + * + * Also in this case, we use the most graceful commit-type (NM_L3_CFG_COMMIT_TYPE_ASSUME), + * but for that to work, we also need NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE flag. */ + + l3cd = nm_l3_ipv6ll_get_l3cd(self); + + if (l3cd) { + if (nm_l3cfg_add_config(self->l3cfg, + L3CD_TAG(self), + TRUE, + l3cd, + NM_L3CFG_CONFIG_PRIORITY_IPV6LL, + 0, + 0, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, + 0, + 0, + NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_L3_ACD_DEFEND_TYPE_ALWAYS, + 0, + NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE, + NM_L3_CONFIG_MERGE_FLAGS_NONE)) + changed = TRUE; + } else { + if (nm_l3cfg_remove_config_all(self->l3cfg, L3CD_TAG(self))) + changed = TRUE; + } + + self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg, + l3cd ? NM_L3_CFG_COMMIT_TYPE_ASSUME + : NM_L3_CFG_COMMIT_TYPE_NONE, + self->l3cfg_commit_handle, + "ipv6ll"); + + if (changed) + nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); + + if (!self->emit_changed_idle_source) { + _LOGT("schedule changed signal on idle"); + self->emit_changed_idle_source = nm_g_idle_add_source(_emit_changed_on_idle_cb, self); + } +} + +/*****************************************************************************/ + +static gboolean +_set_cur_lladdr(NML3IPv6LL *self, NML3IPv6LLState state, const struct in6_addr *lladdr) +{ + gboolean changed = FALSE; + + if (lladdr) { + nm_assert(IN6_IS_ADDR_LINKLOCAL(lladdr)); + if (!IN6_ARE_ADDR_EQUAL(&self->cur_lladdr, lladdr)) { + self->cur_lladdr = *lladdr; + nm_clear_l3cd(&self->l3cd); + changed = TRUE; + } + } else { + if (!nm_ip_addr_is_null(AF_INET6, &self->cur_lladdr)) { + nm_clear_l3cd(&self->l3cd); + self->cur_lladdr = nm_ip_addr_zero.addr6; + changed = TRUE; + } + nm_assert(!self->l3cd); + nm_assert(!_state_has_lladdr(state)); + } + + if (self->state != state) { + if (!_state_has_lladdr(state)) + nm_clear_l3cd(&self->l3cd); + self->state = state; + changed = TRUE; + } + + return changed; +} + +static gboolean +_set_cur_lladdr_obj(NML3IPv6LL *self, NML3IPv6LLState state, const NMPlatformIP6Address *lladdr_obj) +{ + nm_assert(lladdr_obj); + nm_assert(_state_has_lladdr(state)); + + nmp_object_ref_set_up_cast(&self->cur_lladdr_obj, lladdr_obj); + return _set_cur_lladdr(self, state, &lladdr_obj->address); +} + +static gboolean +_set_cur_lladdr_bin(NML3IPv6LL *self, NML3IPv6LLState state, const struct in6_addr *lladdr) +{ + nmp_object_ref_set_up_cast(&self->cur_lladdr_obj, NULL); + return _set_cur_lladdr(self, state, lladdr); +} + +static gboolean +_wait_for_addr_timeout_cb(gpointer user_data) +{ + NML3IPv6LL *self = user_data; + + nm_clear_g_source_inst(&self->wait_for_addr_source); + + nm_assert( + NM_IN_SET(self->state, NM_L3_IPV6LL_STATE_DAD_FAILED, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS)); + + _check(self); + + return G_SOURCE_CONTINUE; +} + +static void +_check(NML3IPv6LL *self) +{ + const NMPlatformIP6Address *pladdr; + char sbuf[INET6_ADDRSTRLEN]; + gboolean cur_addr_failed; + struct in6_addr lladdr; + + pladdr = _pladdr_find_ll(self, &cur_addr_failed); + + if (pladdr) { + nm_clear_g_source_inst(&self->wait_for_addr_source); + + if (_pladdr_is_ll_tentative(pladdr)) { + if (_set_cur_lladdr_obj(self, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, pladdr)) { + _LOGT("changed: waiting for address %s to complete DAD", + _nm_utils_inet6_ntop(&self->cur_lladdr, sbuf)); + _lladdr_handle_changed(self); + } + return; + } + + if (_set_cur_lladdr_obj(self, NM_L3_IPV6LL_STATE_READY, pladdr)) { + _LOGT("changed: address %s is ready", _nm_utils_inet6_ntop(&self->cur_lladdr, sbuf)); + _lladdr_handle_changed(self); + } + return; + } + + if (self->cur_lladdr_obj || cur_addr_failed) { + /* we were doing DAD, but the address is no longer a suitable candidate. + * Prematurely abort DAD to generate a new address below. */ + nm_assert( + NM_IN_SET(self->state, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, NM_L3_IPV6LL_STATE_READY)); + if (self->state == NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS) + _LOGT("changed: address %s did not complete DAD", + _nm_utils_inet6_ntop(&self->cur_lladdr, sbuf)); + else { + _LOGT("changed: address %s is gone", _nm_utils_inet6_ntop(&self->cur_lladdr, sbuf)); + } + + /* reset the state here, so that we are sure that the following + * _set_cur_lladdr_bin() calls (below) will notice the change + * and trigger a _lladdr_handle_changed(). */ + _set_cur_lladdr_bin(self, NM_L3_IPV6LL_STATE_STARTING, NULL); + nm_clear_g_source_inst(&self->wait_for_addr_source); + } else if (self->wait_for_addr_source) { + /* we are waiting. Nothing to do for now. */ + return; + } + + if (!_generate_new_address(self, &lladdr)) { + /* our DAD counter expired. We reset it, and start a timer to retry + * and recover. */ + self->addrgen.dad_counter = 0; + self->wait_for_addr_source = + nm_g_timeout_add_source(10000, _wait_for_addr_timeout_cb, self); + if (_set_cur_lladdr_bin(self, NM_L3_IPV6LL_STATE_DAD_FAILED, NULL)) { + _LOGW("changed: no IPv6 link local address to retry after Duplicate Address Detection " + "failures (back off)"); + _lladdr_handle_changed(self); + } + return; + } + + /* we give NML3Cfg 2 seconds to configure the address on the interface. We + * thus very soon expect to see this address configured (and kernel started DAD). + * If that does not happen within timeout, we assume that this address failed DAD. */ + self->wait_for_addr_source = nm_g_timeout_add_source(2000, _wait_for_addr_timeout_cb, self); + if (_set_cur_lladdr_bin(self, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, &lladdr)) { + _LOGT("changed: starting DAD for address %s", + _nm_utils_inet6_ntop(&self->cur_lladdr, sbuf)); + _lladdr_handle_changed(self); + } + return; +} + +/*****************************************************************************/ + +static void +_l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NML3IPv6LL *self) +{ + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE) { + if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags, + nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ADDRESS))) + _check(self); + return; + } +} + +/*****************************************************************************/ + +static gboolean +_starting_on_idle_cb(gpointer user_data) +{ + NML3IPv6LL *self = user_data; + + nm_clear_g_source_inst(&self->starting_on_idle_source); + + self->l3cfg_signal_notify_id = + g_signal_connect(self->l3cfg, NM_L3CFG_SIGNAL_NOTIFY, G_CALLBACK(_l3cfg_notify_cb), self); + + _check(self); + + return G_SOURCE_CONTINUE; +} + +/*****************************************************************************/ + +NML3IPv6LL * +_nm_l3_ipv6ll_new(NML3Cfg * l3cfg, + gboolean assume, + NMUtilsStableType stable_type, + const char * ifname, + const char * network_id, + const NMUtilsIPv6IfaceId *token_iid, + NML3IPv6LLNotifyFcn notify_fcn, + gpointer user_data) +{ + NML3IPv6LL *self; + + g_return_val_if_fail(NM_IS_L3CFG(l3cfg), NULL); + g_return_val_if_fail(notify_fcn, NULL); + g_return_val_if_fail( + (stable_type == NM_UTILS_STABLE_TYPE_NONE && !ifname && !network_id && token_iid) + || (stable_type != NM_UTILS_STABLE_TYPE_NONE && ifname && network_id && !token_iid), + NULL); + + self = g_slice_new(NML3IPv6LL); + *self = (NML3IPv6LL){ + .l3cfg = g_object_ref(l3cfg), + .notify_fcn = notify_fcn, + .user_data = user_data, + .state = NM_L3_IPV6LL_STATE_STARTING, + .starting_on_idle_source = nm_g_idle_add_source(_starting_on_idle_cb, self), + .l3cfg_signal_notify_id = 0, + .cur_lladdr_obj = NULL, + .cur_lladdr = IN6ADDR_ANY_INIT, + .assume = assume, + .addrgen = + { + .stable_type = stable_type, + .dad_counter = 0, + }, + }; + + if (self->addrgen.stable_type == NM_UTILS_STABLE_TYPE_NONE) { + char sbuf_token[sizeof(self->addrgen.token.iid) * 3]; + + self->addrgen.token.iid = *token_iid; + _LOGT("created: l3cfg=" NM_HASH_OBFUSCATE_PTR_FMT ", ifindex=%d, token=%s%s", + NM_HASH_OBFUSCATE_PTR(l3cfg), + nm_l3cfg_get_ifindex(l3cfg), + nm_utils_bin2hexstr_full(&self->addrgen.token.iid, + sizeof(self->addrgen.token.iid), + ':', + FALSE, + sbuf_token), + self->assume ? ", assume" : ""); + } else { + self->addrgen.stable_privacy.ifname = g_strdup(ifname); + self->addrgen.stable_privacy.network_id = g_strdup(network_id); + _LOGT("created: l3cfg=" NM_HASH_OBFUSCATE_PTR_FMT + ", ifindex=%d, stable-type=%u, ifname=%s, network_id=%s%s", + NM_HASH_OBFUSCATE_PTR(l3cfg), + nm_l3cfg_get_ifindex(l3cfg), + (unsigned) self->addrgen.stable_type, + self->addrgen.stable_privacy.ifname, + self->addrgen.stable_privacy.network_id, + self->assume ? ", assume" : ""); + } + + return self; +} + +void +nm_l3_ipv6ll_destroy(NML3IPv6LL *self) +{ + if (!self) + return; + + _ASSERT(self); + + _LOGT("finalize"); + + nm_l3cfg_commit_type_unregister(self->l3cfg, g_steal_pointer(&self->l3cfg_commit_handle)); + + nm_l3cfg_remove_config_all(self->l3cfg, L3CD_TAG(self)); + + nm_clear_g_source_inst(&self->starting_on_idle_source); + nm_clear_g_source_inst(&self->wait_for_addr_source); + nm_clear_g_source_inst(&self->emit_changed_idle_source); + nm_clear_g_signal_handler(self->l3cfg, &self->l3cfg_signal_notify_id); + + g_clear_object(&self->l3cfg); + + nm_clear_l3cd(&self->l3cd); + + nm_clear_nmp_object_up_cast(&self->cur_lladdr_obj); + + if (self->addrgen.stable_type != NM_UTILS_STABLE_TYPE_NONE) { + g_free((char *) self->addrgen.stable_privacy.ifname); + g_free((char *) self->addrgen.stable_privacy.network_id); + } + + nm_g_slice_free(self); +} diff --git a/src/core/nm-l3-ipv6ll.h b/src/core/nm-l3-ipv6ll.h new file mode 100644 index 00000000..770a4268 --- /dev/null +++ b/src/core/nm-l3-ipv6ll.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_L3_IPV6LL_H__ +#define __NM_L3_IPV6LL_H__ + +#include "nm-l3cfg.h" +#include "nm-core-utils.h" + +/*****************************************************************************/ + +typedef struct _NML3IPv6LL NML3IPv6LL; + +typedef enum _nm_packed { + NM_L3_IPV6LL_STATE_STARTING, + NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, + NM_L3_IPV6LL_STATE_READY, + NM_L3_IPV6LL_STATE_DAD_FAILED, + + /* The following flags are not actually use by NML3IPv6LL. They exist for + * convenience of the users, to encode additional states. */ + + /* IPv6LL is disabled */ + NM_L3_IPV6LL_STATE_NONE, + + /* We want to do IPv6LL, but something is missing so we cannot even create + * a NML3IPv6LL instance. For example, no NML3Cfg instance or no interface name. */ + NM_L3_IPV6LL_STATE_DEFUNCT, + +} NML3IPv6LLState; + +const char *nm_l3_ipv6ll_state_to_string(NML3IPv6LLState state); + +typedef void (*NML3IPv6LLNotifyFcn)(NML3IPv6LL * ipv6ll, + NML3IPv6LLState state, + const struct in6_addr *lladdr, + gpointer user_data); + +static inline gboolean +NM_IS_L3_IPV6LL(const NML3IPv6LL *self) +{ + nm_assert(!self || (NM_IS_L3CFG(*((NML3Cfg **) self)))); + return !!self; +} + +NML3IPv6LL *_nm_l3_ipv6ll_new(NML3Cfg * l3cfg, + gboolean assume, + NMUtilsStableType stable_type, + const char * ifname, + const char * network_id, + const NMUtilsIPv6IfaceId *token_iid, + NML3IPv6LLNotifyFcn notify_fcn, + gpointer user_data); + +static inline NML3IPv6LL * +nm_l3_ipv6ll_new_stable_privacy(NML3Cfg * l3cfg, + gboolean assume, + NMUtilsStableType stable_type, + const char * ifname, + const char * network_id, + NML3IPv6LLNotifyFcn notify_fcn, + gpointer user_data) +{ + nm_assert(stable_type != NM_UTILS_STABLE_TYPE_NONE); + return _nm_l3_ipv6ll_new(l3cfg, + assume, + stable_type, + ifname, + network_id, + NULL, + notify_fcn, + user_data); +} + +static inline NML3IPv6LL * +nm_l3_ipv6ll_new_token(NML3Cfg * l3cfg, + gboolean assume, + const NMUtilsIPv6IfaceId *token_iid, + NML3IPv6LLNotifyFcn notify_fcn, + gpointer user_data) +{ + return _nm_l3_ipv6ll_new(l3cfg, + assume, + NM_UTILS_STABLE_TYPE_NONE, + NULL, + NULL, + token_iid, + notify_fcn, + user_data); +} + +void nm_l3_ipv6ll_destroy(NML3IPv6LL *self); + +NM_AUTO_DEFINE_FCN0(NML3IPv6LL *, _nm_auto_destroy_l3ipv6ll, nm_l3_ipv6ll_destroy); +#define nm_auto_destroy_l3ipv6ll nm_auto(_nm_auto_destroy_l3ipv6ll) + +/*****************************************************************************/ + +NML3Cfg *nm_l3_ipv6ll_get_l3cfg(NML3IPv6LL *self); + +int nm_l3_ipv6ll_get_ifindex(NML3IPv6LL *self); + +NMPlatform *nm_l3_ipv6ll_get_platform(NML3IPv6LL *self); + +/*****************************************************************************/ + +NML3IPv6LLState nm_l3_ipv6ll_get_state(NML3IPv6LL *self, const struct in6_addr **out_lladdr); + +const NML3ConfigData *nm_l3_ipv6ll_get_l3cd(NML3IPv6LL *self); + +/*****************************************************************************/ + +#endif /* __NM_L3_IPV6LL_H__ */ diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index 93e92673..aa56c13f 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -18,6 +18,17 @@ /*****************************************************************************/ +#define ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC ((gint64) 20000) + +/* When a ObjStateData becomes a "zombie", we aim to delete it from platform + * on the next commit (until it disappears from platform). But we might have + * a bug, so that we fail to delete the platform (for example, related to + * IPv6 multicast routes). We thus rate limit how often we try to do this, + * before giving up. */ +#define ZOMBIE_COUNT_START 5 + +/*****************************************************************************/ + G_STATIC_ASSERT(NM_ACD_TIMEOUT_RFC5227_MSEC == N_ACD_TIMEOUT_RFC5227); #define ACD_SUPPORTED_ETH_ALEN ETH_ALEN @@ -97,6 +108,58 @@ typedef struct { G_STATIC_ASSERT(G_STRUCT_OFFSET(AcdData, info.addr) == 0); +typedef struct { + const NMPObject *obj; + + /* Whether obj is currently in the platform cache or not. + * Since "obj" is the NMPObject from the merged NML3ConfigData, + * the object in platform has the same ID (but may otherwise not + * be identical). If this is not NULL, then currently the object + * is configured in kernel. */ + const NMPObject *os_plobj; + + CList os_lst; + + /* If we have a timeout pending, we link the instance to + * self->priv.p->obj_state_temporary_not_available_lst_head. */ + CList os_temporary_not_available_lst; + + /* If a NMPObject is no longer to be configured (but was configured + * during a previous commit), then we need to remember it so that the + * next commit can delete the address/route in kernel. It becomes a zombie. */ + CList os_zombie_lst; + + /* We might want to configure "obj" in platform, but it's currently not possible. + * For example, certain IPv6 routes can only be added after the IPv6 address + * becomes non-tentative (*sigh*). In such a case, we need to remember that, and + * retry later. If this timestamp is set to a non-zero value, then it means + * we tried to configure the obj (at that timestamp) and failed, but we are + * waiting to retry. + * + * See also self->priv.p->obj_state_temporary_not_available_lst_head + * and self->priv.p->obj_state_temporary_not_available_timeout_source. */ + gint64 os_temporary_not_available_timestamp_msec; + + /* When the obj is a zombie (that means, it was previously configured by NML3Cfg, but + * now no longer), it needs to be deleted from platform. This ratelimits the time + * how often we try that. When the counter reaches zero, we forget about it. */ + guint8 os_zombie_count; + + /* whether we ever saw the object in platform. */ + bool os_was_in_platform : 1; + + /* Indicates whether NetworkManager actively tried to configure the object + * in platform once. */ + bool os_nm_configured : 1; + + /* This flag is only used temporarily to do a bulk update and + * clear all the ones that are no longer in used. */ + bool os_dirty : 1; + bool os_tna_dirty : 1; +} ObjStateData; + +G_STATIC_ASSERT(G_STRUCT_OFFSET(ObjStateData, obj) == 0); + struct _NML3CfgCommitTypeHandle { CList commit_type_lst; NML3CfgCommitType commit_type; @@ -104,6 +167,7 @@ struct _NML3CfgCommitTypeHandle { typedef struct { const NML3ConfigData *l3cd; + NML3CfgConfigFlags config_flags; NML3ConfigMergeFlags merge_flags; union { struct { @@ -126,6 +190,13 @@ typedef struct { }; guint32 default_route_penalty_x[2]; }; + union { + struct { + int default_dns_priority_6; + int default_dns_priority_4; + }; + int default_dns_priority_x[2]; + }; gconstpointer tag_confdata; guint64 pseudo_timestamp_confdata; int priority_confdata; @@ -146,7 +217,6 @@ enum { static guint signals[LAST_SIGNAL] = {0}; typedef struct _NML3CfgPrivate { - GArray *property_emit_list; GArray *l3_config_datas; NML3IPv4LL *ipv4ll; @@ -157,9 +227,11 @@ typedef struct _NML3CfgPrivate { CList commit_type_lst_head; - GHashTable *routes_temporary_not_available_hash; + GHashTable *obj_state_hash; - GHashTable *externally_removed_objs_hash; + CList obj_state_lst_head; + CList obj_state_zombie_lst_head; + CList obj_state_temporary_not_available_lst_head; GHashTable *acd_ipv4_addresses_on_link; @@ -181,41 +253,30 @@ typedef struct _NML3CfgPrivate { guint64 pseudo_timestamp_counter; - union { - struct { - guint externally_removed_objs_cnt_addresses_6; - guint externally_removed_objs_cnt_addresses_4; - }; - guint externally_removed_objs_cnt_addresses_x[2]; - }; + GSource *obj_state_temporary_not_available_timeout_source; - union { - struct { - guint externally_removed_objs_cnt_routes_6; - guint externally_removed_objs_cnt_routes_4; - }; - guint externally_removed_objs_cnt_routes_x[2]; - }; + NML3CfgCommitType commit_on_idle_type; - union { - struct { - GPtrArray *last_addresses_6; - GPtrArray *last_addresses_4; - }; - GPtrArray *last_addresses_x[2]; - }; + gint8 commit_reentrant_count; - union { - struct { - GPtrArray *last_routes_6; - GPtrArray *last_routes_4; - }; - GPtrArray *last_routes_x[2]; - }; + /* The value that was set before we touched the sysctl (this only is + * meaningful if "ip6_privacy_set" is true. At the end, we want to restore + * this value. */ + NMSettingIP6ConfigPrivacy ip6_privacy_initial : 4; - guint routes_temporary_not_available_id; + /* The value that we set the last time. This is cached so that we don't + * repeatedly try to commit the same value. */ + NMSettingIP6ConfigPrivacy ip6_privacy_set_before : 4; - gint8 commit_reentrant_count; + guint32 ndisc_retrans_timer_msec; + guint32 ndisc_reachable_time_msec; + int ndisc_hop_limit; + + /* Whether "self" set the ip6_privacy sysctl (and whether it needs to be reset). */ + bool ip6_privacy_set : 1; + bool ndisc_reachable_time_msec_set : 1; + bool ndisc_retrans_timer_msec_set : 1; + bool ndisc_hop_limit_set : 1; bool commit_type_update_sticky : 1; @@ -268,8 +329,6 @@ G_DEFINE_TYPE(NML3Cfg, nm_l3cfg, G_TYPE_OBJECT) static void _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle); -static void _property_emit_notify(NML3Cfg *self, NML3CfgPropertyEmitType emit_type); - static void _nm_l3cfg_emit_signal_notify_acd_event_all(NML3Cfg *self); static gboolean _acd_has_valid_link(const NMPObject *obj, @@ -305,6 +364,7 @@ static NM_UTILS_ENUM2STR_DEFINE( NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED, "l3cd-changed"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, "platform-change"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, "platform-change-on-idle"), + NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT, "pre-commit"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, "post-commit"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED, "routes-temporary-not-available-expired"), @@ -314,7 +374,7 @@ static NM_UTILS_ENUM2STR_DEFINE(_l3_acd_defend_type_to_string, NML3AcdDefendType, NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_ALWAYS, "always"), NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_NEVER, "never"), - NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_NONE, "none"), + NM_UTILS_ENUM2STR(_NM_L3_ACD_DEFEND_TYPE_NONE, "none"), NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_ONCE, "once"), ); static NM_UTILS_LOOKUP_DEFINE(_l3_acd_defend_type_to_nacd, @@ -342,6 +402,17 @@ static NM_UTILS_LOOKUP_DEFINE(_l3_acd_addr_state_to_string, /*****************************************************************************/ +gboolean +nm_l3cfg_is_vrf(const NML3Cfg *self) +{ + const NMPlatformLink *pllink; + + pllink = nm_l3cfg_get_pllink(self, TRUE); + return pllink && pllink->type == NM_LINK_TYPE_VRF; +} + +/*****************************************************************************/ + static const char * _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, char * sbuf, @@ -358,31 +429,29 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, nm_assert(sbuf_size > 0); _l3_config_notify_type_to_string(notify_data->notify_type, s, l); - nm_utils_strbuf_seek_end(&s, &l); + nm_strbuf_seek_end(&s, &l); switch (notify_data->notify_type) { case NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED: - nm_utils_strbuf_append( - &s, - &l, - ", l3cd-old=%s", - NM_HASH_OBFUSCATE_PTR_STR(notify_data->l3cd_changed.l3cd_old, sbufobf)); - nm_utils_strbuf_append( - &s, - &l, - ", l3cd-new=%s", - NM_HASH_OBFUSCATE_PTR_STR(notify_data->l3cd_changed.l3cd_new, sbufobf)); - nm_utils_strbuf_append(&s, &l, ", commited=%d", notify_data->l3cd_changed.commited); + nm_strbuf_append(&s, + &l, + ", l3cd-old=%s", + NM_HASH_OBFUSCATE_PTR_STR(notify_data->l3cd_changed.l3cd_old, sbufobf)); + nm_strbuf_append(&s, + &l, + ", l3cd-new=%s", + NM_HASH_OBFUSCATE_PTR_STR(notify_data->l3cd_changed.l3cd_new, sbufobf)); + nm_strbuf_append(&s, &l, ", commited=%d", notify_data->l3cd_changed.commited); break; case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT: - nm_utils_strbuf_append(&s, - &l, - ", addr=%s, state=%s", - _nm_utils_inet4_ntop(notify_data->acd_event.info.addr, sbuf_addr), - _l3_acd_addr_state_to_string(notify_data->acd_event.info.state)); + nm_strbuf_append(&s, + &l, + ", addr=%s, state=%s", + _nm_utils_inet4_ntop(notify_data->acd_event.info.addr, sbuf_addr), + _l3_acd_addr_state_to_string(notify_data->acd_event.info.state)); break; case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE: - nm_utils_strbuf_append( + nm_strbuf_append( &s, &l, ", obj-type=%s, change=%s, obj=", @@ -391,15 +460,15 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, nmp_object_to_string(notify_data->platform_change.obj, NMP_OBJECT_TO_STRING_PUBLIC, s, l); break; case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE: - nm_utils_strbuf_append(&s, - &l, - ", obj-type-flags=0x%x", - notify_data->platform_change_on_idle.obj_type_flags); + nm_strbuf_append(&s, + &l, + ", obj-type-flags=0x%x", + notify_data->platform_change_on_idle.obj_type_flags); break; case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT: nm_assert(NM_IS_L3_IPV4LL(notify_data->ipv4ll_event.ipv4ll)); addr4 = nm_l3_ipv4ll_get_addr(notify_data->ipv4ll_event.ipv4ll); - nm_utils_strbuf_append( + nm_strbuf_append( &s, &l, ", ipv4ll=" NM_HASH_OBFUSCATE_PTR_FMT "%s%s, state=%s", @@ -555,157 +624,447 @@ _nm_n_acd_data_probe_new(NML3Cfg *self, in_addr_t addr, guint32 timeout_msec, gp /*****************************************************************************/ -static guint * -_l3cfg_externally_removed_objs_counter(NML3Cfg *self, NMPObjectType obj_type) +#define nm_assert_obj_state(self, obj_state) \ + G_STMT_START \ + { \ + if (NM_MORE_ASSERTS > 0) { \ + const NML3Cfg * _self = (self); \ + const ObjStateData *_obj_state = (obj_state); \ + \ + nm_assert(_obj_state); \ + nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(_obj_state->obj), \ + NMP_OBJECT_TYPE_IP4_ADDRESS, \ + NMP_OBJECT_TYPE_IP6_ADDRESS, \ + NMP_OBJECT_TYPE_IP4_ROUTE, \ + NMP_OBJECT_TYPE_IP6_ROUTE)); \ + nm_assert(!_obj_state->os_plobj || _obj_state->os_was_in_platform); \ + nm_assert((_obj_state->os_temporary_not_available_timestamp_msec == 0) \ + == c_list_is_empty(&_obj_state->os_temporary_not_available_lst)); \ + if (_self) { \ + if (c_list_is_empty(&_obj_state->os_zombie_lst)) { \ + nm_assert(_self->priv.p->combined_l3cd_commited); \ + \ + if (NM_MORE_ASSERTS > 5) { \ + nm_assert(c_list_contains(&_self->priv.p->obj_state_lst_head, \ + &_obj_state->os_lst)); \ + nm_assert((_obj_state->os_temporary_not_available_timestamp_msec == 0) \ + || c_list_contains( \ + &_self->priv.p->obj_state_temporary_not_available_lst_head, \ + &_obj_state->os_temporary_not_available_lst)); \ + nm_assert(_obj_state->os_plobj \ + == nm_platform_lookup_obj(_self->priv.platform, \ + NMP_CACHE_ID_TYPE_OBJECT_TYPE, \ + _obj_state->obj)); \ + nm_assert( \ + c_list_is_empty(&obj_state->os_zombie_lst) \ + ? (_obj_state->obj \ + == nm_dedup_multi_entry_get_obj(nm_l3_config_data_lookup_obj( \ + _self->priv.p->combined_l3cd_commited, \ + _obj_state->obj))) \ + : (!nm_l3_config_data_lookup_obj( \ + _self->priv.p->combined_l3cd_commited, \ + _obj_state->obj))); \ + } \ + } \ + } \ + } \ + } \ + G_STMT_END + +static gboolean +_obj_state_data_get_assume_config_once(const ObjStateData *obj_state) { - switch (obj_type) { - case NMP_OBJECT_TYPE_IP4_ADDRESS: - return &self->priv.p->externally_removed_objs_cnt_addresses_4; - case NMP_OBJECT_TYPE_IP6_ADDRESS: - return &self->priv.p->externally_removed_objs_cnt_addresses_6; - case NMP_OBJECT_TYPE_IP4_ROUTE: - return &self->priv.p->externally_removed_objs_cnt_routes_4; - case NMP_OBJECT_TYPE_IP6_ROUTE: - return &self->priv.p->externally_removed_objs_cnt_routes_6; - default: - return nm_assert_unreachable_val(NULL); - } + nm_assert_obj_state(NULL, obj_state); + + return nmp_object_get_assume_config_once(obj_state->obj); +} + +static ObjStateData * +_obj_state_data_new(const NMPObject *obj, const NMPObject *plobj) +{ + ObjStateData *obj_state; + + obj_state = g_slice_new(ObjStateData); + *obj_state = (ObjStateData){ + .obj = nmp_object_ref(obj), + .os_plobj = nmp_object_ref(plobj), + .os_was_in_platform = !!plobj, + .os_nm_configured = FALSE, + .os_dirty = FALSE, + .os_temporary_not_available_lst = C_LIST_INIT(obj_state->os_temporary_not_available_lst), + .os_zombie_lst = C_LIST_INIT(obj_state->os_zombie_lst), + }; + return obj_state; } static void -_l3cfg_externally_removed_objs_drop(NML3Cfg *self) +_obj_state_data_free(gpointer data) { - nm_assert(NM_IS_L3CFG(self)); + ObjStateData *obj_state = data; + + c_list_unlink_stale(&obj_state->os_lst); + c_list_unlink_stale(&obj_state->os_zombie_lst); + c_list_unlink_stale(&obj_state->os_temporary_not_available_lst); + nmp_object_unref(obj_state->obj); + nmp_object_unref(obj_state->os_plobj); + nm_g_slice_free(obj_state); +} + +static const char * +_obj_state_data_to_string(const ObjStateData *obj_state, char *buf, gsize buf_size) +{ + const char *buf0 = buf; + gint64 now_msec = 0; + + nm_assert(buf); + nm_assert(buf_size > 0); + nm_assert_obj_state(NULL, obj_state); + + nm_strbuf_append(&buf, + &buf_size, + "[" NM_HASH_OBFUSCATE_PTR_FMT ", %s, ", + NM_HASH_OBFUSCATE_PTR(obj_state), + NMP_OBJECT_GET_CLASS(obj_state->obj)->obj_type_name); + + nmp_object_to_string(obj_state->obj, NMP_OBJECT_TO_STRING_PUBLIC, buf, buf_size); + nm_strbuf_seek_end(&buf, &buf_size); + nm_strbuf_append_c(&buf, &buf_size, ']'); + + if (!c_list_is_empty(&obj_state->os_zombie_lst)) + nm_strbuf_append(&buf, &buf_size, ", zombie[%u]", obj_state->os_zombie_count); + + if (obj_state->os_nm_configured) + nm_strbuf_append_str(&buf, &buf_size, ", nm-configured"); + + if (obj_state->os_plobj) { + nm_assert(obj_state->os_was_in_platform); + nm_strbuf_append_str(&buf, &buf_size, ", in-platform"); + } else if (obj_state->os_was_in_platform) + nm_strbuf_append_str(&buf, &buf_size, ", was-in-platform"); + + if (obj_state->os_temporary_not_available_timestamp_msec > 0) { + nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); + nm_strbuf_append( + &buf, + &buf_size, + ", temporary-not-available-since=%" G_GINT64_FORMAT ".%03d", + (now_msec - obj_state->os_temporary_not_available_timestamp_msec) / 1000, + (int) ((now_msec - obj_state->os_temporary_not_available_timestamp_msec) % 1000)); + } + + return buf0; +} + +static gboolean +_obj_state_data_update(ObjStateData *obj_state, const NMPObject *obj) +{ + gboolean changed = FALSE; + + nm_assert_obj_state(NULL, obj_state); + nm_assert(obj); + nm_assert(nmp_object_id_equal(obj_state->obj, obj)); + + obj_state->os_dirty = FALSE; - self->priv.p->externally_removed_objs_cnt_addresses_4 = 0; - self->priv.p->externally_removed_objs_cnt_addresses_6 = 0; - self->priv.p->externally_removed_objs_cnt_routes_4 = 0; - self->priv.p->externally_removed_objs_cnt_routes_6 = 0; - if (nm_g_hash_table_size(self->priv.p->externally_removed_objs_hash) > 0) - _LOGD("externally-removed: untrack all"); - nm_clear_pointer(&self->priv.p->externally_removed_objs_hash, g_hash_table_unref); + if (obj_state->obj != obj) { + nm_auto_nmpobj const NMPObject *obj_old = NULL; + + if (!nmp_object_equal(obj_state->obj, obj)) + changed = TRUE; + obj_old = g_steal_pointer(&obj_state->obj); + obj_state->obj = nmp_object_ref(obj); + } + + if (!c_list_is_empty(&obj_state->os_zombie_lst)) { + c_list_unlink(&obj_state->os_zombie_lst); + changed = TRUE; + } + + return changed; } +/*****************************************************************************/ + static void -_l3cfg_externally_removed_objs_drop_unused(NML3Cfg *self) +_obj_states_externally_removed_track(NML3Cfg *self, const NMPObject *obj, gboolean in_platform) { - GHashTableIter h_iter; - const NMPObject *obj; - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + ObjStateData *obj_state; nm_assert(NM_IS_L3CFG(self)); + nm_assert_is_bool(in_platform); - if (!self->priv.p->externally_removed_objs_hash) + nm_assert( + in_platform + ? (obj + == nm_platform_lookup_obj(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)) + : (!nm_platform_lookup_obj(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj))); + + obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &obj); + if (!obj_state) return; - if (!self->priv.p->combined_l3cd_commited) { - _l3cfg_externally_removed_objs_drop(self); + if (!in_platform) + obj = NULL; + + if (obj_state->os_plobj == obj) + goto out; + + if (!in_platform && !c_list_is_empty(&obj_state->os_zombie_lst)) { + /* this is a zombie. We can forget about it.*/ + nm_clear_nmp_object(&obj_state->os_plobj); + c_list_unlink(&obj_state->os_zombie_lst); + _LOGD("obj-state: zombie gone (untrack): %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + g_hash_table_remove(self->priv.p->obj_state_hash, obj_state); return; } - g_hash_table_iter_init(&h_iter, self->priv.p->externally_removed_objs_hash); - while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj, NULL)) { - if (!nm_l3_config_data_lookup_obj(self->priv.p->combined_l3cd_commited, obj)) { - /* The object is no longer tracked in the configuration. - * The externally_removed_objs_hash is to prevent adding entires that were - * removed externally, so if we don't plan to add the entry, we no longer need to track - * it. */ - _LOGD("externally-removed: untrack %s", - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); - (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj))))--; - g_hash_table_iter_remove(&h_iter); - } + nm_assert(c_list_is_empty(&obj_state->os_zombie_lst)); + + if (in_platform) { + nmp_object_ref_set(&obj_state->os_plobj, obj); + obj_state->os_was_in_platform = TRUE; + _LOGD("obj-state: appeared in platform: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + goto out; } + + nm_clear_nmp_object(&obj_state->os_plobj); + _LOGD("obj-state: remove from platform: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + +out: + nm_assert_obj_state(self, obj_state); } static void -_l3cfg_externally_removed_objs_track(NML3Cfg *self, const NMPObject *obj, gboolean is_removed) +_obj_states_update_all(NML3Cfg *self) { - char sbuf[1000]; + static const NMPObjectType obj_types[] = { + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE, + }; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + ObjStateData *obj_state; + int i; + gboolean any_dirty = FALSE; nm_assert(NM_IS_L3CFG(self)); - if (!self->priv.p->combined_l3cd_commited) - return; + c_list_for_each_entry (obj_state, &self->priv.p->obj_state_lst_head, os_lst) { + if (!c_list_is_empty(&obj_state->os_zombie_lst)) { + /* we can ignore zombies. */ + continue; + } + any_dirty = TRUE; + obj_state->os_dirty = TRUE; + } + + for (i = 0; i < (int) G_N_ELEMENTS(obj_types); i++) { + const NMPObjectType obj_type = obj_types[i]; + NMDedupMultiIter o_iter; + const NMPObject * obj; + + if (!self->priv.p->combined_l3cd_commited) + continue; + + nm_l3_config_data_iter_obj_for_each (&o_iter, + self->priv.p->combined_l3cd_commited, + &obj, + obj_type) { + obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &obj); + if (!obj_state) { + obj_state = + _obj_state_data_new(obj, + nm_platform_lookup_obj(self->priv.platform, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + obj)); + c_list_link_tail(&self->priv.p->obj_state_lst_head, &obj_state->os_lst); + g_hash_table_add(self->priv.p->obj_state_hash, obj_state); + _LOGD("obj-state: track: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + nm_assert_obj_state(self, obj_state); + continue; + } - if (!is_removed) { - /* the object is still (or again) present. It no longer gets hidden. */ - if (self->priv.p->externally_removed_objs_hash) { - const NMPObject *obj2; - gpointer x_val; - - if (g_hash_table_steal_extended(self->priv.p->externally_removed_objs_hash, - obj, - (gpointer *) &obj2, - &x_val)) { - (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj2))))--; - _LOGD("externally-removed: untrack %s", - nmp_object_to_string(obj2, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); - nmp_object_unref(obj2); + if (_obj_state_data_update(obj_state, obj)) { + _LOGD("obj-state: update: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); } + + nm_assert_obj_state(self, obj_state); } - return; } - if (!nm_l3_config_data_lookup_obj(self->priv.p->combined_l3cd_commited, obj)) { - /* we don't care about this object, so there is nothing to hide hide */ - return; + if (any_dirty) { + GHashTableIter h_iter; + + g_hash_table_iter_init(&h_iter, self->priv.p->obj_state_hash); + while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_state, NULL)) { + if (!c_list_is_empty(&obj_state->os_zombie_lst)) + continue; + if (!obj_state->os_dirty) + continue; + + if (obj_state->os_plobj && obj_state->os_nm_configured) { + c_list_link_tail(&self->priv.p->obj_state_zombie_lst_head, + &obj_state->os_zombie_lst); + obj_state->os_zombie_count = ZOMBIE_COUNT_START; + _LOGD("obj-state: now zombie: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + continue; + } + + _LOGD("obj-state: untrack: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + g_hash_table_iter_remove(&h_iter); + } } +} - if (G_UNLIKELY(!self->priv.p->externally_removed_objs_hash)) { - self->priv.p->externally_removed_objs_hash = - g_hash_table_new_full((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal, - (GDestroyNotify) nmp_object_unref, - NULL); +typedef struct { + NML3Cfg * self; + NML3CfgCommitType commit_type; +} ObjStatesSyncFilterData; + +static gboolean +_obj_states_sync_filter(/* const NMDedupMultiObj * */ gconstpointer o, gpointer user_data) +{ + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + const NMPObject * obj = o; + const ObjStatesSyncFilterData *sync_filter_data = user_data; + NMPObjectType obj_type; + ObjStateData * obj_state; + + nm_assert(sync_filter_data); + nm_assert(NM_IS_L3CFG(sync_filter_data->self)); + + obj_type = NMP_OBJECT_GET_TYPE(obj); + + if (obj_type == NMP_OBJECT_TYPE_IP4_ADDRESS + && NMP_OBJECT_CAST_IP4_ADDRESS(obj)->a_acd_not_ready) + return FALSE; + + obj_state = g_hash_table_lookup(sync_filter_data->self->priv.p->obj_state_hash, &obj); + + nm_assert_obj_state(sync_filter_data->self, obj_state); + nm_assert(obj_state->obj == obj); + nm_assert(c_list_is_empty(&obj_state->os_zombie_lst)); + + if (!obj_state->os_nm_configured) { + NML3Cfg *self; + + if (sync_filter_data->commit_type == NM_L3_CFG_COMMIT_TYPE_ASSUME + && !_obj_state_data_get_assume_config_once(obj_state)) + return FALSE; + + obj_state->os_nm_configured = TRUE; + + self = sync_filter_data->self; + _LOGD("obj-state: configure-first-time: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + return TRUE; } - if (g_hash_table_add(self->priv.p->externally_removed_objs_hash, - (gpointer) nmp_object_ref(obj))) { - (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj))))++; - _LOGD("externally-removed: track %s", - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); + if (obj_state->os_temporary_not_available_timestamp_msec > 0) { + /* we currently try to configure this address (but failed earlier). + * Definitely retry. */ + return TRUE; } + + if (!obj_state->os_plobj && sync_filter_data->commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY) + return FALSE; + + return TRUE; } static void -_l3cfg_externally_removed_objs_pickup(NML3Cfg *self, int addr_family) +_obj_state_zombie_lst_get_prune_lists(NML3Cfg * self, + int addr_family, + GPtrArray **out_addresses_prune, + GPtrArray **out_routes_prune) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMDedupMultiIter iter; - const NMPObject *obj; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMPObjectType obj_type_route = NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4); + const NMPObjectType obj_type_address = NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4); + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + ObjStateData * obj_state; + ObjStateData * obj_state_safe; - if (!self->priv.p->combined_l3cd_commited) - return; + nm_assert(NM_IS_L3CFG(self)); + nm_assert(out_addresses_prune && !*out_addresses_prune); + nm_assert(out_routes_prune && !*out_routes_prune); - nm_l3_config_data_iter_obj_for_each (&iter, - self->priv.p->combined_l3cd_commited, - &obj, - NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { - if (!nm_platform_lookup_entry(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)) - _l3cfg_externally_removed_objs_track(self, obj, TRUE); - } - nm_l3_config_data_iter_obj_for_each (&iter, - self->priv.p->combined_l3cd_commited, - &obj, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { - if (!nm_platform_lookup_entry(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)) - _l3cfg_externally_removed_objs_track(self, obj, TRUE); + c_list_for_each_entry_safe (obj_state, + obj_state_safe, + &self->priv.p->obj_state_zombie_lst_head, + os_zombie_lst) { + NMPObjectType obj_type; + GPtrArray ** p_a; + + nm_assert_obj_state(self, obj_state); + nm_assert(obj_state->os_zombie_count > 0); + + obj_type = NMP_OBJECT_GET_TYPE(obj_state->obj); + + if (obj_type == obj_type_route) + p_a = out_routes_prune; + else if (obj_type == obj_type_address) + p_a = out_addresses_prune; + else + continue; + + if (!*p_a) + *p_a = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + + g_ptr_array_add(*p_a, (gpointer) nmp_object_ref(obj_state->obj)); + + if (--obj_state->os_zombie_count == 0) { + _LOGD("obj-state: prune zombie (untrack): %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + g_hash_table_remove(self->priv.p->obj_state_hash, obj_state); + continue; + } + _LOGD("obj-state: prune zombie: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); } } -static gboolean -_l3cfg_externally_removed_objs_filter(/* const NMDedupMultiObj * */ gconstpointer o, - gpointer user_data) +static void +_obj_state_zombie_lst_prune_all(NML3Cfg *self, int addr_family) { - const NMPObject *obj = o; - GHashTable * externally_removed_objs_hash = user_data; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + ObjStateData *obj_state; + ObjStateData *obj_state_safe; - if (NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP4_ADDRESS - && NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready) - return FALSE; + /* we call this during reapply. Then we delete all the routes/addresses + * that are configured, and not only the zombies. + * + * Still, we need to adjust the os_zombie_count and assume that we + * are going to drop them. */ + + c_list_for_each_entry_safe (obj_state, + obj_state_safe, + &self->priv.p->obj_state_zombie_lst_head, + os_zombie_lst) { + nm_assert_obj_state(self, obj_state); + nm_assert(obj_state->os_zombie_count > 0); + + if (NMP_OBJECT_GET_ADDR_FAMILY(obj_state->obj) != addr_family) + continue; - return !nm_g_hash_table_contains(externally_removed_objs_hash, obj); + if (--obj_state->os_zombie_count == 0) { + _LOGD("obj-state: zombie pruned during reapply (untrack): %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + g_hash_table_remove(self->priv.p->obj_state_hash, obj_state); + continue; + } + _LOGD("obj-state: zombie pruned during reapply: %s", + _obj_state_data_to_string(obj_state, sbuf, sizeof(sbuf))); + } } /*****************************************************************************/ @@ -810,11 +1169,6 @@ _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags) _nm_l3cfg_emit_signal_notify(self, ¬ify_data); _nm_l3cfg_emit_signal_notify_acd_event_all(self); - - if (NM_FLAGS_ANY(obj_type_flags, nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP4_ROUTE))) - _property_emit_notify(self, NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE); - if (NM_FLAGS_ANY(obj_type_flags, nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ROUTE))) - _property_emit_notify(self, NM_L3CFG_PROPERTY_EMIT_TYPE_IP6_ROUTE); } void @@ -847,7 +1201,7 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self, case NMP_OBJECT_TYPE_IP6_ADDRESS: case NMP_OBJECT_TYPE_IP4_ROUTE: case NMP_OBJECT_TYPE_IP6_ROUTE: - _l3cfg_externally_removed_objs_track(self, obj, change_type == NM_PLATFORM_SIGNAL_REMOVED); + _obj_states_externally_removed_track(self, obj, change_type != NM_PLATFORM_SIGNAL_REMOVED); default: break; } @@ -864,146 +1218,6 @@ _nm_l3cfg_notify_platform_change(NML3Cfg * self, /*****************************************************************************/ -typedef struct { - GObject * target_obj; - const GParamSpec * target_property; - NML3CfgPropertyEmitType emit_type; -} PropertyEmitData; - -static void -_property_emit_notify(NML3Cfg *self, NML3CfgPropertyEmitType emit_type) -{ - gs_free PropertyEmitData *collected_heap = NULL; - PropertyEmitData * collected = NULL; - PropertyEmitData * emit_data; - guint num; - guint i; - guint j; - - if (!self->priv.p->property_emit_list) - return; - - num = 0; - emit_data = &g_array_index(self->priv.p->property_emit_list, PropertyEmitData, 0); - for (i = 0; i < self->priv.p->property_emit_list->len; i++, emit_data++) { - if (emit_data->emit_type == emit_type) { - collected = emit_data; - num++; - } - } - - if (num == 0) - return; - - if (num == 1) { - g_object_notify_by_pspec(collected->target_obj, (GParamSpec *) collected->target_property); - return; - } - - if (num < 300u / sizeof(*collected)) - collected = g_alloca(sizeof(PropertyEmitData) * num); - else { - collected_heap = g_new(PropertyEmitData, num); - collected = collected_heap; - } - - emit_data = &g_array_index(self->priv.p->property_emit_list, PropertyEmitData, 0); - for (i = 0, j = 0; i < self->priv.p->property_emit_list->len; i++, emit_data++) { - if (emit_data->emit_type == emit_type) { - collected[j++] = *emit_data; - g_object_ref(collected->target_obj); - } - } - - nm_assert(j == num); - - for (i = 0; i < num; i++) { - g_object_notify_by_pspec(collected[i].target_obj, - (GParamSpec *) collected[i].target_property); - if (i > 0) - g_object_unref(collected[i].target_obj); - } -} - -void -nm_l3cfg_property_emit_register(NML3Cfg * self, - GObject * target_obj, - const GParamSpec * target_property, - NML3CfgPropertyEmitType emit_type) -{ - PropertyEmitData *emit_data; - guint i; - - nm_assert(NM_IS_L3CFG(self)); - nm_assert(G_IS_OBJECT(target_obj)); - nm_assert(target_property); - nm_assert(NM_IN_SET(emit_type, - NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE, - NM_L3CFG_PROPERTY_EMIT_TYPE_IP6_ROUTE)); - nm_assert(target_property - == nm_g_object_class_find_property_from_gtype(G_OBJECT_TYPE(target_obj), - target_property->name)); - - if (!self->priv.p->property_emit_list) - self->priv.p->property_emit_list = g_array_new(FALSE, FALSE, sizeof(PropertyEmitData)); - else { - emit_data = &g_array_index(self->priv.p->property_emit_list, PropertyEmitData, 0); - for (i = 0; i < self->priv.p->property_emit_list->len; i++, emit_data++) { - if (emit_data->target_obj != target_obj - || emit_data->target_property != target_property) - continue; - nm_assert(emit_data->emit_type == emit_type); - emit_data->emit_type = emit_type; - return; - } - } - - emit_data = nm_g_array_append_new(self->priv.p->property_emit_list, PropertyEmitData); - *emit_data = (PropertyEmitData){ - .target_obj = target_obj, - .target_property = target_property, - .emit_type = emit_type, - }; -} - -void -nm_l3cfg_property_emit_unregister(NML3Cfg * self, - GObject * target_obj, - const GParamSpec *target_property) -{ - PropertyEmitData *emit_data; - guint i; - - nm_assert(NM_IS_L3CFG(self)); - nm_assert(G_IS_OBJECT(target_obj)); - nm_assert(!target_property - || target_property - == nm_g_object_class_find_property_from_gtype(G_OBJECT_TYPE(target_obj), - target_property->name)); - - if (!self->priv.p->property_emit_list) - return; - - for (i = self->priv.p->property_emit_list->len; i > 0; i--) { - emit_data = &g_array_index(self->priv.p->property_emit_list, PropertyEmitData, i); - - if (emit_data->target_obj != target_obj) - continue; - if (target_property && emit_data->target_property != target_property) - continue; - - g_array_remove_index_fast(self->priv.p->property_emit_list, i); - - if (target_property) { - /* if a target-property is given, we don't have another entry in - * the list. */ - return; - } - } -} - -/*****************************************************************************/ - gboolean nm_l3cfg_get_acd_is_pending(NML3Cfg *self) { @@ -1012,12 +1226,6 @@ nm_l3cfg_get_acd_is_pending(NML3Cfg *self) return self->priv.p->acd_is_pending; } -static gboolean -_acd_track_data_is_not_dirty(const NML3AcdAddrTrackInfo *acd_track) -{ - return acd_track && !acd_track->_priv.acd_dirty_track; -} - static void _acd_track_data_clear(NML3AcdAddrTrackInfo *acd_track) { @@ -1044,7 +1252,7 @@ _acd_data_collect_tracks_data(const AcdData * acd_data, guint32 * out_best_acd_timeout_msec, NML3AcdDefendType *out_best_acd_defend_type) { - NML3AcdDefendType best_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_NONE; + NML3AcdDefendType best_acd_defend_type = _NM_L3_ACD_DEFEND_TYPE_NONE; guint32 best_acd_timeout_msec = G_MAXUINT32; guint n = 0; guint i; @@ -1063,7 +1271,7 @@ _acd_data_collect_tracks_data(const AcdData * acd_data, best_acd_defend_type = acd_track->_priv.acd_defend_type_track; } - nm_assert(n == 0 || best_acd_defend_type > NM_L3_ACD_DEFEND_TYPE_NONE); + nm_assert(n == 0 || best_acd_defend_type > _NM_L3_ACD_DEFEND_TYPE_NONE); nm_assert(best_acd_defend_type <= NM_L3_ACD_DEFEND_TYPE_ALWAYS); NM_SET_OUT(out_best_acd_timeout_msec, n > 0 ? best_acd_timeout_msec : 0u); @@ -1136,9 +1344,9 @@ _l3_acd_nacd_event_down_timeout_cb(gpointer user_data) static gboolean _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) { - NML3Cfg *self = user_data; - gboolean success = FALSE; - int r; + gs_unref_object NML3Cfg *self = g_object_ref(user_data); + gboolean success = FALSE; + int r; nm_assert(NM_IS_L3CFG(self)); nm_assert(self->priv.p->nacd); @@ -1155,6 +1363,13 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) AcdData * acd_data; NAcdEvent * event; + if (!self->priv.p->nacd) { + /* In the loop we emit signals, where *anything* might happen. + * Check that we still have the nacd instance. */ + success = TRUE; + goto out; + } + r = n_acd_pop_event(self->priv.p->nacd, &event); if (r) { _LOGT("acd: pop-event failed with error %d", r); @@ -1286,7 +1501,7 @@ _l3_acd_nacd_instance_reset(NML3Cfg *self, NMTernary start_timer, gboolean acd_d switch (start_timer) { case NM_TERNARY_FALSE: _l3_changed_configs_set_dirty(self); - nm_l3cfg_commit_on_idle_schedule(self); + nm_l3cfg_commit_on_idle_schedule(self, NM_L3_CFG_COMMIT_TYPE_AUTO); break; case NM_TERNARY_TRUE: self->priv.p->nacd_instance_ensure_retry = @@ -1527,8 +1742,8 @@ _l3_acd_data_add(NML3Cfg * self, .n_track_infos_alloc = 0, .acd_event_notify_lst = C_LIST_INIT(acd_data->acd_event_notify_lst), .probing_timestamp_msec = 0, - .acd_defend_type_desired = NM_L3_ACD_DEFEND_TYPE_NONE, - .acd_defend_type_current = NM_L3_ACD_DEFEND_TYPE_NONE, + .acd_defend_type_desired = _NM_L3_ACD_DEFEND_TYPE_NONE, + .acd_defend_type_current = _NM_L3_ACD_DEFEND_TYPE_NONE, .acd_defend_type_is_active = FALSE, }; c_list_link_tail(&self->priv.p->acd_lst_head, &acd_data->acd_lst); @@ -1794,7 +2009,7 @@ _nm_printf(5, 6) static void _l3_acd_data_state_set_full(NML3Cfg * self, /* The availability of an address just changed (and we are instructed to * trigger a new commit). Do it. */ _l3_changed_configs_set_dirty(self); - nm_l3cfg_commit_on_idle_schedule(self); + nm_l3cfg_commit_on_idle_schedule(self, NM_L3_CFG_COMMIT_TYPE_AUTO); } } @@ -2464,7 +2679,7 @@ handle_start_defending: ACD_STATE_CHANGE_MODE_INIT_REAPPLY, ACD_STATE_CHANGE_MODE_POST_COMMIT)); - nm_assert(acd_data->acd_defend_type_desired > NM_L3_ACD_DEFEND_TYPE_NONE); + nm_assert(acd_data->acd_defend_type_desired > _NM_L3_ACD_DEFEND_TYPE_NONE); nm_assert(acd_data->acd_defend_type_desired <= NM_L3_ACD_DEFEND_TYPE_ALWAYS); if (acd_data->acd_defend_type_desired != acd_data->acd_defend_type_current) { @@ -2570,33 +2785,163 @@ nm_l3cfg_get_acd_addr_info(NML3Cfg *self, in_addr_t addr) /*****************************************************************************/ +gboolean +nm_l3cfg_check_ready(NML3Cfg * self, + const NML3ConfigData * l3cd, + int addr_family, + NML3CfgCheckReadyFlags flags, + gboolean * acd_used) +{ + NMDedupMultiIter iter; + const NMPObject *obj; + + nm_assert(NM_IS_L3CFG(self)); + nm_assert_addr_family_or_unspec(addr_family); + + NM_SET_OUT(acd_used, FALSE); + + if (!l3cd) + return TRUE; + + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET) + && NM_FLAGS_HAS(flags, NM_L3CFG_CHECK_READY_FLAGS_IP4_ACD_READY)) { + gboolean pending = FALSE; + + nm_l3_config_data_iter_obj_for_each (&iter, l3cd, &obj, NMP_OBJECT_TYPE_IP4_ADDRESS) { + const NML3AcdAddrInfo *addr_info; + + addr_info = nm_l3cfg_get_acd_addr_info(self, NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address); + if (!addr_info) { + /* We don't track the this address? That's odd. Not ready. */ + pending = TRUE; + } else { + if (addr_info->state <= NM_L3_ACD_ADDR_STATE_PROBING) { + /* Still probing. Not ready. */ + pending = TRUE; + } else if (addr_info->state == NM_L3_ACD_ADDR_STATE_USED) { + NM_SET_OUT(acd_used, TRUE); + } + } + /* we only care that we don't have ACD still pending. Otherwise we are ready, + * including if we have no addr_info about this address or the address is in use. */ + } + if (pending) + return FALSE; + } + + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6) + && NM_FLAGS_HAS(flags, NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY)) { + nm_l3_config_data_iter_obj_for_each (&iter, l3cd, &obj, NMP_OBJECT_TYPE_IP6_ADDRESS) { + ObjStateData *obj_state; + + obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &obj); + + if (!obj_state) { + /* Hm, we don't track this object? That is odd. Not ready. */ + return FALSE; + } + + if (!obj_state->os_nm_configured && !obj_state->os_plobj) { + /* We didn't (yet) configure this address and it also is not in platform. + * Not ready. */ + return FALSE; + } + + if (obj_state->os_plobj + && NM_FLAGS_HAS(NMP_OBJECT_CAST_IP6_ADDRESS(obj_state->os_plobj)->n_ifa_flags, + IFA_F_TENTATIVE)) { + /* The address is configured in kernel, but still tentative. Not ready. */ + return FALSE; + } + + /* This address is ready. Even if it is not (not anymore) configured in kernel (as + * indicated by obj_state->os_plobj). We apparently did configure it once, and + * it's no longer tentative. This address are good. */ + } + } + + return TRUE; +} + +/*****************************************************************************/ + static gboolean _l3_commit_on_idle_cb(gpointer user_data) { - NML3Cfg *self = user_data; + _nm_unused gs_unref_object NML3Cfg *self_keep_alive = NULL; + NML3Cfg * self = user_data; + NML3CfgCommitType commit_type; + + commit_type = self->priv.p->commit_on_idle_type; + + if (nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source)) + self_keep_alive = self; + else + nm_assert_not_reached(); - nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source); + self->priv.p->commit_on_idle_type = NM_L3_CFG_COMMIT_TYPE_AUTO; - _LOGT("commit on idle"); - _l3_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO, TRUE); + _l3_commit(self, commit_type, TRUE); return G_SOURCE_REMOVE; } +/* DOC(l3cfg:commit-type): + * + * Usually we don't want to call the synchronous nm_l3cfg_commit(), because + * that has side effects and might not be safe to do (depending on the current + * circumstances in which commit is called). The usually proper thing to do + * is schedule a commit on an idle handler. Use this function. + * + * During commit, the actually used commit-type (that is, the level of "how much" + * will be synced) is determined by users who register their desired commit + * type via nm_l3cfg_commit_type_register(), where always the "maxium" is used. + * + * nm_l3cfg_commit() and nm_l3cfg_commit_on_idle_schedule() also accept an additional + * commit_type argument. This acts like a one-shot registration. + */ gboolean -nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self) +nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self, NML3CfgCommitType commit_type) { + char sbuf_commit_type[50]; + nm_assert(NM_IS_L3CFG(self)); + nm_assert(NM_IN_SET(commit_type, + NM_L3_CFG_COMMIT_TYPE_AUTO, + NM_L3_CFG_COMMIT_TYPE_ASSUME, + NM_L3_CFG_COMMIT_TYPE_UPDATE, + NM_L3_CFG_COMMIT_TYPE_REAPPLY)); - if (self->priv.p->commit_on_idle_source) + if (self->priv.p->commit_on_idle_source) { + if (self->priv.p->commit_on_idle_type < commit_type) { + /* For multiple calls, we collect the maximum "commit-type". */ + _LOGT("commit on idle (scheduled) (update to %s)", + _l3_cfg_commit_type_to_string(commit_type, + sbuf_commit_type, + sizeof(sbuf_commit_type))); + self->priv.p->commit_on_idle_type = commit_type; + } return FALSE; + } + + _LOGT("commit on idle (scheduled) (%s)", + _l3_cfg_commit_type_to_string(commit_type, sbuf_commit_type, sizeof(sbuf_commit_type))); + self->priv.p->commit_on_idle_source = nm_g_idle_add_source(_l3_commit_on_idle_cb, self); + self->priv.p->commit_on_idle_type = commit_type; + + /* While we have an idle update scheduled, we need to keep the instance alive. */ + g_object_ref(self); - _LOGT("commit on idle (scheduled)"); - self->priv.p->commit_on_idle_source = - nm_g_idle_source_new(G_PRIORITY_DEFAULT, _l3_commit_on_idle_cb, self, NULL); - g_source_attach(self->priv.p->commit_on_idle_source, NULL); return TRUE; } +gboolean +nm_l3cfg_commit_on_idle_is_scheduled(NML3Cfg *self) +{ + nm_assert(NM_IS_L3CFG(self)); + + return !!(self->priv.p->commit_on_idle_source); +} + /*****************************************************************************/ #define _l3_config_datas_at(l3_config_datas, idx) \ @@ -2695,8 +3040,11 @@ nm_l3cfg_add_config(NML3Cfg * self, guint32 default_route_metric_6, guint32 default_route_penalty_4, guint32 default_route_penalty_6, + int default_dns_priority_4, + int default_dns_priority_6, NML3AcdDefendType acd_defend_type, guint32 acd_timeout_msec, + NML3CfgConfigFlags config_flags, NML3ConfigMergeFlags merge_flags) { L3ConfigData *l3_config_data; @@ -2761,6 +3109,7 @@ nm_l3cfg_add_config(NML3Cfg * self, *l3_config_data = (L3ConfigData){ .tag_confdata = tag, .l3cd = nm_l3_config_data_ref_and_seal(l3cd), + .config_flags = config_flags, .merge_flags = merge_flags, .default_route_table_4 = default_route_table_4, .default_route_table_6 = default_route_table_6, @@ -2768,6 +3117,8 @@ nm_l3cfg_add_config(NML3Cfg * self, .default_route_metric_6 = default_route_metric_6, .default_route_penalty_4 = default_route_penalty_4, .default_route_penalty_6 = default_route_penalty_6, + .default_dns_priority_4 = default_dns_priority_4, + .default_dns_priority_6 = default_dns_priority_6, .acd_defend_type_confdata = acd_defend_type, .acd_timeout_msec_confdata = acd_timeout_msec, .priority_confdata = priority, @@ -2784,6 +3135,10 @@ nm_l3cfg_add_config(NML3Cfg * self, l3_config_data->priority_confdata = priority; changed = TRUE; } + if (l3_config_data->config_flags != config_flags) { + l3_config_data->config_flags = config_flags; + changed = TRUE; + } if (l3_config_data->merge_flags != merge_flags) { l3_config_data->merge_flags = merge_flags; changed = TRUE; @@ -2812,6 +3167,14 @@ nm_l3cfg_add_config(NML3Cfg * self, l3_config_data->default_route_penalty_6 = default_route_penalty_6; changed = TRUE; } + if (l3_config_data->default_dns_priority_4 != default_dns_priority_4) { + l3_config_data->default_dns_priority_4 = default_dns_priority_4; + changed = TRUE; + } + if (l3_config_data->default_dns_priority_6 != default_dns_priority_6) { + l3_config_data->default_dns_priority_6 = default_dns_priority_6; + changed = TRUE; + } if (l3_config_data->acd_defend_type_confdata != acd_defend_type) { l3_config_data->acd_defend_type_confdata = acd_defend_type; changed = TRUE; @@ -2879,17 +3242,23 @@ _l3cfg_remove_config(NML3Cfg * self, } gboolean -nm_l3cfg_remove_config(NML3Cfg *self, gconstpointer tag, const NML3ConfigData *ifcfg) +nm_l3cfg_remove_config(NML3Cfg *self, gconstpointer tag, const NML3ConfigData *l3cd) { - nm_assert(ifcfg); + nm_assert(l3cd); + + return _l3cfg_remove_config(self, tag, FALSE, l3cd); +} - return _l3cfg_remove_config(self, tag, FALSE, ifcfg); +gboolean +nm_l3cfg_remove_config_all(NML3Cfg *self, gconstpointer tag) +{ + return _l3cfg_remove_config(self, tag, FALSE, NULL); } gboolean -nm_l3cfg_remove_config_all(NML3Cfg *self, gconstpointer tag, gboolean only_dirty) +nm_l3cfg_remove_config_all_dirty(NML3Cfg *self, gconstpointer tag) { - return _l3cfg_remove_config(self, tag, only_dirty, NULL); + return _l3cfg_remove_config(self, tag, TRUE, NULL); } /*****************************************************************************/ @@ -2897,13 +3266,15 @@ nm_l3cfg_remove_config_all(NML3Cfg *self, gconstpointer tag, gboolean only_dirty typedef struct { NML3Cfg * self; gconstpointer tag; + bool assume_config_once; + bool to_commit; } L3ConfigMergeHookAddObjData; static gboolean -_l3_hook_add_addr_cb(const NML3ConfigData *l3cd, - const NMPObject * obj, - NMTernary * out_ip4acd_not_ready, - gpointer user_data) +_l3_hook_add_obj_cb(const NML3ConfigData * l3cd, + const NMPObject * obj, + NML3ConfigMergeHookResult *hook_result, + gpointer user_data) { const L3ConfigMergeHookAddObjData *hook_data = user_data; NML3Cfg * self = hook_data->self; @@ -2911,40 +3282,68 @@ _l3_hook_add_addr_cb(const NML3ConfigData *l3cd, in_addr_t addr; gboolean acd_bad = FALSE; - nm_assert(out_ip4acd_not_ready && *out_ip4acd_not_ready == NM_TERNARY_DEFAULT); + nm_assert(obj); + nm_assert(hook_result); + nm_assert(hook_result->ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT); + nm_assert(hook_result->assume_config_once == NM_OPTION_BOOL_DEFAULT); - if (NMP_OBJECT_GET_TYPE(obj) != NMP_OBJECT_TYPE_IP4_ADDRESS) - return TRUE; + hook_result->assume_config_once = hook_data->assume_config_once; - addr = NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address; + switch (NMP_OBJECT_GET_TYPE(obj)) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: - if (ACD_ADDR_SKIP(addr)) - goto out; + addr = NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address; - acd_data = _l3_acd_data_find(self, addr); + if (ACD_ADDR_SKIP(addr)) + goto out_ip4_address; - if (!acd_data) { - /* we don't yet track an ACD state for this address. That can only - * happend during _l3cfg_update_combined_config() with !to_commit, - * where we didn't update the ACD state. - * - * This means, unless you actually commit, nm_l3cfg_get_combined_l3cd(self, get_commited = FALSE) - * won't consider IPv4 addresses ready, that have no known ACD state yet. */ - nm_assert(self->priv.p->changed_configs_acd_state); - acd_bad = TRUE; - goto out; - } + acd_data = _l3_acd_data_find(self, addr); - nm_assert( - _acd_track_data_is_not_dirty(_acd_data_find_track(acd_data, l3cd, obj, hook_data->tag))); - if (!NM_IN_SET(acd_data->info.state, - NM_L3_ACD_ADDR_STATE_READY, - NM_L3_ACD_ADDR_STATE_DEFENDING)) - acd_bad = TRUE; + if (!hook_data->to_commit) { + nm_assert(self->priv.p->changed_configs_acd_state); + /* We don't do an actual commit in _l3cfg_update_combined_config(). That means our acd-data + * is not up to date. Check whether we have no acd_data ready, and if not, consider the address + * as not ready. It cannot be ready until the next commit starts ACD. */ + if (!acd_data) { + acd_bad = TRUE; + goto out_ip4_address; + } + nm_assert(({ + NML3AcdAddrTrackInfo *_ti = + _acd_data_find_track(acd_data, l3cd, obj, hook_data->tag); -out: - *out_ip4acd_not_ready = acd_bad ? NM_TERNARY_TRUE : NM_TERNARY_FALSE; - return TRUE; + !_ti || _ti->_priv.acd_dirty_track; + })); + } else { + /* If we commit, we called _l3_acd_data_add_all(), thus our acd_data must be present + * and not dirty. */ + nm_assert(({ + NML3AcdAddrTrackInfo *_ti = + _acd_data_find_track(acd_data, l3cd, obj, hook_data->tag); + + _ti && !_ti->_priv.acd_dirty_track; + })); + } + + if (!NM_IN_SET(acd_data->info.state, + NM_L3_ACD_ADDR_STATE_READY, + NM_L3_ACD_ADDR_STATE_DEFENDING)) { + acd_bad = TRUE; + goto out_ip4_address; + } + +out_ip4_address: + hook_result->ip4acd_not_ready = acd_bad ? NM_OPTION_BOOL_TRUE : NM_OPTION_BOOL_FALSE; + return TRUE; + + default: + nm_assert_not_reached(); + /* fall-through */ + case NMP_OBJECT_TYPE_IP6_ADDRESS: + case NMP_OBJECT_TYPE_IP4_ROUTE: + case NMP_OBJECT_TYPE_IP6_ROUTE: + return TRUE; + } } static void @@ -3007,29 +3406,54 @@ _l3cfg_update_combined_config(NML3Cfg * self, if (l3_config_datas_len > 0) { L3ConfigMergeHookAddObjData hook_data = { - .self = self, + .self = self, + .to_commit = to_commit, }; l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(self->priv.platform), - self->priv.ifindex); + self->priv.ifindex, + NM_IP_CONFIG_SOURCE_UNKNOWN); for (i = 0; i < l3_config_datas_len; i++) { const L3ConfigData *l3cd_data = l3_config_datas_arr[i]; - if (NM_FLAGS_HAS(l3cd_data->merge_flags, NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD)) + if (NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD)) continue; hook_data.tag = l3cd_data->tag_confdata; + hook_data.assume_config_once = + NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE); + nm_l3_config_data_merge(l3cd, l3cd_data->l3cd, l3cd_data->merge_flags, l3cd_data->default_route_table_x, l3cd_data->default_route_metric_x, l3cd_data->default_route_penalty_x, - _l3_hook_add_addr_cb, + l3cd_data->default_dns_priority_x, + _l3_hook_add_obj_cb, &hook_data); } + for (i = 0; i < l3_config_datas_len; i++) { + const L3ConfigData *l3cd_data = l3_config_datas_arr[i]; + int IS_IPv4; + + if (NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD)) + continue; + + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + nm_l3_config_data_add_dependent_device_routes( + l3cd, + IS_IPv4 ? AF_INET : AF_INET6, + l3cd_data->default_route_table_x[IS_IPv4], + l3cd_data->default_route_metric_x[IS_IPv4], + l3cd_data->l3cd); + } + } + + nm_l3_config_data_add_dependent_onlink_routes(l3cd, AF_UNSPEC); + nm_assert(l3cd); nm_assert(nm_l3_config_data_get_ifindex(l3cd) == self->priv.ifindex); @@ -3060,6 +3484,8 @@ out: nm_l3_config_data_ref(self->priv.p->combined_l3cd_merged); commited_changed = TRUE; + _obj_states_update_all(self); + _nm_l3cfg_emit_signal_notify_l3cd_changed(self, l3cd_commited_old, self->priv.p->combined_l3cd_commited, @@ -3095,75 +3521,45 @@ out: /*****************************************************************************/ -typedef struct { - const NMPObject *obj; - gint64 timestamp_msec; - bool dirty; -} RoutesTemporaryNotAvailableData; - -static void -_routes_temporary_not_available_data_free(gpointer user_data) -{ - RoutesTemporaryNotAvailableData *data = user_data; - - nmp_object_unref(data->obj); - nm_g_slice_free(data); -} - -#define ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC ((gint64) 20000) - static gboolean _routes_temporary_not_available_timeout(gpointer user_data) { - RoutesTemporaryNotAvailableData *data; - NML3Cfg * self = NM_L3CFG(user_data); - GHashTableIter iter; - gint64 expiry_threshold_msec; - gboolean any_expired = FALSE; - gint64 now_msec; - gint64 oldest_msec; + NML3Cfg * self = NM_L3CFG(user_data); + ObjStateData *obj_state; + gint64 now_msec; + gint64 expiry_msec; - self->priv.p->routes_temporary_not_available_id = 0; + nm_clear_g_source_inst(&self->priv.p->obj_state_temporary_not_available_timeout_source); - if (!self->priv.p->routes_temporary_not_available_hash) - return G_SOURCE_REMOVE; + obj_state = c_list_first_entry(&self->priv.p->obj_state_temporary_not_available_lst_head, + ObjStateData, + os_temporary_not_available_lst); - /* we check the timeouts again. That is, because we allow to remove - * entries from routes_temporary_not_available_hash, without rescheduling - * out timeouts. */ + if (!obj_state) + return G_SOURCE_CONTINUE; now_msec = nm_utils_get_monotonic_timestamp_msec(); - expiry_threshold_msec = now_msec - ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC; - oldest_msec = G_MAXINT64; + expiry_msec = obj_state->os_temporary_not_available_timestamp_msec + + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC; - g_hash_table_iter_init(&iter, self->priv.p->routes_temporary_not_available_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &data, NULL)) { - if (data->timestamp_msec >= expiry_threshold_msec) { - any_expired = TRUE; - break; - } - if (data->timestamp_msec < oldest_msec) - oldest_msec = data->timestamp_msec; - } - - if (any_expired) { - /* a route expired. We emit a signal, but we don't schedule it again. That will - * only happen if the user calls nm_l3cfg_commit() again. */ - _nm_l3cfg_emit_signal_notify_simple( - self, - NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED); - return G_SOURCE_REMOVE; + if (now_msec < expiry_msec) { + /* the timeout is not yet reached. Restart the timer... */ + self->priv.p->obj_state_temporary_not_available_timeout_source = + nm_g_timeout_add_source(expiry_msec - now_msec, + _routes_temporary_not_available_timeout, + self); + return G_SOURCE_CONTINUE; } - if (oldest_msec != G_MAXINT64) { - /* we have a timeout still. Reschedule. */ - self->priv.p->routes_temporary_not_available_id = - g_timeout_add(oldest_msec + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC - now_msec, - _routes_temporary_not_available_timeout, - self); - } - return G_SOURCE_REMOVE; + /* One (or several) routes expired. We emit a signal, but we don't schedule it again. + * We expect the callers to commit again, which will one last time try to configure + * the route. If that again fails, we detect the timeout, log a warning and don't + * track the object as not temporary-not-available anymore. */ + _nm_l3cfg_emit_signal_notify_simple( + self, + NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED); + return G_SOURCE_CONTINUE; } static gboolean @@ -3171,14 +3567,15 @@ _routes_temporary_not_available_update(NML3Cfg * self, int addr_family, GPtrArray *routes_temporary_not_available_arr) { - RoutesTemporaryNotAvailableData *data; - GHashTableIter iter; - gint64 oldest_msec; - gint64 now_msec; - gboolean prune_all = FALSE; - gboolean success = TRUE; - guint i; - + ObjStateData * obj_state; + ObjStateData * obj_state_safe; + gint64 now_msec; + gboolean prune_all = FALSE; + gboolean success = TRUE; + guint i; + const NMPClass *klass; + + klass = nmp_class_from_type(NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family))); now_msec = nm_utils_get_monotonic_timestamp_msec(); if (nm_g_ptr_array_len(routes_temporary_not_available_arr) <= 0) { @@ -3186,36 +3583,45 @@ _routes_temporary_not_available_update(NML3Cfg * self, goto out_prune; } - if (self->priv.p->routes_temporary_not_available_hash) { - g_hash_table_iter_init(&iter, self->priv.p->routes_temporary_not_available_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &data, NULL)) { - if (NMP_OBJECT_GET_ADDR_FAMILY(data->obj) == addr_family) - data->dirty = TRUE; + c_list_for_each_entry (obj_state, + &self->priv.p->obj_state_temporary_not_available_lst_head, + os_temporary_not_available_lst) { + if (NMP_OBJECT_GET_CLASS(obj_state->obj) == klass) { + nm_assert(obj_state->os_temporary_not_available_timestamp_msec > 0); + obj_state->os_tna_dirty = TRUE; } - } else { - self->priv.p->routes_temporary_not_available_hash = - g_hash_table_new_full(nmp_object_indirect_id_hash, - nmp_object_indirect_id_equal, - _routes_temporary_not_available_data_free, - NULL); } for (i = 0; i < routes_temporary_not_available_arr->len; i++) { const NMPObject *o = routes_temporary_not_available_arr->pdata[i]; - char sbuf[1024]; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family))); - data = g_hash_table_lookup(self->priv.p->routes_temporary_not_available_hash, &o); + obj_state = g_hash_table_lookup(self->priv.p->obj_state_hash, &o); - if (data) { - if (!data->dirty) - continue; + if (!obj_state) { + /* Hm? We don't track this object? Very odd, a bug? */ + nm_assert_not_reached(); + continue; + } - nm_assert(data->timestamp_msec > 0 && data->timestamp_msec <= now_msec); + if (obj_state->os_temporary_not_available_timestamp_msec > 0) { + nm_assert(obj_state->os_temporary_not_available_timestamp_msec > 0 + && obj_state->os_temporary_not_available_timestamp_msec <= now_msec); - if (now_msec > data->timestamp_msec + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC) { - /* timeout. Could not add this address. */ + if (!obj_state->os_tna_dirty) { + /* Odd, this only can happen if routes_temporary_not_available_arr contains duplicates. + * It should not. */ + nm_assert_not_reached(); + continue; + } + + if (now_msec > obj_state->os_temporary_not_available_timestamp_msec + + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC) { + /* Timeout. Could not add this address. + * + * For now, keep it obj_state->os_tna_dirty and prune it below. */ _LOGW("failure to add IPv%c route: %s", nm_utils_addr_family_to_char(addr_family), nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); @@ -3223,7 +3629,7 @@ _routes_temporary_not_available_update(NML3Cfg * self, continue; } - data->dirty = FALSE; + obj_state->os_tna_dirty = FALSE; continue; } @@ -3231,47 +3637,229 @@ _routes_temporary_not_available_update(NML3Cfg * self, nm_utils_addr_family_to_char(addr_family), nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); - data = g_slice_new(RoutesTemporaryNotAvailableData); - *data = (RoutesTemporaryNotAvailableData){ - .obj = nmp_object_ref(o), - .timestamp_msec = now_msec, - .dirty = FALSE, - }; - g_hash_table_add(self->priv.p->routes_temporary_not_available_hash, data); + obj_state->os_tna_dirty = FALSE; + obj_state->os_temporary_not_available_timestamp_msec = now_msec; + c_list_link_tail(&self->priv.p->obj_state_temporary_not_available_lst_head, + &obj_state->os_temporary_not_available_lst); } out_prune: - oldest_msec = G_MAXINT64; - - if (self->priv.p->routes_temporary_not_available_hash) { - g_hash_table_iter_init(&iter, self->priv.p->routes_temporary_not_available_hash); - while (g_hash_table_iter_next(&iter, (gpointer *) &data, NULL)) { - nm_assert(NMP_OBJECT_GET_ADDR_FAMILY(data->obj) == addr_family || !data->dirty); - if (!prune_all && !data->dirty) { - if (data->timestamp_msec < oldest_msec) - oldest_msec = data->timestamp_msec; - continue; + c_list_for_each_entry_safe (obj_state, + obj_state_safe, + &self->priv.p->obj_state_temporary_not_available_lst_head, + os_temporary_not_available_lst) { + if (prune_all || obj_state->os_tna_dirty) { + if (NMP_OBJECT_GET_CLASS(obj_state->obj) == klass) { + obj_state->os_temporary_not_available_timestamp_msec = 0; + c_list_unlink(&obj_state->os_temporary_not_available_lst); } - g_hash_table_iter_remove(&iter); } - if (oldest_msec != G_MAXINT64) - nm_clear_pointer(&self->priv.p->routes_temporary_not_available_hash, - g_hash_table_unref); } - nm_clear_g_source(&self->priv.p->routes_temporary_not_available_id); - if (oldest_msec != G_MAXINT64) { - nm_assert(oldest_msec + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC < now_msec); - self->priv.p->routes_temporary_not_available_id = - g_timeout_add(oldest_msec + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC - now_msec, - _routes_temporary_not_available_timeout, - self); + nm_clear_g_source_inst(&self->priv.p->obj_state_temporary_not_available_timeout_source); + + obj_state = c_list_first_entry(&self->priv.p->obj_state_temporary_not_available_lst_head, + ObjStateData, + os_temporary_not_available_lst); + if (obj_state) { + self->priv.p->obj_state_temporary_not_available_timeout_source = + nm_g_timeout_add_source((obj_state->os_temporary_not_available_timestamp_msec + + ROUTES_TEMPORARY_NOT_AVAILABLE_MAX_AGE_MSEC - now_msec), + _routes_temporary_not_available_timeout, + self); } return success; } /*****************************************************************************/ +static const char * +ip6_privacy_to_str(NMSettingIP6ConfigPrivacy ip6_privacy) +{ + switch (ip6_privacy) { + case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: + return "0"; + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: + return "1"; + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: + return "2"; + case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: + break; + } + return nm_assert_unreachable_val("0"); +} + +static void +_l3_commit_ndisc_params(NML3Cfg *self, NML3CfgCommitType commit_type) +{ + const NML3ConfigData *l3cd; + gboolean retrans_set = FALSE; + gboolean reachable_set = FALSE; + gboolean hop_limit_set = FALSE; + guint32 reachable = 0; + guint32 retrans = 0; + int hop_limit = 0; + const char * ifname; + + if (commit_type < NM_L3_CFG_COMMIT_TYPE_UPDATE) { + self->priv.p->ndisc_reachable_time_msec_set = FALSE; + self->priv.p->ndisc_retrans_timer_msec_set = FALSE; + self->priv.p->ndisc_hop_limit_set = FALSE; + return; + } + + l3cd = self->priv.p->combined_l3cd_commited; + if (l3cd) { + reachable_set = nm_l3_config_data_get_ndisc_reachable_time_msec(l3cd, &reachable); + retrans_set = nm_l3_config_data_get_ndisc_retrans_timer_msec(l3cd, &retrans); + hop_limit = nm_l3_config_data_get_ndisc_hop_limit(l3cd, &hop_limit); + } + ifname = nm_l3cfg_get_ifname(self, TRUE); + + if (reachable_set + && (!self->priv.p->ndisc_reachable_time_msec_set + || self->priv.p->ndisc_reachable_time_msec != reachable)) { + self->priv.p->ndisc_reachable_time_msec = reachable; + self->priv.p->ndisc_reachable_time_msec_set = TRUE; + if (ifname) { + nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(self->priv.platform, + ifname, + reachable); + } + } + + 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_set = TRUE; + if (ifname) { + nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(self->priv.platform, ifname, retrans); + } + } + + if (hop_limit_set + && (!self->priv.p->ndisc_hop_limit_set || self->priv.p->ndisc_hop_limit != hop_limit)) { + self->priv.p->ndisc_hop_limit = hop_limit; + self->priv.p->ndisc_hop_limit_set = TRUE; + if (ifname) { + nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(self->priv.platform, + ifname, + hop_limit); + } + } + + // FIXME: restore values if necessary +} + +static void +_l3_commit_ip6_privacy(NML3Cfg *self, NML3CfgCommitType commit_type) +{ + NMSettingIP6ConfigPrivacy ip6_privacy; + NMSettingIP6ConfigPrivacy ip6_privacy_set_before; + const char * ifname; + + if (commit_type < NM_L3_CFG_COMMIT_TYPE_UPDATE) + ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + else + ip6_privacy = nm_l3_config_data_get_ip6_privacy(self->priv.p->combined_l3cd_commited); + + if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) { + if (!self->priv.p->ip6_privacy_set) { + /* Nothing to set. But do we need to reset a previous value? */ + return; + } + self->priv.p->ip6_privacy_set = FALSE; + ip6_privacy = self->priv.p->ip6_privacy_initial; + ifname = nm_l3cfg_get_ifname(self, TRUE); + _LOGT("commit-ip6-privacy: reset initial value %d (was %d)%s%s", + (int) ip6_privacy, + (int) self->priv.p->ip6_privacy_set_before, + NM_PRINT_FMT_QUOTED2(ifname, ", ifname ", ifname, " (skip, no interface)")); + if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) + return; + if (!ifname) + return; + goto set; + } + + nm_assert(NM_IN_SET(ip6_privacy, + NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR)); + + if (self->priv.p->ip6_privacy_set && self->priv.p->ip6_privacy_set_before == ip6_privacy + && commit_type < NM_L3_CFG_COMMIT_TYPE_REAPPLY) { + /* Already set. We leave this alone except during reapply. */ + return; + } + + ip6_privacy_set_before = self->priv.p->ip6_privacy_set_before; + self->priv.p->ip6_privacy_set_before = ip6_privacy; + + if (!self->priv.p->ip6_privacy_set) { + gint64 s = G_MININT64; + + self->priv.p->ip6_privacy_set = TRUE; + ifname = nm_l3cfg_get_ifname(self, TRUE); + if (ifname) { + s = nm_platform_sysctl_ip_conf_get_int_checked(self->priv.platform, + AF_INET6, + ifname, + "use_tempaddr", + 10, + G_MININT32, + G_MAXINT32, + G_MININT64); + if (s != G_MININT64) + s = NM_CLAMP(s, 0, 2); + } + switch (s) { + case 0: + self->priv.p->ip6_privacy_initial = NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED; + break; + case 1: + self->priv.p->ip6_privacy_initial = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR; + break; + case 2: + self->priv.p->ip6_privacy_initial = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR; + break; + default: + nm_assert_not_reached(); + /* fall-through */ + case G_MININT64: + self->priv.p->ip6_privacy_initial = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; + break; + } + _LOGT("commit-ip6-privacy: set value %d (initial value was %d)%s%s", + (int) ip6_privacy, + (int) self->priv.p->ip6_privacy_initial, + NM_PRINT_FMT_QUOTED2(ifname, ", ifname ", ifname, " (skip, no interface)")); + if (!ifname) + return; + /* The first time, we always set the value, and don't skip it based on what we + * read. */ + goto set; + } + + ifname = nm_l3cfg_get_ifname(self, TRUE); + _LOGT("commit-ip6-privacy: set value %d (after %d, initial value was %d)%s%s", + (int) ip6_privacy, + (int) ip6_privacy_set_before, + (int) self->priv.p->ip6_privacy_initial, + NM_PRINT_FMT_QUOTED2(ifname, ", ifname ", ifname, " (skip, no interface)")); + if (!ifname) + return; + +set: + nm_assert(ifname); + self->priv.p->ip6_privacy_set_before = ip6_privacy; + nm_platform_sysctl_ip_conf_set(self->priv.platform, + AF_INET6, + ifname, + "use_tempaddr", + ip6_privacy_to_str(ip6_privacy)); +} static gboolean _l3_commit_one(NML3Cfg * self, @@ -3303,58 +3891,35 @@ _l3_commit_one(NML3Cfg * self, nm_utils_addr_family_to_char(addr_family), _l3_cfg_commit_type_to_string(commit_type, sbuf_commit_type, sizeof(sbuf_commit_type))); - if (changed_combined_l3cd) { - /* our combined configuration changed. We may track entries in externally_removed_objs_hash, - * which are not longer to be considered by our configuration. We need to forget about them. */ - _l3cfg_externally_removed_objs_drop_unused(self); - } - - if (commit_type == NM_L3_CFG_COMMIT_TYPE_ASSUME) { - /* we need to artificially pre-populate the externally remove hash. */ - _l3cfg_externally_removed_objs_pickup(self, addr_family); - } - if (self->priv.p->combined_l3cd_commited) { - GHashTable * externally_removed_objs_hash; - NMDedupMultiFcnSelectPredicate predicate; - const NMDedupMultiHeadEntry * head_entry; - - if (commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY - && self->priv.p->externally_removed_objs_cnt_addresses_x[IS_IPv4] > 0) { - predicate = _l3cfg_externally_removed_objs_filter; - externally_removed_objs_hash = self->priv.p->externally_removed_objs_hash; - } else { - if (IS_IPv4) - predicate = _l3cfg_externally_removed_objs_filter; - else - predicate = NULL; - externally_removed_objs_hash = NULL; - } + const NMDedupMultiHeadEntry * head_entry; + const ObjStatesSyncFilterData sync_filter_data = { + .self = self, + .commit_type = commit_type, + }; + head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)); addresses = nm_dedup_multi_objs_to_ptr_array_head(head_entry, - predicate, - externally_removed_objs_hash); + _obj_states_sync_filter, + (gpointer) &sync_filter_data); - if (commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY - && self->priv.p->externally_removed_objs_cnt_routes_x[IS_IPv4] > 0) { - predicate = _l3cfg_externally_removed_objs_filter; - externally_removed_objs_hash = self->priv.p->externally_removed_objs_hash; - } else { - predicate = NULL; - externally_removed_objs_hash = NULL; - } head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)); routes = nm_dedup_multi_objs_to_ptr_array_head(head_entry, - predicate, - externally_removed_objs_hash); + _obj_states_sync_filter, + (gpointer) &sync_filter_data); route_table_sync = nm_l3_config_data_get_route_table_sync(self->priv.p->combined_l3cd_commited, addr_family); } + if (!IS_IPv4) { + _l3_commit_ip6_privacy(self, commit_type); + _l3_commit_ndisc_params(self, commit_type); + } + if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE) route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_ALL; @@ -3367,17 +3932,11 @@ _l3_commit_one(NML3Cfg * self, addr_family, self->priv.ifindex, route_table_sync); - } else if (commit_type == NM_L3_CFG_COMMIT_TYPE_UPDATE) { - addresses_prune = nm_g_ptr_array_ref(self->priv.p->last_addresses_x[IS_IPv4]); - routes_prune = nm_g_ptr_array_ref(self->priv.p->last_routes_x[IS_IPv4]); - } - - nm_g_ptr_array_set(&self->priv.p->last_addresses_x[IS_IPv4], addresses); - nm_g_ptr_array_set(&self->priv.p->last_routes_x[IS_IPv4], routes); + _obj_state_zombie_lst_prune_all(self, addr_family); + } else + _obj_state_zombie_lst_get_prune_lists(self, addr_family, &addresses_prune, &routes_prune); - /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_ip6_privacy(). */ /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_ndisc_*(). */ - /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_ip6_mtu(). */ /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_mtu(). */ nm_platform_ip_address_sync(self->priv.platform, @@ -3409,8 +3968,11 @@ _l3_commit_one(NML3Cfg * self, static void _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) { - nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; - gboolean commit_type_detected = FALSE; + _nm_unused gs_unref_object NML3Cfg *self_keep_alive = NULL; + nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; + NML3CfgCommitType commit_type_auto; + gboolean commit_type_from_auto = FALSE; + gboolean is_sticky_update = FALSE; char sbuf_ct[30]; gboolean changed_combined_l3cd; @@ -3423,44 +3985,45 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) NM_L3_CFG_COMMIT_TYPE_REAPPLY)); nm_assert(self->priv.p->commit_reentrant_count == 0); - switch (commit_type) { - case NM_L3_CFG_COMMIT_TYPE_AUTO: - /* if in "AUTO" mode we currently have commit-type "UPDATE", that - * causes also the following update to still be "UPDATE". Either - * the same commit */ - commit_type_detected = TRUE; - commit_type = nm_l3cfg_commit_type_get(self); - if (commit_type == NM_L3_CFG_COMMIT_TYPE_UPDATE) - self->priv.p->commit_type_update_sticky = TRUE; - else if (self->priv.p->commit_type_update_sticky) { + /* The actual commit type is always the maximum of what is requested + * and what is registered via nm_l3cfg_commit_type_register(), combined + * with the ad-hoc requested @commit_type argument. */ + commit_type_auto = nm_l3cfg_commit_type_get(self); + if (commit_type == NM_L3_CFG_COMMIT_TYPE_AUTO || commit_type_auto > commit_type) { + commit_type_from_auto = TRUE; + commit_type = commit_type_auto; + } + + /* Levels UPDATE and higher are sticky. That means, when do perform such a commit + * type, then the next one will at least be of level "UPDATE". The idea is + * that if the current commit adds an address, then the following needs + * to do at least "UPDATE" level to remove it again. Even if in the meantime + * the "UPDATE" is unregistered (nm_l3cfg_commit_type_unregister()). */ + if (commit_type < NM_L3_CFG_COMMIT_TYPE_UPDATE) { + if (self->priv.p->commit_type_update_sticky) { self->priv.p->commit_type_update_sticky = FALSE; commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE; + is_sticky_update = TRUE; } - break; - case NM_L3_CFG_COMMIT_TYPE_ASSUME: - break; - case NM_L3_CFG_COMMIT_TYPE_REAPPLY: - case NM_L3_CFG_COMMIT_TYPE_UPDATE: - self->priv.p->commit_type_update_sticky = FALSE; - break; - case NM_L3_CFG_COMMIT_TYPE_NONE: - break; - } + } else + self->priv.p->commit_type_update_sticky = TRUE; - _LOGT("commit %s%s%s", + _LOGT("commit %s%s%s%s", _l3_cfg_commit_type_to_string(commit_type, sbuf_ct, sizeof(sbuf_ct)), - commit_type_detected ? " (auto)" : "", + commit_type_from_auto ? " (auto)" : "", + is_sticky_update ? " (sticky-update)" : "", is_idle ? " (idle handler)" : ""); - if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE) - return; + nm_assert(commit_type > NM_L3_CFG_COMMIT_TYPE_AUTO); - self->priv.p->commit_reentrant_count++; + if (nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source)) + self_keep_alive = self; + self->priv.p->commit_on_idle_type = NM_L3_CFG_COMMIT_TYPE_AUTO; - nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source); + if (commit_type <= NM_L3_CFG_COMMIT_TYPE_NONE) + return; - if (commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY) - _l3cfg_externally_removed_objs_drop(self); + self->priv.p->commit_reentrant_count++; _l3cfg_update_combined_config(self, TRUE, @@ -3468,7 +4031,7 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) &l3cd_old, &changed_combined_l3cd); - /* FIXME(l3cfg): handle items currently not configurable in kernel. */ + _nm_l3cfg_emit_signal_notify_simple(self, NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT); _l3_commit_one(self, AF_INET, commit_type, changed_combined_l3cd, l3cd_old); _l3_commit_one(self, AF_INET6, commit_type, changed_combined_l3cd, l3cd_old); @@ -3481,6 +4044,7 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) _nm_l3cfg_emit_signal_notify_simple(self, NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT); } +/* See DOC(l3cfg:commit-type) */ void nm_l3cfg_commit(NML3Cfg *self, NML3CfgCommitType commit_type) { @@ -3508,29 +4072,39 @@ nm_l3cfg_commit_type_get(NML3Cfg *self) * @commit_type: the commit type to register * @existing_handle: instead of being a new registration, update an existing handle. * This may be %NULL, which is like having no previous registration. + * @source: the source of the commit type, for logging. * * NML3Cfg needs to know whether it is in charge of an interface (and how "much"). * By default, it is not in charge, but various users can register themself with * a certain @commit_type. The "higher" commit type is the used one when calling * nm_l3cfg_commit() with %NM_L3_CFG_COMMIT_TYPE_AUTO. * - * Returns: a handle tracking the registration, or %NULL of @commit_type + * Returns: a handle tracking the registration, or %NULL if @commit_type * is %NM_L3_CFG_COMMIT_TYPE_NONE. */ NML3CfgCommitTypeHandle * nm_l3cfg_commit_type_register(NML3Cfg * self, NML3CfgCommitType commit_type, - NML3CfgCommitTypeHandle *existing_handle) + NML3CfgCommitTypeHandle *existing_handle, + const char * source) { NML3CfgCommitTypeHandle *handle; NML3CfgCommitTypeHandle *h; gboolean linked; + NML3CfgCommitTypeHandle *ret = NULL; + char buf[64]; nm_assert(NM_IS_L3CFG(self)); nm_assert(NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_ASSUME, NM_L3_CFG_COMMIT_TYPE_UPDATE)); + + /* It would be easy (and maybe convenient) to allow that @existing_handle + * can currently be registered on another NML3Cfg instance. But then we couldn't + * do this assertion, and it seems error prone to allow arbitrary handles where + * we cannot check whether it is valid. So if @existing_handle is given, it + * must be tracked by @self (and only by @self). */ nm_assert( !existing_handle || c_list_contains(&self->priv.p->commit_type_lst_head, &existing_handle->commit_type_lst)); @@ -3538,21 +4112,24 @@ nm_l3cfg_commit_type_register(NML3Cfg * self, if (existing_handle) { if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE) { nm_l3cfg_commit_type_unregister(self, existing_handle); - return NULL; + goto out; + } + if (existing_handle->commit_type == commit_type) { + ret = existing_handle; + goto out; } - if (existing_handle->commit_type == commit_type) - return existing_handle; c_list_unlink_stale(&existing_handle->commit_type_lst); handle = existing_handle; } else { if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE) - return NULL; - handle = g_slice_new(NML3CfgCommitTypeHandle); - handle->commit_type = commit_type; + goto out; + handle = g_slice_new(NML3CfgCommitTypeHandle); if (c_list_is_empty(&self->priv.p->commit_type_lst_head)) g_object_ref(self); } + handle->commit_type = commit_type; + linked = FALSE; c_list_for_each_entry (h, &self->priv.p->commit_type_lst_head, commit_type_lst) { if (handle->commit_type >= h->commit_type) { @@ -3564,7 +4141,15 @@ nm_l3cfg_commit_type_register(NML3Cfg * self, if (!linked) c_list_link_tail(&self->priv.p->commit_type_lst_head, &handle->commit_type_lst); - return handle; + ret = handle; +out: + _LOGT("commit type register (type \"%s\", source \"%s\", existing " NM_HASH_OBFUSCATE_PTR_FMT + ") -> " NM_HASH_OBFUSCATE_PTR_FMT "", + _l3_cfg_commit_type_to_string(commit_type, buf, sizeof(buf)), + source, + NM_HASH_OBFUSCATE_PTR(existing_handle), + NM_HASH_OBFUSCATE_PTR(ret)); + return ret; } void @@ -3577,6 +4162,8 @@ nm_l3cfg_commit_type_unregister(NML3Cfg *self, NML3CfgCommitTypeHandle *handle) nm_assert(c_list_contains(&self->priv.p->commit_type_lst_head, &handle->commit_type_lst)); + _LOGT("commit type unregister " NM_HASH_OBFUSCATE_PTR_FMT "", NM_HASH_OBFUSCATE_PTR(handle)); + c_list_unlink_stale(&handle->commit_type_lst); if (c_list_is_empty(&self->priv.p->commit_type_lst_head)) g_object_unref(self); @@ -3688,7 +4275,7 @@ _nm_l3cfg_unregister_ipv4ll(NML3Cfg *self) { nm_assert(NM_IS_L3CFG(self)); - /* we don't own the refernce to "self->priv.p->ipv4ll", but + /* we don't own the reference to "self->priv.p->ipv4ll", but * when that instance gets destroyed, we get called back to * forget about it. Basically, it's like a weak pointer. */ @@ -3747,6 +4334,14 @@ nm_l3cfg_init(NML3Cfg *self) c_list_init(&self->priv.p->acd_lst_head); c_list_init(&self->priv.p->acd_event_notify_lst_head); c_list_init(&self->priv.p->commit_type_lst_head); + c_list_init(&self->priv.p->obj_state_lst_head); + c_list_init(&self->priv.p->obj_state_temporary_not_available_lst_head); + c_list_init(&self->priv.p->obj_state_zombie_lst_head); + + self->priv.p->obj_state_hash = g_hash_table_new_full(nmp_object_indirect_id_hash, + nmp_object_indirect_id_equal, + _obj_state_data_free, + NULL); } static void @@ -3786,9 +4381,7 @@ finalize(GObject *object) nm_assert(c_list_is_empty(&self->priv.p->commit_type_lst_head)); - nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source); - - nm_assert(nm_g_array_len(self->priv.p->property_emit_list) == 0u); + nm_assert(!self->priv.p->commit_on_idle_source); _l3_acd_data_prune(self, TRUE); @@ -3801,15 +4394,12 @@ finalize(GObject *object) nm_clear_g_source_inst(&self->priv.p->nacd_source); nm_clear_g_source_inst(&self->priv.p->nacd_instance_ensure_retry); - nm_clear_pointer(&self->priv.p->last_addresses_4, g_ptr_array_unref); - nm_clear_pointer(&self->priv.p->last_addresses_6, g_ptr_array_unref); - nm_clear_pointer(&self->priv.p->last_routes_4, g_ptr_array_unref); - nm_clear_pointer(&self->priv.p->last_routes_6, g_ptr_array_unref); - - nm_clear_g_source(&self->priv.p->routes_temporary_not_available_id); - nm_clear_pointer(&self->priv.p->routes_temporary_not_available_hash, g_hash_table_unref); + nm_clear_g_source_inst(&self->priv.p->obj_state_temporary_not_available_timeout_source); - nm_clear_pointer(&self->priv.p->externally_removed_objs_hash, g_hash_table_unref); + nm_clear_pointer(&self->priv.p->obj_state_hash, g_hash_table_destroy); + nm_assert(c_list_is_empty(&self->priv.p->obj_state_lst_head)); + nm_assert(c_list_is_empty(&self->priv.p->obj_state_temporary_not_available_lst_head)); + nm_assert(c_list_is_empty(&self->priv.p->obj_state_zombie_lst_head)); g_clear_object(&self->priv.netns); g_clear_object(&self->priv.platform); diff --git a/src/core/nm-l3cfg.h b/src/core/nm-l3cfg.h index 037f2178..19dec118 100644 --- a/src/core/nm-l3cfg.h +++ b/src/core/nm-l3cfg.h @@ -7,6 +7,7 @@ #include "nm-l3-config-data.h" #define NM_L3CFG_CONFIG_PRIORITY_IPV4LL 0 +#define NM_L3CFG_CONFIG_PRIORITY_IPV6LL 0 #define NM_ACD_TIMEOUT_RFC5227_MSEC 9000u #define NM_TYPE_L3CFG (nm_l3cfg_get_type()) @@ -22,12 +23,43 @@ #define NM_L3CFG_SIGNAL_NOTIFY "l3cfg-notify" typedef enum _nm_packed { - NM_L3_ACD_DEFEND_TYPE_NONE, + _NM_L3_ACD_DEFEND_TYPE_NONE, NM_L3_ACD_DEFEND_TYPE_NEVER, NM_L3_ACD_DEFEND_TYPE_ONCE, NM_L3_ACD_DEFEND_TYPE_ALWAYS, } NML3AcdDefendType; +/** + * NML3CfgConfigFlags: + * @NM_L3CFG_CONFIG_FLAGS_NONE: no flags, the default. + * @NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD: if this merge flag is set, + * the the NML3ConfigData doesn't get merged and it's information won't be + * synced. The only purpose is to run ACD on its IPv4 addresses, but + * regardless whether ACD succeeds/fails, the IP addresses won't be configured. + * The point is to run ACD first (without configuring it), and only + * commit the settings if requested. That can either happen by + * nm_l3cfg_add_config() the same NML3Cfg again (with a different + * tag), or by calling nm_l3cfg_add_config() again with this flag + * cleared (and the same tag). + * @NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE: a commit with + * %NM_L3_CFG_COMMIT_TYPE_ASSUME, means to not remove/add + * addresses that are missing/already exist. The assume mode + * is for taking over a device gracefully after restart, so + * it aims to preserve whatever was configured (or not configured). + * With this flag enabled, the first commit in assume mode will still + * add the addresses/routes. This is necessary for example with IPv6LL. + * Also while assuming a device, we want to configure things + * (like an IPv6 address), so we need to bypass the common + * "don't change" behavior. At least once. If the address/route + * is still not (no longer) configured on the subsequent + * commit, it's not getting added again. + */ +typedef enum _nm_packed { + NM_L3CFG_CONFIG_FLAGS_NONE = 0, + NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD = (1LL << 0), + NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE = (1LL << 1), +} NML3CfgConfigFlags; + typedef enum _nm_packed { NM_L3_ACD_ADDR_STATE_INIT, NM_L3_ACD_ADDR_STATE_PROBING, @@ -98,6 +130,12 @@ typedef enum { NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT, + /* emitted before the merged l3cd is committed to platform. + * + * This event also gets emitted "under unsafe circumstances". + * See NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED. */ + NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT, + /* emitted at the end of nm_l3cfg_platform_commit(). This signals also that * nm_l3cfg_is_ready() might have switched to TRUE. */ NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, @@ -105,7 +143,9 @@ typedef enum { /* NML3Cfg hooks to the NMPlatform signals for link, addresses and routes. * It re-emits the platform signal. * Contrary to NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, this even - * is re-emitted synchronously. */ + * is re-emitted synchronously. You probably want to hook to the on-idle signal, + * unless you need to catch all intermediate changes too. Note that this + * event is not re-entrant safe (so beware what you are doing). */ NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, /* NML3Cfg hooks to the NMPlatform signals for link, addresses and routes. @@ -235,6 +275,8 @@ nm_l3cfg_get_ifname(const NML3Cfg *self, gboolean get_next) return nmp_object_link_get_ifname(nm_l3cfg_get_plobj(self, get_next)); } +gboolean nm_l3cfg_is_vrf(const NML3Cfg *self); + static inline NMNetns * nm_l3cfg_get_netns(const NML3Cfg *self) { @@ -251,31 +293,12 @@ nm_l3cfg_get_platform(const NML3Cfg *self) return self->priv.platform; } -gboolean nm_l3cfg_get_acd_is_pending(NML3Cfg *self); - /*****************************************************************************/ void _nm_l3cfg_emit_signal_notify(NML3Cfg *self, const NML3ConfigNotifyData *notify_data); /*****************************************************************************/ -typedef enum { - NM_L3CFG_PROPERTY_EMIT_TYPE_ANY, - NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE, - NM_L3CFG_PROPERTY_EMIT_TYPE_IP6_ROUTE, -} NML3CfgPropertyEmitType; - -void nm_l3cfg_property_emit_register(NML3Cfg * self, - GObject * target_obj, - const GParamSpec * target_property, - NML3CfgPropertyEmitType emit_type); - -void nm_l3cfg_property_emit_unregister(NML3Cfg * self, - GObject * target_obj, - const GParamSpec *target_property); - -/*****************************************************************************/ - void nm_l3cfg_mark_config_dirty(NML3Cfg *self, gconstpointer tag, gboolean dirty); gboolean nm_l3cfg_add_config(NML3Cfg * self, @@ -289,17 +312,39 @@ gboolean nm_l3cfg_add_config(NML3Cfg * self, guint32 default_route_metric_6, guint32 default_route_penalty_4, guint32 default_route_penalty_6, + int default_dns_priority_4, + int default_dns_priority_6, NML3AcdDefendType acd_defend_type, guint32 acd_timeout_msec, + NML3CfgConfigFlags config_flags, NML3ConfigMergeFlags merge_flags); -gboolean nm_l3cfg_remove_config(NML3Cfg *self, gconstpointer tag, const NML3ConfigData *ifcfg); +gboolean nm_l3cfg_remove_config(NML3Cfg *self, gconstpointer tag, const NML3ConfigData *l3cd); -gboolean nm_l3cfg_remove_config_all(NML3Cfg *self, gconstpointer tag, gboolean only_dirty); +gboolean nm_l3cfg_remove_config_all(NML3Cfg *self, gconstpointer tag); +gboolean nm_l3cfg_remove_config_all_dirty(NML3Cfg *self, gconstpointer tag); /*****************************************************************************/ -/* The numeric values of the enum matters: higher number mean more "important". +/* DOC(l3cfg:commit-type): + * + * The major idea of NML3Cfg is that independent parties can register configuration + * (NML3ConfigData via nm_l3cfg_add_config()), and then nm_l3cfg_commit() will + * actually configure it. Usually we would not call the synchronous nm_l3cfg_commit(), + * but instead nm_l3cfg_commit_on_idle_schedule(). + * + * We have different levels of "how much" we should sync during commit. That is + * NML3CfgCommitType. Since independent parties should be able to work together, + * they can only ask for their minimal required commit-type level. That means, + * during commit we will commit with the highest level of how much one of the + * users request the commit. To request a commit level, users can call + * nm_l3cfg_commit_type_register(). nm_l3cfg_commit_on_idle_schedule() also + * accepts a one-time commit-type argument. + * + * This is related to NMDevice's sys_iface_state, which we use to control whether + * to touch/assume/manage the interface. + * + * The numeric values of the enum matters: higher number mean more "important". * E.g. "assume" tries to preserve the most settings, while "reapply" forces * all configuration to match. */ typedef enum _nm_packed { @@ -314,7 +359,10 @@ typedef enum _nm_packed { /* ASSUME means to keep any pre-existing extra routes/addresses, while * also not adding routes/addresses that are not present yet. This is to * gracefully take over after restart, where the existing IP configuration - * should not change. */ + * should not change. + * + * The flag NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE can make certain addresses/ + * routes commitable also during "assume". */ NM_L3_CFG_COMMIT_TYPE_ASSUME, /* UPDATE means to add new addresses/routes, while also removing addresses/routes @@ -331,24 +379,53 @@ typedef enum _nm_packed { void nm_l3cfg_commit(NML3Cfg *self, NML3CfgCommitType commit_type); -gboolean nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self); +gboolean nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self, NML3CfgCommitType commit_type); + +gboolean nm_l3cfg_commit_on_idle_is_scheduled(NML3Cfg *self); /*****************************************************************************/ +gboolean nm_l3cfg_get_acd_is_pending(NML3Cfg *self); + const NML3AcdAddrInfo *nm_l3cfg_get_acd_addr_info(NML3Cfg *self, in_addr_t addr); /*****************************************************************************/ +typedef enum { + NM_L3CFG_CHECK_READY_FLAGS_NONE = 0, + NM_L3CFG_CHECK_READY_FLAGS_IP4_ACD_READY = (1ull << 0), + NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY = (1ull << 1), +} NML3CfgCheckReadyFlags; + +gboolean nm_l3cfg_check_ready(NML3Cfg * self, + const NML3ConfigData * l3cd, + int addr_family, + NML3CfgCheckReadyFlags flags, + gboolean * acd_used); + +/*****************************************************************************/ + NML3CfgCommitType nm_l3cfg_commit_type_get(NML3Cfg *self); typedef struct _NML3CfgCommitTypeHandle NML3CfgCommitTypeHandle; NML3CfgCommitTypeHandle *nm_l3cfg_commit_type_register(NML3Cfg * self, NML3CfgCommitType commit_type, - NML3CfgCommitTypeHandle *existing_handle); + NML3CfgCommitTypeHandle *existing_handle, + const char * source); void nm_l3cfg_commit_type_unregister(NML3Cfg *self, NML3CfgCommitTypeHandle *handle); +static inline gboolean +nm_l3cfg_commit_type_clear(NML3Cfg *self, NML3CfgCommitTypeHandle **handle) +{ + if (!handle || !*handle) + return FALSE; + + nm_l3cfg_commit_type_unregister(self, g_steal_pointer(handle)); + return TRUE; +} + /*****************************************************************************/ const NML3ConfigData *nm_l3cfg_get_combined_l3cd(NML3Cfg *self, gboolean get_commited); diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index d859c1ea..3c9660c7 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -8,47 +8,46 @@ #include "nm-manager.h" -#include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include -#include "libnm-glib-aux/nm-c-list.h" - -#include "libnm-core-aux-intern/nm-common-macros.h" -#include "nm-dbus-manager.h" -#include "vpn/nm-vpn-manager.h" -#include "devices/nm-device.h" +#include "NetworkManagerUtils.h" +#include "devices/nm-device-factory.h" #include "devices/nm-device-generic.h" +#include "devices/nm-device.h" +#include "dhcp/nm-dhcp-manager.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-c-list.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-object.h" -#include "nm-hostname-manager.h" -#include "nm-keep-alive.h" -#include "nm-rfkill-manager.h" -#include "dhcp/nm-dhcp-manager.h" -#include "settings/nm-settings.h" -#include "settings/nm-settings-connection.h" -#include "nm-auth-utils.h" -#include "nm-auth-manager.h" -#include "NetworkManagerUtils.h" -#include "devices/nm-device-factory.h" -#include "nm-sleep-monitor.h" -#include "nm-connectivity.h" -#include "nm-policy.h" -#include "nm-session-monitor.h" +#include "libnm-std-aux/nm-dbus-compat.h" #include "nm-act-request.h" -#include "libnm-core-intern/nm-core-internal.h" -#include "nm-config.h" #include "nm-audit-manager.h" -#include "libnm-std-aux/nm-dbus-compat.h" -#include "nm-checkpoint.h" +#include "nm-auth-manager.h" +#include "nm-auth-utils.h" #include "nm-checkpoint-manager.h" +#include "nm-checkpoint.h" +#include "nm-config.h" +#include "nm-connectivity.h" +#include "nm-dbus-manager.h" #include "nm-dbus-object.h" #include "nm-dispatcher.h" -#include "NetworkManagerUtils.h" +#include "nm-hostname-manager.h" +#include "nm-keep-alive.h" +#include "nm-policy.h" +#include "nm-priv-helper-call.h" +#include "nm-rfkill-manager.h" +#include "nm-session-monitor.h" +#include "nm-sleep-monitor.h" +#include "settings/nm-settings-connection.h" +#include "settings/nm-settings.h" +#include "vpn/nm-vpn-manager.h" #define DEVICE_STATE_PRUNE_RATELIMIT_MAX 100u @@ -214,6 +213,13 @@ struct _NMManager { typedef struct { NMDBusObjectClass parent; + +#if WITH_OPENVSWITCH + /* these fields only serve the purpose to use the symbols.*/ + void (*_use_symbol_nm_priv_helper_call_get_fd)(void); + void (*_use_symbol_nm_priv_helper_utils_open_fd)(void); +#endif + } NMManagerClass; G_DEFINE_TYPE(NMManager, nm_manager, NM_TYPE_DBUS_OBJECT) @@ -2854,9 +2860,10 @@ recheck_assume_connection(NMManager *self, NMDevice *device) g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); if (!nm_device_get_managed(device, FALSE)) { - /* If the device is only unmanaged by NM_UNMANAGED_PLATFORM_INIT, + /* If the device is unmanaged by NM_UNMANAGED_PLATFORM_INIT or NM_UNMANAGED_PARENT, * don't reset the state now but wait until it becomes managed. */ - if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_ALL) != NM_UNMANAGED_PLATFORM_INIT) + if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_ALL) + & ~(NM_UNMANAGED_PLATFORM_INIT | NM_UNMANAGED_PARENT)) nm_device_assume_state_reset(device); _LOG2D(LOGD_DEVICE, device, "assume: don't assume because %s", "not managed"); return FALSE; @@ -2867,7 +2874,7 @@ recheck_assume_connection(NMManager *self, NMDevice *device) _LOG2D(LOGD_DEVICE, device, "assume: don't assume due to device state %s", - nm_device_state_to_str(state)); + nm_device_state_to_string(state)); return FALSE; } @@ -3179,9 +3186,10 @@ _device_realize_finish(NMManager *self, NMDevice *device, const NMPlatformLink * nm_device_realize_finish(device, plink); if (!nm_device_get_managed(device, FALSE)) { - /* If the device is only unmanaged by NM_UNMANAGED_PLATFORM_INIT, + /* If the device is unmanaged by NM_UNMANAGED_PLATFORM_INIT or NM_UNMANAGED_PARENT, * don't reset the state now but wait until it becomes managed. */ - if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_ALL) != NM_UNMANAGED_PLATFORM_INIT) + if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_ALL) + & ~(NM_UNMANAGED_PLATFORM_INIT | NM_UNMANAGED_PARENT)) nm_device_assume_state_reset(device); return; } @@ -4751,7 +4759,7 @@ active_connection_parent_active(NMActiveConnection *active, NMSettingsConnection *sett_conn; NMDevice * parent; - g_signal_handlers_disconnect_by_func(active, (GCallback) active_connection_parent_active, self); + g_signal_handlers_disconnect_by_func(active, G_CALLBACK(active_connection_parent_active), self); if (!parent_ac) { _LOGW(LOGD_CORE, @@ -4926,7 +4934,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError ** /* We can't realize now; defer until the parent device is ready. */ g_signal_connect(active, NM_ACTIVE_CONNECTION_PARENT_ACTIVE, - (GCallback) active_connection_parent_active, + G_CALLBACK(active_connection_parent_active), self); nm_active_connection_set_parent(active, parent_ac); } else { @@ -6164,7 +6172,7 @@ sleep_devices_add(NMManager *self, NMDevice *device, gboolean suspending) g_hash_table_insert(priv->sleep_devices, g_object_ref(device), suspending ? nm_sleep_monitor_inhibit_take(priv->sleep_monitor) : NULL); - g_signal_connect(device, "notify::" NM_DEVICE_STATE, (GCallback) device_sleep_cb, self); + g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(device_sleep_cb), self); return TRUE; } @@ -8076,7 +8084,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_boolean(value, priv->sleeping); break; case PROP_DEVICES: - g_value_take_boxed(value, nm_utils_strv_make_deep_copied(_get_devices_paths(self, FALSE))); + g_value_take_boxed(value, nm_strv_make_deep_copied(_get_devices_paths(self, FALSE))); break; case PROP_METERED: g_value_set_uint(value, priv->metered); @@ -8087,12 +8095,12 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) nm_global_dns_config_to_dbus(dns_config, value); break; case PROP_ALL_DEVICES: - g_value_take_boxed(value, nm_utils_strv_make_deep_copied(_get_devices_paths(self, TRUE))); + g_value_take_boxed(value, nm_strv_make_deep_copied(_get_devices_paths(self, TRUE))); break; case PROP_CHECKPOINTS: g_value_take_boxed( value, - priv->checkpoint_mgr ? nm_utils_strv_make_deep_copied( + priv->checkpoint_mgr ? nm_strv_make_deep_copied( nm_checkpoint_manager_get_checkpoint_paths(priv->checkpoint_mgr, NULL)) : NULL); break; @@ -8530,6 +8538,16 @@ nm_manager_class_init(NMManagerClass *manager_class) GObjectClass * object_class = G_OBJECT_CLASS(manager_class); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(manager_class); +#if WITH_OPENVSWITCH + /* Use the symbols. These symbols are in NetworkManager binary but will be + * used by the OVS device plugin. If we don't use the symbol here, it will + * be wrongly dropped. */ + manager_class->_use_symbol_nm_priv_helper_call_get_fd = + (void (*)(void)) nm_priv_helper_call_get_fd; + manager_class->_use_symbol_nm_priv_helper_utils_open_fd = + (void (*)(void)) nm_priv_helper_utils_open_fd; +#endif + dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_STATIC(NM_DBUS_PATH); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_manager); diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index d5a0317d..224070be 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -29,7 +29,7 @@ typedef struct { GHashTable * l3cfgs; GHashTable * shared_ips; CList l3cfg_signal_pending_lst_head; - guint signal_pending_idle_id; + GSource * signal_pending_idle_source; } NMNetnsPrivate; struct _NMNetns { @@ -189,7 +189,7 @@ _platform_signal_on_idle_cb(gpointer user_data) L3CfgData * l3cfg_data; CList work_list; - priv->signal_pending_idle_id = 0; + nm_clear_g_source_inst(&priv->signal_pending_idle_source); /* we emit all queued signals together. However, we don't want to hook the * main loop for longer than the currently queued elements. @@ -210,7 +210,7 @@ _platform_signal_on_idle_cb(gpointer user_data) nm_steal_int(&l3cfg_data->signal_pending_obj_type_flags)); } - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } static void @@ -235,8 +235,9 @@ _platform_signal_cb(NMPlatform * platform, if (c_list_is_empty(&l3cfg_data->signal_pending_lst)) { c_list_link_tail(&priv->l3cfg_signal_pending_lst_head, &l3cfg_data->signal_pending_lst); - if (priv->signal_pending_idle_id == 0) - priv->signal_pending_idle_id = g_idle_add(_platform_signal_on_idle_cb, self); + if (!priv->signal_pending_idle_source) + priv->signal_pending_idle_source = + nm_g_idle_add_source(_platform_signal_on_idle_cb, self); } _nm_l3cfg_notify_platform_change(l3cfg_data->l3cfg, @@ -460,7 +461,7 @@ dispose(GObject *object) nm_assert(c_list_is_empty(&priv->l3cfg_signal_pending_lst_head)); nm_assert(!priv->shared_ips); - nm_clear_g_source(&priv->signal_pending_idle_id); + nm_clear_g_source_inst(&priv->signal_pending_idle_source); if (priv->platform) g_signal_handlers_disconnect_by_data(priv->platform, &priv->_self_signal_user_data); diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index e147e504..03e082f1 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -322,7 +322,9 @@ ip6_remove_device_prefix_delegations(NMPolicy *self, NMDevice *device) } static void -device_ip6_prefix_delegated(NMDevice *device, NMPlatformIP6Address *prefix, gpointer user_data) +device_ip6_prefix_delegated(NMDevice * device, + const NMPlatformIP6Address *prefix, + gpointer user_data) { NMPolicyPrivate * priv = user_data; NMPolicy * self = _PRIV_TO_SELF(priv); @@ -913,7 +915,7 @@ update_system_hostname(NMPolicy *self, const char *msg) if (wait) { g_signal_connect(info->device, NM_DEVICE_DNS_LOOKUP_DONE, - (GCallback) device_dns_lookup_done, + G_CALLBACK(device_dns_lookup_done), self); return; } @@ -2057,7 +2059,7 @@ device_state_changed(NMDevice * device, _LOGD(LOGD_DEVICE, "blocking autoconnect of connection '%s': %s", nm_settings_connection_get_id(sett_conn), - NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_str, + NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_string, nm_device_state_reason_check(reason))); nm_settings_connection_autoconnect_blocked_reason_set(sett_conn, blocked_reason, @@ -2141,6 +2143,7 @@ device_ip_config_changed(NMDevice * device, NMPolicyPrivate *priv = user_data; NMPolicy * self = _PRIV_TO_SELF(priv); int addr_family; + NMDeviceState state; nm_assert(new_config || old_config); nm_assert(!new_config || NM_IS_IP_CONFIG(new_config)); @@ -2159,7 +2162,8 @@ device_ip_config_changed(NMDevice * device, * ignore IP config changes but when the device is in activated state. * Prevents unnecessary changes to DNS information. */ - if (nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) { + state = nm_device_get_state(device); + if (state > NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_ACTIVATED) { if (old_config != new_config) { if (new_config) _dns_manager_set_ip_config(priv->dns_manager, @@ -2222,30 +2226,30 @@ devices_list_register(NMPolicy *self, NMDevice *device) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); /* Connect state-changed with _after, so that the handler is invoked after other handlers. */ - g_signal_connect_after(device, NM_DEVICE_STATE_CHANGED, (GCallback) device_state_changed, priv); + g_signal_connect_after(device, NM_DEVICE_STATE_CHANGED, G_CALLBACK(device_state_changed), priv); g_signal_connect(device, NM_DEVICE_IP4_CONFIG_CHANGED, - (GCallback) device_ip_config_changed, + G_CALLBACK(device_ip_config_changed), priv); g_signal_connect(device, NM_DEVICE_IP6_CONFIG_CHANGED, - (GCallback) device_ip_config_changed, + G_CALLBACK(device_ip_config_changed), priv); g_signal_connect(device, NM_DEVICE_IP6_PREFIX_DELEGATED, - (GCallback) device_ip6_prefix_delegated, + G_CALLBACK(device_ip6_prefix_delegated), priv); g_signal_connect(device, NM_DEVICE_IP6_SUBNET_NEEDED, - (GCallback) device_ip6_subnet_needed, + G_CALLBACK(device_ip6_subnet_needed), priv); g_signal_connect(device, "notify::" NM_DEVICE_AUTOCONNECT, - (GCallback) device_autoconnect_changed, + G_CALLBACK(device_autoconnect_changed), priv); g_signal_connect(device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, - (GCallback) device_recheck_auto_activate, + G_CALLBACK(device_recheck_auto_activate), priv); } @@ -2801,49 +2805,49 @@ constructed(GObject *object) g_signal_connect(priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, - (GCallback) hostname_changed, + G_CALLBACK(hostname_changed), priv); g_signal_connect(priv->manager, "notify::" NM_MANAGER_SLEEPING, - (GCallback) sleeping_changed, + G_CALLBACK(sleeping_changed), priv); g_signal_connect(priv->manager, "notify::" NM_MANAGER_NETWORKING_ENABLED, - (GCallback) sleeping_changed, + G_CALLBACK(sleeping_changed), priv); g_signal_connect(priv->manager, NM_MANAGER_INTERNAL_DEVICE_ADDED, - (GCallback) device_added, + G_CALLBACK(device_added), priv); g_signal_connect(priv->manager, NM_MANAGER_INTERNAL_DEVICE_REMOVED, - (GCallback) device_removed, + G_CALLBACK(device_removed), priv); g_signal_connect(priv->manager, NM_MANAGER_ACTIVE_CONNECTION_ADDED, - (GCallback) active_connection_added, + G_CALLBACK(active_connection_added), priv); g_signal_connect(priv->manager, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, - (GCallback) active_connection_removed, + G_CALLBACK(active_connection_removed), priv); g_signal_connect(priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, - (GCallback) connection_added, + G_CALLBACK(connection_added), priv); g_signal_connect(priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, - (GCallback) connection_updated, + G_CALLBACK(connection_updated), priv); g_signal_connect(priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, - (GCallback) connection_removed, + G_CALLBACK(connection_removed), priv); g_signal_connect(priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, - (GCallback) connection_flags_changed, + G_CALLBACK(connection_flags_changed), priv); g_signal_connect(priv->agent_mgr, diff --git a/src/core/nm-priv-helper-call.c b/src/core/nm-priv-helper-call.c new file mode 100644 index 00000000..06249ece --- /dev/null +++ b/src/core/nm-priv-helper-call.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-priv-helper-call.h" + +#include + +#include "nm-dbus-manager.h" + +/*****************************************************************************/ + +static void +_nm_priv_helper_call_get_fd_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMPrivHelperCallGetFDCallback callback; + gpointer callback_data; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + gs_unref_object GUnixFDList *fd_list = NULL; + gs_free int * fd_arr = NULL; + + nm_utils_user_data_unpack(user_data, &callback, &callback_data); + + ret = g_dbus_connection_call_with_unix_fd_list_finish(G_DBUS_CONNECTION(source), + &fd_list, + res, + &error); + + if (error) { + callback(-1, error, callback_data); + return; + } + + if (!fd_list || g_unix_fd_list_get_length(fd_list) != 1) { + nm_utils_error_set(&error, + NM_UTILS_ERROR_UNKNOWN, + "Unexpectedly not one FD is returned by nm-priv-helper GetFD()"); + callback(-1, error, callback_data); + return; + } + + fd_arr = g_unix_fd_list_steal_fds(fd_list, NULL); + + /* we transfer ownership of the file descriptor! */ + callback(fd_arr[0], NULL, callback_data); +} + +static gboolean +_nm_priv_helper_call_get_fd_fail_on_idle(gpointer user_data) +{ + gs_unref_object GCancellable *cancellable = NULL; + NMPrivHelperCallGetFDCallback callback; + gpointer callback_data; + gs_free_error GError *error = NULL; + + nm_utils_user_data_unpack(user_data, &cancellable, &callback, &callback_data); + + if (!g_cancellable_set_error_if_cancelled(cancellable, &error)) + nm_utils_error_set(&error, + NM_UTILS_ERROR_UNKNOWN, + "Cannot talk to nm-priv-helper without D-Bus"); + + callback(-1, error, callback_data); + return G_SOURCE_REMOVE; +} + +void +nm_priv_helper_call_get_fd(NMPrivHelperGetFDType fd_type, + GCancellable * cancellable, + NMPrivHelperCallGetFDCallback callback, + gpointer user_data) +{ + GDBusConnection *dbus_connection; + + nm_assert(NM_IN_SET(fd_type, NM_PRIV_HELPER_GET_FD_TYPE_OVSDB_SOCKET)); + nm_assert(!cancellable || G_IS_CANCELLABLE(cancellable)); + nm_assert(callback); + + dbus_connection = NM_MAIN_DBUS_CONNECTION_GET; + + if (!dbus_connection) { + nm_g_idle_add(_nm_priv_helper_call_get_fd_fail_on_idle, + nm_utils_user_data_pack(g_object_ref(cancellable), callback, user_data)); + return; + } + + g_dbus_connection_call_with_unix_fd_list(dbus_connection, + NM_PRIV_HELPER_DBUS_BUS_NAME, + NM_PRIV_HELPER_DBUS_OBJECT_PATH, + NM_PRIV_HELPER_DBUS_IFACE_NAME, + "GetFD", + g_variant_new("(u)", fd_type), + G_VARIANT_TYPE("()"), + G_DBUS_CALL_FLAGS_NONE, + 10000, + NULL, + cancellable, + _nm_priv_helper_call_get_fd_cb, + nm_utils_user_data_pack(callback, user_data)); +} diff --git a/src/core/nm-priv-helper-call.h b/src/core/nm-priv-helper-call.h new file mode 100644 index 00000000..1915c5b3 --- /dev/null +++ b/src/core/nm-priv-helper-call.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_PRIV_HELPER_CALL_H__ +#define __NM_PRIV_HELPER_CALL_H__ + +#include "../libnm-base/nm-priv-helper-utils.h" + +typedef void (*NMPrivHelperCallGetFDCallback)(int fd_take, GError *error, gpointer user_data); + +void nm_priv_helper_call_get_fd(NMPrivHelperGetFDType fd_type, + GCancellable * cancellable, + NMPrivHelperCallGetFDCallback callback, + gpointer user_data); + +#endif /* __NM_PRIV_HELPER_CALL_H__ */ diff --git a/src/core/nm-session-monitor.c b/src/core/nm-session-monitor.c index 88de1a00..2cc99ab3 100644 --- a/src/core/nm-session-monitor.c +++ b/src/core/nm-session-monitor.c @@ -14,17 +14,17 @@ #include #if SESSION_TRACKING_SYSTEMD && SESSION_TRACKING_ELOGIND - #error Cannot build both systemd-logind and elogind support +#error Cannot build both systemd-logind and elogind support #endif #if SESSION_TRACKING_SYSTEMD - #include - #define LOGIND_NAME "systemd-logind" +#include +#define LOGIND_NAME "systemd-logind" #endif #if SESSION_TRACKING_ELOGIND - #include - #define LOGIND_NAME "elogind" +#include +#define LOGIND_NAME "elogind" #endif #include "NetworkManagerUtils.h" diff --git a/src/core/nm-sleep-monitor.c b/src/core/nm-sleep-monitor.c index 306453e7..76f13203 100644 --- a/src/core/nm-sleep-monitor.c +++ b/src/core/nm-sleep-monitor.c @@ -16,23 +16,23 @@ #if defined(SUSPEND_RESUME_UPOWER) - #define SUSPEND_DBUS_NAME "org.freedesktop.UPower" - #define SUSPEND_DBUS_PATH "/org/freedesktop/UPower" - #define SUSPEND_DBUS_INTERFACE "org.freedesktop.UPower" - #define USE_UPOWER 1 - #define _NMLOG_PREFIX_NAME "sleep-monitor-up" +#define SUSPEND_DBUS_NAME "org.freedesktop.UPower" +#define SUSPEND_DBUS_PATH "/org/freedesktop/UPower" +#define SUSPEND_DBUS_INTERFACE "org.freedesktop.UPower" +#define USE_UPOWER 1 +#define _NMLOG_PREFIX_NAME "sleep-monitor-up" #elif defined(SUSPEND_RESUME_SYSTEMD) || defined(SUSPEND_RESUME_ELOGIND) - #define SUSPEND_DBUS_NAME "org.freedesktop.login1" - #define SUSPEND_DBUS_PATH "/org/freedesktop/login1" - #define SUSPEND_DBUS_INTERFACE "org.freedesktop.login1.Manager" - #define USE_UPOWER 0 - #if defined(SUSPEND_RESUME_SYSTEMD) - #define _NMLOG_PREFIX_NAME "sleep-monitor-sd" - #else - #define _NMLOG_PREFIX_NAME "sleep-monitor-el" - #endif +#define SUSPEND_DBUS_NAME "org.freedesktop.login1" +#define SUSPEND_DBUS_PATH "/org/freedesktop/login1" +#define SUSPEND_DBUS_INTERFACE "org.freedesktop.login1.Manager" +#define USE_UPOWER 0 +#if defined(SUSPEND_RESUME_SYSTEMD) +#define _NMLOG_PREFIX_NAME "sleep-monitor-sd" +#else +#define _NMLOG_PREFIX_NAME "sleep-monitor-el" +#endif #elif defined(SUSPEND_RESUME_CONSOLEKIT) @@ -40,15 +40,15 @@ * uses. http://consolekit2.github.io/ConsoleKit2/#Manager.Inhibit */ - #define SUSPEND_DBUS_NAME "org.freedesktop.ConsoleKit" - #define SUSPEND_DBUS_PATH "/org/freedesktop/ConsoleKit/Manager" - #define SUSPEND_DBUS_INTERFACE "org.freedesktop.ConsoleKit.Manager" - #define USE_UPOWER 0 - #define _NMLOG_PREFIX_NAME "sleep-monitor-ck" +#define SUSPEND_DBUS_NAME "org.freedesktop.ConsoleKit" +#define SUSPEND_DBUS_PATH "/org/freedesktop/ConsoleKit/Manager" +#define SUSPEND_DBUS_INTERFACE "org.freedesktop.ConsoleKit.Manager" +#define USE_UPOWER 0 +#define _NMLOG_PREFIX_NAME "sleep-monitor-ck" #else - #error define one of SUSPEND_RESUME_SYSTEMD, SUSPEND_RESUME_ELOGIND, SUSPEND_RESUME_CONSOLEKIT, or SUSPEND_RESUME_UPOWER +#error define one of SUSPEND_RESUME_SYSTEMD, SUSPEND_RESUME_ELOGIND, SUSPEND_RESUME_CONSOLEKIT, or SUSPEND_RESUME_UPOWER #endif diff --git a/src/core/nm-test-utils-core.h b/src/core/nm-test-utils-core.h index 99d12ba9..e037ba92 100644 --- a/src/core/nm-test-utils-core.h +++ b/src/core/nm-test-utils-core.h @@ -222,7 +222,7 @@ nmtst_platform_ip4_routes_equal(const NMPlatformIP4Route *a, } } - #ifdef __NMP_OBJECT_H__ +#ifdef __NMP_OBJECT_H__ static inline void nmtst_platform_ip4_routes_equal_aptr(const NMPObject *const * a, @@ -242,7 +242,7 @@ nmtst_platform_ip4_routes_equal_aptr(const NMPObject *const * a, nmtst_platform_ip4_routes_equal(c_a, b, len, ignore_order); } - #endif +#endif static inline int _nmtst_platform_ip6_routes_equal_sort(gconstpointer a, gconstpointer b, gpointer user_data) @@ -291,7 +291,7 @@ nmtst_platform_ip6_routes_equal(const NMPlatformIP6Route *a, } } - #ifdef __NMP_OBJECT_H__ +#ifdef __NMP_OBJECT_H__ static inline void nmtst_platform_ip6_routes_equal_aptr(const NMPObject *const * a, @@ -311,13 +311,13 @@ nmtst_platform_ip6_routes_equal_aptr(const NMPObject *const * a, nmtst_platform_ip6_routes_equal(c_a, b, len, ignore_order); } - #endif +#endif #endif #ifdef __NETWORKMANAGER_IP4_CONFIG_H__ - #include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" static inline NMIP4Config * nmtst_ip4_config_new(int ifindex) @@ -331,7 +331,7 @@ nmtst_ip4_config_new(int ifindex) #ifdef __NETWORKMANAGER_IP6_CONFIG_H__ - #include "libnm-glib-aux/nm-dedup-multi.h" +#include "libnm-glib-aux/nm-dedup-multi.h" static inline NMIP6Config * nmtst_ip6_config_new(int ifindex) diff --git a/src/core/nm-types.h b/src/core/nm-types.h index 7ad5aee1..294cf409 100644 --- a/src/core/nm-types.h +++ b/src/core/nm-types.h @@ -7,7 +7,7 @@ #define __NETWORKMANAGER_TYPES_H__ #if !((NETWORKMANAGER_COMPILATION) &NM_NETWORKMANAGER_COMPILATION_WITH_DAEMON) - #error Cannot use this header. +#error Cannot use this header. #endif /* core */ diff --git a/src/core/platform/tests/meson.build b/src/core/platform/tests/meson.build index 5d55707a..8824ed2f 100644 --- a/src/core/platform/tests/meson.build +++ b/src/core/platform/tests/meson.build @@ -14,7 +14,6 @@ test_units = [ ['test-platform-general', 'test-platform-general.c', test_c_flags, default_test_timeout], ['test-route-fake', 'test-route.c', test_fake_c_flags, default_test_timeout], ['test-route-linux', 'test-route.c', test_linux_c_flags, default_test_timeout], - ['test-tc-fake', 'test-tc.c', test_fake_c_flags, default_test_timeout], ['test-tc-linux', 'test-tc.c', test_linux_c_flags, default_test_timeout], ] diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 2fc9e836..4f56a3a7 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -37,7 +37,9 @@ gboolean nmtstp_is_root_test(void) { g_assert(_nmtstp_setup_platform_func); - return _nmtstp_setup_platform_func == nm_linux_platform_setup; + return NM_IN_SET(_nmtstp_setup_platform_func, + nm_linux_platform_setup, + nm_linux_platform_setup_with_tc_cache); } gboolean @@ -2694,9 +2696,13 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) NM_HASH_OBFUSCATE_PTR(defender), NM_ETHER_ADDR_FORMAT_VAL((const NMEtherAddr *) event->defended.sender)); break; + case N_ACD_EVENT_DOWN: + /* Not sure why this sometimes happens. But this is only the test stub, ignore it. */ + _LOGT("acd-defender[" NM_HASH_OBFUSCATE_PTR_FMT "]: link down event received", + NM_HASH_OBFUSCATE_PTR(defender)); + break; case N_ACD_EVENT_USED: case N_ACD_EVENT_CONFLICT: - case N_ACD_EVENT_DOWN: default: g_assert_not_reached(); break; diff --git a/src/core/platform/tests/test-common.h b/src/core/platform/tests/test-common.h index 1fb97d24..fc4149f0 100644 --- a/src/core/platform/tests/test-common.h +++ b/src/core/platform/tests/test-common.h @@ -104,11 +104,11 @@ SignalData *add_signal_full(const char * name, int ifindex, const char * ifname); #define add_signal(name, change_type, callback) \ - add_signal_full(name, change_type, (GCallback) callback, 0, NULL) + add_signal_full(name, change_type, G_CALLBACK(callback), 0, NULL) #define add_signal_ifindex(name, change_type, callback, ifindex) \ - add_signal_full(name, change_type, (GCallback) callback, ifindex, NULL) + add_signal_full(name, change_type, G_CALLBACK(callback), ifindex, NULL) #define add_signal_ifname(name, change_type, callback, ifname) \ - add_signal_full(name, change_type, (GCallback) callback, 0, ifname) + add_signal_full(name, change_type, G_CALLBACK(callback), 0, ifname) void _accept_signal(const char *file, int line, const char *func, SignalData *data); void _accept_signals(const char *file, int line, const char *func, SignalData *data, int min, int max); diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index f6c3841e..24e3fd99 100644 --- a/src/core/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -580,6 +580,7 @@ test_bridge_addr(void) char addr[ETH_ALEN]; NMPlatformLink link; const NMPlatformLink *plink = NULL; + NMPLinkAddress hw_perm_addr; nm_utils_hwaddr_aton("de:ad:be:ef:00:11", addr, sizeof(addr)); @@ -599,27 +600,49 @@ test_bridge_addr(void) plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex); g_assert(plink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, plink, &hw_perm_addr)); - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { - g_assert(!nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex)); + if (nmtstp_is_root_test()) { + g_assert_cmpint(nm_platform_link_get_inet6_addr_gen_mode(NM_PLATFORM_GET, link.ifindex), + ==, + NM_IN6_ADDR_GEN_MODE_EUI64); + g_assert_cmpint(_nm_platform_link_get_inet6_addr_gen_mode(plink), + ==, + NM_IN6_ADDR_GEN_MODE_EUI64); g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_EUI64); g_assert(NMTST_NM_ERR_SUCCESS( - nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex, TRUE))); - g_assert(nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex)); + nm_platform_link_set_inet6_addr_gen_mode(NM_PLATFORM_GET, + link.ifindex, + NM_IN6_ADDR_GEN_MODE_NONE))); + g_assert_cmpint(nm_platform_link_get_inet6_addr_gen_mode(NM_PLATFORM_GET, link.ifindex), + ==, + NM_IN6_ADDR_GEN_MODE_NONE); plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex); g_assert(plink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, plink, &hw_perm_addr)); + g_assert_cmpint(_nm_platform_link_get_inet6_addr_gen_mode(plink), + ==, + NM_IN6_ADDR_GEN_MODE_NONE); g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_NONE); g_assert(NMTST_NM_ERR_SUCCESS( - nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex, FALSE))); - g_assert(!nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex)); + nm_platform_link_set_inet6_addr_gen_mode(NM_PLATFORM_GET, + link.ifindex, + NM_IN6_ADDR_GEN_MODE_EUI64))); + g_assert_cmpint(nm_platform_link_get_inet6_addr_gen_mode(NM_PLATFORM_GET, link.ifindex), + ==, + NM_IN6_ADDR_GEN_MODE_EUI64); plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex); g_assert(plink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, plink, &hw_perm_addr)); + g_assert_cmpint(_nm_platform_link_get_inet6_addr_gen_mode(plink), + ==, + NM_IN6_ADDR_GEN_MODE_EUI64); g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_EUI64); @@ -730,6 +753,7 @@ static void test_external(void) { const NMPlatformLink *pllink; + NMPLinkAddress hw_perm_addr; SignalData * link_added, *link_changed, *link_removed; int ifindex; @@ -758,6 +782,7 @@ test_external(void) pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex); g_assert(pllink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink, &hw_perm_addr)); if (!pllink->initialized) { /* we still lack the notification via UDEV. Expect another link changed signal. */ wait_signal(link_changed); @@ -1488,7 +1513,7 @@ test_software_detect(gconstpointer user_data) * The fix (17af2bce) is included kernel 4.7, dated 24 July, 2016. */ for (i = ifindex_parent + 1; i < ifindex_parent + 100; i++) { - snprintf(buf, sizeof(buf), "/sys/class/macvtap/tap%d", i); + g_snprintf(buf, sizeof(buf), "/sys/class/macvtap/tap%d", i); if (!g_file_test(buf, G_FILE_TEST_IS_SYMLINK)) break; @@ -2522,6 +2547,7 @@ test_nl_bugs_veth(void) const NMPlatformLink *pllink_veth0, *pllink_veth1; gs_free_error GError * error = NULL; NMTstpNamespaceHandle *ns_handle = NULL; + NMPLinkAddress hw_perm_addr; /* create veth pair. */ ifindex_veth0 = nmtstp_link_veth_add(NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex; @@ -2538,6 +2564,7 @@ test_nl_bugs_veth(void) /* assert that NMPlatformLink.parent is the peer-ifindex. */ pllink_veth0 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth0); g_assert(pllink_veth0); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink_veth0, &hw_perm_addr)); if (pllink_veth0->parent == 0) { /* Kernels prior to 4.1 dated 21 June, 2015 don't support exposing the veth peer * as IFA_LINK. skip the remainder of the test. */ @@ -2549,6 +2576,7 @@ test_nl_bugs_veth(void) * https://bugzilla.redhat.com/show_bug.cgi?id=1285827 in place. */ pllink_veth1 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth1); g_assert(pllink_veth1); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink_veth1, &hw_perm_addr)); g_assert_cmpint(pllink_veth1->parent, ==, ifindex_veth0); /* move one veth peer to another namespace and check that the @@ -2588,6 +2616,7 @@ test_nl_bugs_spuroius_newlink(void) const char * IFACE_DUMMY0 = "nm-test-dummy0"; int ifindex_bond0, ifindex_dummy0; const NMPlatformLink *pllink; + NMPLinkAddress hw_perm_addr; gboolean wait_for_settle; /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ @@ -2609,6 +2638,7 @@ test_nl_bugs_spuroius_newlink(void) pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0); g_assert(pllink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink, &hw_perm_addr)); if (pllink->master == ifindex_bond0) break; }); @@ -2621,6 +2651,7 @@ again: nm_platform_process_events(NM_PLATFORM_GET); pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_bond0); g_assert(!pllink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink, &hw_perm_addr)); if (wait_for_settle) { wait_for_settle = FALSE; @@ -2641,6 +2672,7 @@ test_nl_bugs_spuroius_dellink(void) const char * IFACE_DUMMY0 = "nm-test-dummy0"; int ifindex_bridge0, ifindex_dummy0; const NMPlatformLink *pllink; + NMPLinkAddress hw_perm_addr; gboolean wait_for_settle; /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ @@ -2663,6 +2695,7 @@ test_nl_bugs_spuroius_dellink(void) pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0); g_assert(pllink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink, &hw_perm_addr)); if (pllink->master == ifindex_bridge0) break; }); @@ -2677,8 +2710,10 @@ again: nm_platform_process_events(NM_PLATFORM_GET); pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_bridge0); g_assert(pllink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink, &hw_perm_addr)); pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0); g_assert(pllink); + g_assert(!nm_platform_link_get_permanent_address(NM_PLATFORM_GET, pllink, &hw_perm_addr)); g_assert_cmpint(pllink->parent, ==, 0); if (wait_for_settle) { @@ -2716,7 +2751,7 @@ _test_netns_create_platform(void) netns = nmp_netns_new(); g_assert(NMP_IS_NETNS(netns)); - platform = nm_linux_platform_new(TRUE, TRUE); + platform = nm_linux_platform_new(TRUE, TRUE, TRUE); g_assert(NM_IS_LINUX_PLATFORM(platform)); nmp_netns_pop(netns); @@ -2805,7 +2840,7 @@ test_netns_general(gpointer fixture, gconstpointer test_data) if (_check_sysctl_skip()) return; - platform_1 = nm_linux_platform_new(TRUE, TRUE); + platform_1 = nm_linux_platform_new(TRUE, TRUE, TRUE); platform_2 = _test_netns_create_platform(); /* add some dummy devices. The "other-*" devices are there to bump the ifindex */ @@ -2933,7 +2968,7 @@ test_netns_set_netns(gpointer fixture, gconstpointer test_data) if (_test_netns_check_skip()) return; - platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE); + platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE, TRUE); platforms[1] = platform_1 = _test_netns_create_platform(); platforms[2] = platform_2 = _test_netns_create_platform(); @@ -3032,7 +3067,7 @@ test_netns_push(gpointer fixture, gconstpointer test_data) if (_check_sysctl_skip()) return; - pl[0].platform = platform_0 = nm_linux_platform_new(TRUE, TRUE); + pl[0].platform = platform_0 = nm_linux_platform_new(TRUE, TRUE, TRUE); pl[1].platform = platform_1 = _test_netns_create_platform(); pl[2].platform = platform_2 = _test_netns_create_platform(); @@ -3179,7 +3214,7 @@ test_netns_bind_to_path(gpointer fixture, gconstpointer test_data) if (_test_netns_check_skip()) return; - platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE); + platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE, TRUE); platforms[1] = platform_1 = _test_netns_create_platform(); platforms[2] = platform_2 = _test_netns_create_platform(); @@ -3344,7 +3379,7 @@ test_sysctl_netns_switch(void) if (_test_netns_check_skip()) return; - platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE); + platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE, TRUE); platforms[1] = platform_1 = _test_netns_create_platform(); platforms[2] = platform_2 = _test_netns_create_platform(); PL = platforms[nmtst_get_rand_uint32() % 3]; diff --git a/src/core/platform/tests/test-platform-general.c b/src/core/platform/tests/test-platform-general.c index 05158228..8ffd92b5 100644 --- a/src/core/platform/tests/test-platform-general.c +++ b/src/core/platform/tests/test-platform-general.c @@ -31,7 +31,7 @@ test_init_linux_platform(void) { gs_unref_object NMPlatform *platform = NULL; - platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); + platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT, TRUE); } /*****************************************************************************/ @@ -42,7 +42,7 @@ test_link_get_all(void) gs_unref_object NMPlatform *platform = NULL; gs_unref_ptrarray GPtrArray *links = NULL; - platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); + platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT, TRUE); links = nm_platform_link_get_all(platform, TRUE); } @@ -104,34 +104,34 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) [0] = ("5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218424e48836dd1cb504e03d53e1124c5" "0065aeb2e6fbf952902383028e3b47f280f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a" "8982c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000" - "883b0f3fd6ed84d6c959e553b887edcd01c2f5d200000043b809d259e499db7d00f1853bdcb0e4bc" - "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c400368b6630000007a" + "883b0f3fd6ed84d6c959e553b887edcd6101f5d200000043b809d259e499db7d00f1853bdcb0e4bc" + "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c40b403b6630000007a" "034f43340d01683c0045097aea4a849f060ddf57b24a5be9636360d603000000ad7c499dd538d345" - "74c038404923e75d0209e2fc0000004acc807cdce682f80f00315c45ef817264c89a736ed55ed637" - "b96c200203000000faf1809becd2506315a6da29b2e94d3a031fe0e900000083a36035fb6297dfa7" + "74c038404923e75d0e02e2fc0000004acc807cdce682f80f00315c45ef817264c89a736ed55ed637" + "b96c200203000000faf1809becd2506315a6da29b2e94d3ab503e0e900000083a36035fb6297dfa7" "00686b5efd0d53bb6215de4bb6f6f3d031a79028030000008bb836c0a25ea71f5daaed4d99eb2ebe" - "033c432f000000bf4ccf30d3aaaf02a4005d7308b67f91bf9d82c856ba942455e8d07c8403000000" - "f2abb982b001ec16901f55f960c55c22022099a80000002b4d4647f53b1921af0088e3759a08e7a5" - "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf1402d3481e00000060" + "be03432f000000bf4ccf30d3aaaf02a4005d7308b67f91bf9d82c856ba942455e8d07c8403000000" + "f2abb982b001ec16901f55f960c55c22f30299a80000002b4d4647f53b1921af0088e3759a08e7a5" + "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf148e02481e00000060" "e89f7abdb682380a00eae374835b4a49a2b980b6aba92da6409969aa03000000e00473755d31e5b2" - "de252167c1c91b3a02ba0c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4" - "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348b00c12ebd000000ab667224dae775e5cc" + "de252167c1c91b3a36020c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4" + "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348bda002ebd000000ab667224dae775e5cc" "0041aca2ff0f576767d3648102b61886d149f07403000000153ece68ade15cec25a59273e7519f34" "c4458d70000000f3819aa46fbe1439340033ae6dec0fb124f264af67eed7c9a8ecc8fb1103000000" - "fcebbaeb0c56535923f14874042a8aff021f8e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b" - "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0029c44770000004b" + "fcebbaeb0c56535923f14874042a8aff1d028e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b" + "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0500244770000004b" "2e69220d6c0fc09c25d6534c809829af4a9df58dbfef186d416f3a1e030000002c932e655203d82a" - "3c84c4eb274ed18603780281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b" - "69e66142030000004fda8a3e0b841cf76391dd68269b53ec0244a831000000b78c54dda9ac3bb1b1" + "3c84c4eb274ed18687030281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b" + "69e66142030000004fda8a3e0b841cf76391dd68269b53eccb02a831000000b78c54dda9ac3bb1b1" "d43e6505621b9a7f0422ae3fc8979ee0416f95e70300000057d6249b652ba98c7dc7f17f666969e4" - "023baf7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000" - "cd897619f51f44e644d7cf1d06b2b1150082549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3" - "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1c03c2056c00000051" + "5c02af7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000" + "cd897619f51f44e644d7cf1d06b2b115d800549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3" + "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1cfc03056c00000051" "bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0e5fe7d360300000066a3ae3939762df3" - "3a2d55060c78d55100b110fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b" - "86ed271803000000a5edc511c1507a141e0f515638c7ba31027609450000003357ae79989870ccec" + "3a2d55060c78d551cb0010fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b" + "86ed271803000000a5edc511c1507a141e0f515638c7ba31f50209450000003357ae79989870ccec" "3def0ad92749e016663fe6ee0228c1da82d1595603000000348352d715cf9d411ea012e5307294b6" - "0146dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000" + "e301dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000" "862573c2303dd1d65c7b2cffeca6d1adaccae11f0000000f855ebf3b772eb2b1c896c9a7304f6645" "0a5f6abd850b06e3b10123e6030000001dff045298cfee0636674cdefb57b9ae54cfe8f400000038" "1ba2c4396de60f032bc7f34de2959871c0d4c0d4eb720c4ab550c5db03000000f32f4af595d785d5" @@ -139,108 +139,108 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) "b16c7376030000005219061ab4c5c79489b2cc6a883c146972decb8b000000f5e6d66df46ea13910" "7754dee62c36d2fc70ccc567df7a49b8585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e" "75039fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000" - "895d5f24037d233302ad3b82d639272e0246eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c" + "895d5f24037d233302ad3b82d639272e4a02eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c" "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8ec7e4b89bf5a5d0" "6776e66a9d80ab132e1ac921eb76adbb229df32e561fa80a0fc4676703000000a23eb66e720da9e0" - "7ac998b5690807d50217369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a" - "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed03bb58f0e9201f17bd99fcf72909ac9e" + "7ac998b5690807d52602369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a" + "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed720358f0e9201f17bd99fcf72909ac9e" "7a55299e9bb4fd53bc7417940fcffe3f81cafd6302000000d6732578acd14320aefd4503189f7630" - "038e501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000" - "891715df7fc6a902edae579e2e10c7f7022ba0340436242cbeb0248cee3fbc160032d4f28aa28c08" + "2403501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000" + "891715df7fc6a902edae579e2e10c7f7a202a0340436242cbeb0248cee3fbc160032d4f28aa28c08" "f80dd50c6712dfb4abba4a32020000008ffe423d01883918039249f398f9b37ea091465100000064" "3722d9b707c0d8a400b7c8307f06b4b29088f20d9ac676d5e4bafc4e02000000fde69eec3af2e6d0" "bd68ab722af14548b29572e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea" - "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd6011fa56dfdcfc1155f236c8b9c79a620" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c01a56dfdcfc1155f236c8b9c79a620" "00660bbf024b03ff0a8e27c405e64244e36f90d402000000fd41fe47684b370b6ec6584d64496089" - "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a119c64ed0402000000" - "a660ac824b7fae389861419c50da49bf02092583000000259f9f0251becc987907879cca68fec7bb" - "bb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6078a806d329c9b0000bfc972000000f5" - "b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f641e447502000000b9b68c08a5e4351e" - "a349e1ccf662e058b879a45100000045fcb6a035339d504c9726d80d9c2d89df765b4d9a130257dc" - "d1e1b34902000000bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46da" - "fe7d6ec4ac1ea051010911915ddb05f2c43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0" - "032d2ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000" - "18238487a417f3da01d99dae5f19009601582cab0000005b2363d13edc5aa115005eb914d8fbe9a4" - "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40267c3d400000064" + "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a11d1e1b34902000000" + "bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46dafe7d6ec4ac1ea051" + "010911915ddb05f29c64ed0402000000a660ac824b7fae389861419c50da49bf2b02258300000025" + "9f9f0251becc987907879cca68fec7bbbb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6" + "078a806d329c9b008b00c972000000f5b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f" + "641e447502000000b9b68c08a5e4351ea349e1ccf662e058b879a45100000045fcb6a035339d504c" + "9726d80d9c2d89df765b4d9a130257dcc43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0" + "e0032ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000" + "18238487a417f3da01d99dae5f190096cc012cab0000005b2363d13edc5aa115005eb914d8fbe9a4" + "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40c02c3d400000064" "9da90bd2fff2f2560046870bd7d5f14870c6d18d6242b356b9ef1b2101000000f90adac616a31dc2" - "e46a234558817151008fc9c900000073e64b0bd761fdf274005dca8ce1bd1871ae17bb4515856092" - "b4d9e89b010000006855676c277cf1bd017c9148da5892bb0351c3a70000009f3391ce7d3fd48469" + "e46a234558817151b300c9c900000073e64b0bd761fdf274005dca8ce1bd1871ae17bb4515856092" + "b4d9e89b010000006855676c277cf1bd017c9148da5892bb4903c3a70000009f3391ce7d3fd48469" "005f0c233dbdd2a97835df1f1782dee86c1de913010000003ee1d76fc1ea76e98c9dfc78997ab53e" - "00c21963f5b4cb2454830c68e44ea74b002b83f9b3bee14d861a4c9eeecc89f65408c1b701000000" - "d9e1825fa638e1af284a024b7f9e85ff00e050a2000000276e08cb887464b93400c3127c750fabdd" - "69121aec129cdc690d58fbcc01000000d0d44ff1e51c35157666c05348e6f50700a8e89800000012" + "27001963f5b4cb2454830c68e44ea74b002b83f9b3bee14d861a4c9eeecc89f65408c1b701000000" + "d9e1825fa638e1af284a024b7f9e85ff730050a2000000276e08cb887464b93400c3127c750fabdd" + "69121aec129cdc690d58fbcc01000000d0d44ff1e51c35157666c05348e6f507ff00e89800000012" "b900b2061d0c334b009f2dd1cdf64b0f9a60e0e289f08db3fde6b0250100000039dd8f88152a5845" - "4d9ca9d20f45dfa702e78604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c" - "210aeb09010000007000b96d06992b6a58acd3995b9663d20248f333ef467092818aa77d6732b678" + "4d9ca9d20f45dfa774028604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c" + "210aeb09010000007000b96d06992b6a58acd3995b9663d2df02f333ef467092818aa77d6732b678" "00844ef5a943825fcd743f59bd14c89b955e1a13010000007acbce3e3bcdf3824f1b134847ff26ba" - "009a774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000" - "5e0dfe491d1ba96742c7b5e02b2271220188b02a06d0dc5504b0595daf37deb499996bfb667f072d" - "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba80383f4c500000063" + "4400774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000" + "5e0dfe491d1ba96742c7b5e02b2271229c01b02a06d0dc5504b0595daf37deb499996bfb667f072d" + "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba85103f4c500000063" "eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8ca0100000027335a25a364d101" - "5ffac03089f4553902b01784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507" + "5ffac03089f45539e1021784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507" "f121014a01000000efc67bce716c856e3973dc42a1003be94f89d8ee0000009b5d5bbe6c10085f3d" "6176f78a19bb8df1804c122fce5078c156e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807" "cbad7645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000" "da40d88d40a6d75bc404156225b7eedefc2b44574b15e2ae496ad01bf007eacb0a28aec868282510" - "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189018ee815000000a7" + "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189f701e815000000a7" "5c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a7a859db500000000362956cd46646a0e" - "222160e5f769bb290366ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d" - "8e47935e0000000034f0386a253c21d94064f6b021281e230094ae20000000d71fd050bf8d85055b" + "222160e5f769bb295703ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d" + "8e47935e0000000034f0386a253c21d94064f6b021281e235f00ae20000000d71fd050bf8d85055b" "00e3756ccdb3455c60ca7b11c66af76e594f24a100000000e143fd52599364e13468f80fd514573f" "b572671c0000006932d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c857ae81200000000" "3e29535402e9b690c628d048eacce745ea213cb1000000b632ef3be6070dafa200187470e9da5570" "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db4532545666937c22a3b000000dc" "c405cbee5016c25200d8901d7a0165fe20744edb6ba04f14a4c73cf500000000a4bab14874afdf54" "e6aae816430607ca0675e09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b" - "6e4c699300000000d9c1e67743efb54e54270e46042e911803894e38000000376feecb80ac245409" - "c0becc271d9c2f67179bff0644399ae7e3c9472e00000000c5cfd9f2343b21362c19a0921dce2f83" - "00defa45000000270b9977e166bee737fe73670c439a644c323b59b4cd20eb7dabea74f700000000" - "f6989d2d6a909e986ff7add5df2c93e05459507b0000000f466554d2ae4d52a8c67b2e48b47003c8" - "1785d3ffdbd9a617df6b3542000000004c5cf8107ba282f4f983821918f93e742d08f0550000006f" - "2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b5159747cf200000000ab2dadc5a39411fd" + "6e4c699300000000d9c1e67743efb54e54270e46042e91186a034e38000000376feecb80ac245409" + "c0becc271d9c2f67179bff0644399ae7df6b3542000000004c5cf8107ba282f4f983821918f93e74" + "2d08f0550000006f2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b51e3c9472e00000000" + "c5cfd9f2343b21362c19a0921dce2f839200fa45000000270b9977e166bee737fe73670c439a644c" + "323b59b4cd20eb7dabea74f700000000f6989d2d6a909e986ff7add5df2c93e05459507b0000000f" + "466554d2ae4d52a8c67b2e48b47003c81785d3ffdbd9a61759747cf200000000ab2dadc5a39411fd" "4ff1116d478987316a553fc2000000cfc6ebe434a7ae8ff040483e310819e3b10db116431ec6f769" "438a72e1000000002495a609675344f7e2e3a5ebaec3c85f0a1742f70abe95c50345132a61eda239" "d9d083c3bf085387046ef8a36f0e9e696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9" - "03dd01f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000" - "0d3c723b91adb0da7c4aa7e7eb5a15bc03015fb98b841fd84cc43c510385b9a4c2aac1d67a909b29" + "cb0301f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000" + "0d3c723b91adb0da7c4aa7e7eb5a15bcde035fb98b841fd84cc43c510385b9a4c2aac1d67a909b29" "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a92409c0b7f0318a" "575a4f8e061db3dd7fde25654a4059d565dbc8a91e3b4457b077ddad3108be69f9b97d05c917ad6b" "10e693bb6e26f2ba90c8e909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38" - "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea01aafdc3a9fe1ec787bc45db7c52a52d" + "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea9a01fdc3a9fe1ec787bc45db7c52a52d" "00bd39a44e8e8bc17c01ac63eca0c1cf5ff7f03a03000000c9a89192c1c8be55281a59d1fd338f35" - "0075f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000" - "24438387def0f4c6544e4b275d9b714600f810d2a9fec17647176b7c07d856e3b883efebc09dd9d6" - "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee018588ffa9fe6cae" + "7e00f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000" + "24438387def0f4c6544e4b275d9b7146a70010d2a9fec17647176b7c07d856e3b883efebc09dd9d6" + "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee7a0188ffa9fe6cae" "426de59560fad65d67c624f285d7174177a47579dda0b6eaa9a84c820300000070b1646d8026e9f1" - "704f1b16286ba2da017ef082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82" + "704f1b16286ba2dabc01f082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82" "fa40546c03000000df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea9fe3e7d75a2f42b50c6a363" "40132378b95c59313bacba64dbe996206e6904f50200000047150b9b14010469823acb72bb89182f" - "00112196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000" - "e79c10acfce165e332a62384ec04e5ba009185ada9fe0070a36dd51323b2c54200154d12f86c260a" - "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98c0221c19ca9fe942f" + "93002196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000" + "e79c10acfce165e332a62384ec04e5bab40085ada9fe0070a36dd51323b2c54200154d12f86c260a" + "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98cb102c19ca9fe942f" "460bcea75481f25e007d0de9a7afe283bd2f22ead05ff72006c83bc0020000004bdade862c224f6f" - "36506ebd455e679c00369bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f" - "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb120335256aa9fe6e5d58099ffc4a503a71" + "36506ebd455e679cef009bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f" + "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb12c503256aa9fe6e5d58099ffc4a503a71" "2350acbd48411f0dc15d2f0f49dad345d966279502000000e06302aba042aaa218dc091e9aa1477f" "6fdc9830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000" - "98c39e7cc282208fefc57ff447036b9501adcb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13" - "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde5301b3ec71a9fe9f25" + "98c39e7cc282208fefc57ff447036b955101cb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13" + "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde533601ec71a9fe9f25" "4ac95883195580410062ed564153e17478f8c3344d89c0bbfaa100fd01000000be184524a6bdc878" - "9cf851782d895bcc03a98489a9fe8c1287e6f7bb020ffdb00012098610e52bb2a16a4008aefd545b" - "0d80684e01000000ba8110fb9733cc24904f288262e6ea77032fa5f8a9feeefa701d120523bd98f2" + "9cf851782d895bcc8d038489a9fe8c1287e6f7bb020ffdb00012098610e52bb2a16a4008aefd545b" + "0d80684e01000000ba8110fb9733cc24904f288262e6ea77a203a5f8a9feeefa701d120523bd98f2" "00098b43cd68be6e3f81268193fd637e9037d7a701000000c47cf0f551e96770a754ac19ef820fe0" - "0031f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000" + "2900f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000" "68cb3bc873b04d937a6ed8f7bc51e54066fed098a9fe048a92d3adc69a84eb47622400207799416a" - "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183600085d627a9feb1cb" + "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183609900d627a9feb1cb" "e491cbbbf9443fd6007eb3c5bf64b671d6f18dbf463f9b83f512dc1c00000000fbab244735d67c61" - "283031667b2d74a102e0b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef" - "a9a89f8700000000fcdf6d9be94030b34774d1d7dddedd9802f0f627a9fe965a87041331b2834bcf" + "283031667b2d74a10302b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef" + "a9a89f8700000000fcdf6d9be94030b34774d1d7dddedd989902f627a9fe965a87041331b2834bcf" "00b4e3ce848518c4e3f6cbf25e5e1b992231bb0200000000173c333cd03bc905b7b899afeb760e3f" - "024a2efca9fe96b89b1bc8f415bd4e77be46bae5a1b3cae76665a268abfe8a41a84e27c100000000" - "cb29efdf672d2fa57fc85ebbe276c5660364192da9fee7af5eb888e9eb37bb046686943b101e1f55" - "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82d03c74828a9fe1e37" + "00022efca9fe96b89b1bc8f415bd4e77be46bae5a1b3cae76665a268abfe8a41a84e27c100000000" + "cb29efdf672d2fa57fc85ebbe276c5661a03192da9fee7af5eb888e9eb37bb046686943b101e1f55" + "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82da1034828a9fe1e37" "1051852c972ea7954079884af257b044fd13a6826a4c619f3d136cac000000009402a4c216772167" - "3f2b02b3256ead1f03ea9bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c"), + "3f2b02b3256ead1f2f039bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c"), [1] = ("54270e46020000006a894e387625da376feecb80ac245409c0becc271d9c2f67179bff0644399ae7" "9c64ed0432d599eaa660ac824b7fae389861419c7a899f2d010000009bf5a5d06776e66a9d80ab13" "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" diff --git a/src/core/platform/tests/test-tc.c b/src/core/platform/tests/test-tc.c index cd9536cc..ee7b861e 100644 --- a/src/core/platform/tests/test-tc.c +++ b/src/core/platform/tests/test-tc.c @@ -57,7 +57,7 @@ test_qdisc1(void) g_ptr_array_add(known, qdisc_new(ifindex, "fq_codel", TC_H_ROOT)); g_ptr_array_add(known, qdisc_new(ifindex, "ingress", TC_H_INGRESS)); - g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + g_assert(nm_platform_tc_sync(NM_PLATFORM_GET, ifindex, known, NULL)); plat = qdiscs_lookup(ifindex); g_assert(plat); g_assert_cmpint(plat->len, ==, 2); @@ -97,7 +97,7 @@ test_qdisc_fq_codel(void) obj->qdisc.fq_codel.quantum = 1000; g_ptr_array_add(known, obj); - g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + g_assert(nm_platform_tc_sync(NM_PLATFORM_GET, ifindex, known, NULL)); plat = qdiscs_lookup(ifindex); g_assert(plat); g_assert_cmpint(plat->len, ==, 1); @@ -136,7 +136,7 @@ test_qdisc_sfq(void) obj->qdisc.sfq.flows = 256; g_ptr_array_add(known, obj); - g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + g_assert(nm_platform_tc_sync(NM_PLATFORM_GET, ifindex, known, NULL)); plat = qdiscs_lookup(ifindex); g_assert(plat); g_assert_cmpint(plat->len, ==, 1); @@ -179,7 +179,7 @@ test_qdisc_tbf(void) obj->qdisc.handle = TC_H_MAKE(0x8005 << 16, 0); g_ptr_array_add(known, obj); - g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + g_assert(nm_platform_tc_sync(NM_PLATFORM_GET, ifindex, known, NULL)); plat = qdiscs_lookup(ifindex); g_assert(plat); g_assert_cmpint(plat->len, ==, 2); @@ -202,7 +202,7 @@ test_qdisc_tbf(void) /*****************************************************************************/ -NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; +NMTstpSetupFunc const _nmtstp_setup_platform_func = nm_linux_platform_setup_with_tc_cache; void _nmtstp_init_tests(int *argc, char ***argv) @@ -213,10 +213,8 @@ _nmtstp_init_tests(int *argc, char ***argv) void _nmtstp_setup_tests(void) { - if (nmtstp_is_root_test()) { - nmtstp_env1_add_test_func("/link/qdisc/1", test_qdisc1, TRUE); - nmtstp_env1_add_test_func("/link/qdisc/fq_codel", test_qdisc_fq_codel, TRUE); - nmtstp_env1_add_test_func("/link/qdisc/sfq", test_qdisc_sfq, TRUE); - nmtstp_env1_add_test_func("/link/qdisc/tbf", test_qdisc_tbf, TRUE); - } + nmtstp_env1_add_test_func("/link/qdisc/1", test_qdisc1, TRUE); + nmtstp_env1_add_test_func("/link/qdisc/fq_codel", test_qdisc_fq_codel, TRUE); + nmtstp_env1_add_test_func("/link/qdisc/sfq", test_qdisc_sfq, TRUE); + nmtstp_env1_add_test_func("/link/qdisc/tbf", test_qdisc_tbf, TRUE); } diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index fefc5d61..e6790f22 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -21,7 +21,7 @@ #include #ifndef aligned_u64 - #define aligned_u64 unsigned long long __attribute__((aligned(8))) +#define aligned_u64 unsigned long long __attribute__((aligned(8))) #endif #include #include @@ -761,7 +761,7 @@ create_pppd_cmd_line(NMPPPManager * self, g_return_val_if_fail(setting != NULL, NULL); #ifndef PPPD_PATH - #define PPPD_PATH NULL +#define PPPD_PATH NULL #endif pppd_binary = nm_utils_find_helper("pppd", PPPD_PATH, err); diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c index b423bf5b..71da97d0 100644 --- a/src/core/settings/nm-settings-connection.c +++ b/src/core/settings/nm-settings-connection.c @@ -346,7 +346,7 @@ _getsettings_cached_get(NMSettingsConnection *self, const NMConnectionSerializat priv->getsettings_cached.options = *options; priv->getsettings_cached.options.seen_bssids = - nm_utils_strv_dup_packed(priv->getsettings_cached.options.seen_bssids, -1); + nm_strv_dup_packed(priv->getsettings_cached.options.seen_bssids, -1); return priv->getsettings_cached.variant; } @@ -382,7 +382,7 @@ _nm_settings_connection_set_connection(NMSettingsConnection * self, NM_SETTING_COMPARE_FLAG_EXACT)) { connection_old = priv->connection; priv->connection = g_object_ref(new_connection); - nmtst_connection_assert_unchanging(priv->connection); + nm_assert_connection_unchanging(priv->connection); _getsettings_cached_clear(priv); _nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(priv->settings); diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c index f9f98de7..b71b9d18 100644 --- a/src/core/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -17,7 +17,7 @@ #include #if HAVE_SELINUX - #include +#include #endif #include "libnm-core-aux-intern/nm-common-macros.h" @@ -1352,7 +1352,7 @@ _connection_changed_track(NMSettings * self, || (_nm_connection_verify(connection, NULL) == NM_SETTING_VERIFY_SUCCESS)); nm_assert(!connection || nm_streq0(uuid, nm_connection_get_uuid(connection))); - nmtst_connection_assert_unchanging(connection); + nm_assert_connection_unchanging(connection); sett_conn_entry = _sett_conn_entries_get(self, uuid) ?: _sett_conn_entries_create_and_add(self, uuid); @@ -3372,7 +3372,7 @@ load_plugins(NMSettings *self, const char *const *plugins, GError **error) continue; } - if (nm_utils_strv_find_first((char **) plugins, iter - plugins, pname) >= 0) { + if (nm_strv_find_first(plugins, iter - plugins, pname) >= 0) { /* the plugin is already mentioned in the list previously. * Don't load a duplicate. */ continue; @@ -3452,7 +3452,7 @@ impl_settings_save_hostname(NMDBusObject * obj, g_variant_get(parameters, "(&s)", &hostname); /* Minimal validation of the hostname */ - if (!nm_hostname_manager_validate_hostname(hostname)) { + if (!nm_utils_validate_hostname(hostname)) { error_code = NM_SETTINGS_ERROR_INVALID_HOSTNAME; error_reason = "The hostname was too long or contained invalid characters"; goto err; @@ -3938,7 +3938,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) priv->connections_len, G_STRUCT_OFFSET(NMSettingsConnection, _connections_lst), TRUE); - g_value_take_boxed(value, nm_utils_strv_make_deep_copied(strv)); + g_value_take_boxed(value, nm_strv_make_deep_copied(strv)); break; case PROP_STARTUP_COMPLETE: g_value_set_boolean(value, !nm_settings_get_startup_complete_blocked_reason(self, FALSE)); diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index 5038ac6a..8fdc01fb 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -848,7 +848,7 @@ _unhandled_specs_from_hashtable(GHashTable *hash) GSList * list = NULL; guint i, l; - keys = nm_utils_strdict_get_keys(hash, TRUE, &l); + keys = nm_strdict_get_keys(hash, TRUE, &l); for (i = l; i > 0;) { i--; list = g_slist_prepend(list, g_strdup(keys[i])); 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 03b347f9..6dd5ef05 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 @@ -31,6 +31,7 @@ #include "nm-setting-ethtool.h" #include "nm-setting-8021x.h" #include "nm-setting-bond.h" +#include "nm-setting-bond-port.h" #include "nm-setting-team.h" #include "nm-setting-team-port.h" #include "nm-setting-bridge.h" @@ -474,7 +475,7 @@ make_connection_setting(const char *file, if (v) { gs_free const char **items = NULL; - items = nm_utils_strsplit_set(v, " "); + items = nm_strsplit_set(v, " "); for (iter = items; iter && *iter; iter++) { if (!nm_setting_connection_add_permission(s_con, "user", *iter, NULL)) PARSE_WARNING("invalid USERS item '%s'", *iter); @@ -490,7 +491,7 @@ make_connection_setting(const char *file, if (v) { gs_free const char **items = NULL; - items = nm_utils_strsplit_set(v, " \t"); + items = nm_strsplit_set(v, " \t"); for (iter = items; iter && *iter; iter++) { if (!nm_setting_connection_add_secondary(s_con, *iter)) PARSE_WARNING("secondary connection UUID '%s' already added", *iter); @@ -633,6 +634,15 @@ make_connection_setting(const char *file, PARSE_WARNING("invalid LLMNR setting"); g_object_set(s_con, NM_SETTING_CONNECTION_LLMNR, i_val, NULL); + i_val = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + if (!svGetValueEnum(ifcfg, + "DNS_OVER_TLS", + nm_setting_connection_dns_over_tls_get_type(), + &i_val, + NULL)) + PARSE_WARNING("invalid DNS_OVER_TLS setting"); + g_object_set(s_con, NM_SETTING_CONNECTION_DNS_OVER_TLS, i_val, NULL); + return NM_SETTING(s_con); } @@ -1036,7 +1046,7 @@ parse_route_line(const char *line, * Maybe later we want to support some form of quotation here. * Which of course, would be incompatible with initscripts. */ - words_free = nm_utils_strsplit_set(line, " \t\n"); + words_free = nm_strsplit_set(line, " \t\n"); words = words_free ?: NM_PTRARRAY_EMPTY(const char *); @@ -1582,7 +1592,7 @@ parse_dns_options(NMSettingIPConfig *ip_config, const char *value) if (!nm_setting_ip_config_has_dns_options(ip_config)) nm_setting_ip_config_clear_dns_options(ip_config, TRUE); - options = nm_utils_strsplit_set(value, " "); + options = nm_strsplit_set(value, " "); if (options) { for (item = options; *item; item++) { if (!nm_setting_ip_config_add_dns_option(ip_config, *item)) @@ -1974,26 +1984,27 @@ make_ip4_setting(shvarFile *ifcfg, /* DNS servers * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ - for (i = 1; i <= 10; i++) { + for (i = 1; i < 10000; i++) { char tag[256]; numbered_tag(tag, "DNS", i); nm_clear_g_free(&value); v = svGetValueStr(ifcfg, tag, &value); - if (v) { - if (nm_utils_ipaddr_is_valid(AF_INET, v)) { - if (!nm_setting_ip_config_add_dns(s_ip4, v)) - PARSE_WARNING("duplicate DNS server %s", tag); - } else if (nm_utils_ipaddr_is_valid(AF_INET6, v)) { - /* Ignore IPv6 addresses */ - } else { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid DNS server address '%s'", - v); - return NULL; - } + if (!v) + break; + + if (nm_utils_ipaddr_is_valid(AF_INET, v)) { + if (!nm_setting_ip_config_add_dns(s_ip4, v)) + PARSE_WARNING("duplicate DNS server %s", tag); + } else if (nm_utils_ipaddr_is_valid(AF_INET6, v)) { + /* Ignore IPv6 addresses */ + } else { + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid DNS server address '%s'", + v); + return NULL; } } @@ -2003,7 +2014,7 @@ make_ip4_setting(shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set(v, " "); + searches = nm_strsplit_set(v, " "); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search(s_ip4, *item)) @@ -2063,7 +2074,7 @@ make_ip4_setting(shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set(v, " "); + searches = nm_strsplit_set(v, " "); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search(s_ip4, *item)) @@ -2249,6 +2260,7 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip; NMSettingIP6ConfigPrivacy ip6_privacy_val; guint32 route_table; + gboolean is_disabled; s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); @@ -2375,10 +2387,9 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea NULL); /* Don't bother to read IP, DNS and routes when IPv6 is disabled */ - if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) - return NM_SETTING(g_steal_pointer(&s_ip6)); + is_disabled = NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED); nm_clear_g_free(&value); v = svGetValueStr(ifcfg, "DHCPV6_DUID", &value); @@ -2437,16 +2448,24 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea ipv6addr_secondaries ?: "", NULL); - list = nm_utils_strsplit_set(value, " "); - for (iter = list, i = 0; iter && *iter; iter++, i++) { - NMIPAddress *addr = NULL; + list = nm_strsplit_set(value, " "); + if (list) { + if (is_disabled) + PARSE_WARNING("ignore IPv6 addresses with method disabled/ignore"); + else { + for (iter = list, i = 0; *iter; iter++, i++) { + nm_auto_unref_ip_address NMIPAddress *addr = NULL; - if (!parse_full_ip6_address(ifcfg, *iter, i, &addr, error)) - return NULL; + if (!parse_full_ip6_address(ifcfg, *iter, i, &addr, is_disabled ? NULL : error)) { + if (is_disabled) + break; + return NULL; + } - if (!nm_setting_ip_config_add_address(s_ip6, addr)) - PARSE_WARNING("duplicate IP6 address"); - nm_ip_address_unref(addr); + if (!nm_setting_ip_config_add_address(s_ip6, addr)) + PARSE_WARNING("duplicate IP6 address"); + } + } } /* Gateway */ @@ -2462,18 +2481,20 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea } if (v) { char *ptr; + if ((ptr = strchr(v, '%')) != NULL) *ptr = '\0'; /* remove %interface prefix if present */ if (!nm_utils_ipaddr_is_valid(AF_INET6, v)) { - g_set_error(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid IP6 address '%s'", - v); - return NULL; - } - - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, v, NULL); + if (!is_disabled) { + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid IP6 address '%s'", + v); + return NULL; + } + } else + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, v, NULL); } } @@ -2497,23 +2518,27 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea /* DNS servers * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting()) */ - for (i = 1; i <= 10; i++) { + for (i = 1; i < 10000; i++) { char tag[256]; numbered_tag(tag, "DNS", i); nm_clear_g_free(&value); v = svGetValueStr(ifcfg, tag, &value); - if (!v) { - /* all done */ + if (!v) break; - } if (nm_utils_ipaddr_is_valid(AF_INET6, v)) { + if (is_disabled) { + PARSE_WARNING("ignore DNS server addresses with method disabled/ignore"); + break; + } if (!nm_setting_ip_config_add_dns(s_ip6, v)) PARSE_WARNING("duplicate DNS server %s", tag); } else if (nm_utils_ipaddr_is_valid(AF_INET, v)) { /* Ignore IPv4 addresses */ } else { + if (is_disabled) + continue; g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -2540,11 +2565,15 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set(v, " "); + searches = nm_strsplit_set(v, " "); if (searches) { - for (iter = searches; *iter; iter++) { - if (!nm_setting_ip_config_add_dns_search(s_ip6, *iter)) - PARSE_WARNING("duplicate DNS domain '%s'", *iter); + if (is_disabled) { + PARSE_WARNING("ignore IPV6_DOMAIN with method disabled/ignore"); + } else { + for (iter = searches; *iter; iter++) { + if (!nm_setting_ip_config_add_dns_search(s_ip6, *iter)) + PARSE_WARNING("duplicate DNS domain '%s'", *iter); + } } } } @@ -2957,7 +2986,7 @@ read_dcb_percent_array(shvarFile * ifcfg, return TRUE; } - split = nm_utils_strsplit_set(val, ","); + split = nm_strsplit_set(val, ","); if (NM_PTRARRAY_LEN(split) != 8) { PARSE_WARNING("invalid %s percentage list value '%s'", prop, val); g_set_error_literal(error, @@ -3001,6 +3030,7 @@ make_dcb_setting(shvarFile *ifcfg, NMSetting **out_setting, GError **error) gs_unref_object NMSettingDcb *s_dcb = NULL; gboolean dcb_on; NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE; + gs_free char * val = NULL; g_return_val_if_fail(out_setting, FALSE); *out_setting = NULL; @@ -3020,21 +3050,18 @@ make_dcb_setting(shvarFile *ifcfg, NMSetting **out_setting, GError **error) error)) { return FALSE; } - if (nm_setting_dcb_get_app_fcoe_flags(s_dcb) & NM_SETTING_DCB_FLAG_ENABLE) { - gs_free char *val = NULL; - val = svGetValueStr_cp(ifcfg, KEY_DCB_APP_FCOE_MODE); - if (val) { - if (NM_IN_STRSET(val, NM_SETTING_DCB_FCOE_MODE_FABRIC, NM_SETTING_DCB_FCOE_MODE_VN2VN)) - g_object_set(G_OBJECT(s_dcb), NM_SETTING_DCB_APP_FCOE_MODE, val, NULL); - else { - PARSE_WARNING("invalid FCoE mode '%s'", val); - g_set_error_literal(error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "invalid FCoE mode"); - return FALSE; - } + val = svGetValueStr_cp(ifcfg, KEY_DCB_APP_FCOE_MODE); + if (val) { + if (NM_IN_STRSET(val, NM_SETTING_DCB_FCOE_MODE_FABRIC, NM_SETTING_DCB_FCOE_MODE_VN2VN)) + g_object_set(G_OBJECT(s_dcb), NM_SETTING_DCB_APP_FCOE_MODE, val, NULL); + else { + PARSE_WARNING("invalid FCoE mode '%s'", val); + g_set_error_literal(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "invalid FCoE mode"); + return FALSE; } } @@ -3376,7 +3403,7 @@ fill_wpa_ciphers(shvarFile *ifcfg, NMSettingWirelessSecurity *wsec, gboolean gro if (!p) return TRUE; - list = nm_utils_strsplit_set(p, " "); + list = nm_strsplit_set(p, " "); for (iter = list; iter && *iter; iter++, i++) { if (!strcmp(*iter, "CCMP")) { if (group) @@ -3612,7 +3639,7 @@ parse_8021x_phase2_auth(shvarFile * ifcfg, } inner_auth = g_ascii_strdown(v, -1); - list = nm_utils_strsplit_set(inner_auth, " "); + list = nm_strsplit_set(inner_auth, " "); for (iter = list; iter && *iter; iter++) { if (NM_IN_STRSET(*iter, "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5")) { if (num_auth == 0) { @@ -3787,7 +3814,7 @@ eap_fast_reader(const char * eap_method, if (fast_provisioning) { gs_free const char **list = NULL; - list = nm_utils_strsplit_set(fast_provisioning, " \t"); + list = nm_strsplit_set(fast_provisioning, " \t"); for (iter = list; iter && *iter; iter++) { if (strcmp(*iter, "allow-unauth") == 0) allow_unauth = TRUE; @@ -3865,7 +3892,7 @@ read_8021x_list_value(shvarFile * ifcfg, if (!v) return; - strv = nm_utils_strsplit_set(v, " \t"); + strv = nm_strsplit_set(v, " \t"); if (strv) g_object_set(setting, prop_name, strv, NULL); } @@ -3892,7 +3919,7 @@ fill_8021x(shvarFile *ifcfg, const char *file, const char *key_mgmt, gboolean wi return NULL; } - list = nm_utils_strsplit_set(v, " "); + list = nm_strsplit_set(v, " "); s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); @@ -4245,7 +4272,7 @@ transform_hwaddr_blacklist(const char *blacklist) const char **strv; gsize i, j; - strv = nm_utils_strsplit_set(blacklist, " \t"); + strv = nm_strsplit_set(blacklist, " \t"); if (!strv) return NULL; for (i = 0, j = 0; strv[j]; j++) { @@ -4714,7 +4741,7 @@ parse_ethtool_option(const char * value, gs_free const char **words = NULL; NMEthtoolType ethtool_type = NM_ETHTOOL_TYPE_UNKNOWN; - words = nm_utils_strsplit_set(value, " \t\n"); + words = nm_strsplit_set(value, " \t\n"); if (!words) return; @@ -4976,7 +5003,7 @@ parse_ethtool_options(shvarFile *ifcfg, NMConnection *connection) gs_free const char **opts = NULL; const char *const * iter; - opts = nm_utils_strsplit_set(ethtool_opts, ";"); + opts = nm_strsplit_set(ethtool_opts, ";"); for (iter = opts; iter && iter[0]; iter++) { /* in case of repeated wol_passwords, parse_ethtool_option() * will do the right thing and clear wol_password before resetting. */ @@ -5084,7 +5111,7 @@ make_wired_setting(shvarFile *ifcfg, const char *file, NMSetting8021x **s_8021x, gs_free const char **chans = NULL; guint32 num_chans; - chans = nm_utils_strsplit_set(cvalue, ","); + chans = nm_strsplit_set(cvalue, ","); num_chans = NM_PTRARRAY_LEN(chans); if (num_chans < 2 || num_chans > 3) { PARSE_WARNING("invalid SUBCHANNELS '%s' (%u channels, 2 or 3 expected)", @@ -5456,7 +5483,7 @@ make_bond_setting(shvarFile *ifcfg, const char *file, GError **error) gs_free const char **items = NULL; const char *const * iter; - items = nm_utils_strsplit_set(v, " "); + items = nm_strsplit_set(v, " "); for (iter = items; iter && *iter; iter++) { gs_free char *key = NULL; const char * val; @@ -5474,6 +5501,31 @@ make_bond_setting(shvarFile *ifcfg, const char *file, GError **error) return (NMSetting *) s_bond; } +static NMSetting * +make_bond_port_setting(shvarFile *ifcfg) +{ + NMSetting * s_port = NULL; + gs_free char *value_to_free = NULL; + const char * value; + guint queue_id; + + g_return_val_if_fail(ifcfg != NULL, FALSE); + + value = svGetValue(ifcfg, "BOND_PORT_QUEUE_ID", &value_to_free); + if (value) { + s_port = nm_setting_bond_port_new(); + queue_id = + _nm_utils_ascii_str_to_uint64(value, 10, 0, G_MAXUINT16, NM_BOND_PORT_QUEUE_ID_DEF); + if (errno != 0) { + PARSE_WARNING("Invalid bond port queue_id value '%s'", value); + return s_port; + } + g_object_set(G_OBJECT(s_port), NM_SETTING_BOND_PORT_QUEUE_ID, queue_id, NULL); + } + + return s_port; +} + static NMConnection * bond_connection_from_ifcfg(const char *file, shvarFile *ifcfg, GError **error) { @@ -5766,7 +5818,7 @@ handle_bridging_opts(NMSetting * setting, gs_free const char **items = NULL; const char *const * iter; - items = nm_utils_strsplit_set(value, " "); + items = nm_strsplit_set(value, " "); for (iter = items; iter && *iter; iter++) { gs_free char *key = NULL; const char * val; @@ -6027,7 +6079,7 @@ parse_prio_map_list(NMSettingVlan *s_vlan, shvarFile *ifcfg, const char *key, NM v = svGetValueStr(ifcfg, key, &value); if (!v) return; - list = nm_utils_strsplit_set(v, ","); + list = nm_strsplit_set(v, ","); for (iter = list; iter && *iter; iter++) { if (!strchr(*iter, ':')) @@ -6138,7 +6190,7 @@ make_vlan_setting(shvarFile *ifcfg, const char *file, GError **error) gs_free const char **strv = NULL; const char *const * ptr; - strv = nm_utils_strsplit_set(v, ", "); + strv = nm_strsplit_set(v, ", "); for (ptr = strv; ptr && *ptr; ptr++) { if (nm_streq(*ptr, "GVRP") && gvrp == -1) vlan_flags |= NM_VLAN_FLAG_GVRP; @@ -6284,7 +6336,7 @@ check_dns_search_domains(shvarFile *ifcfg, NMSetting *s_ip4, NMSetting *s_ip6) gs_free const char **searches = NULL; const char *const * item; - searches = nm_utils_strsplit_set(v, " "); + searches = nm_strsplit_set(v, " "); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search(NM_SETTING_IP_CONFIG(s_ip6), *item)) @@ -6641,6 +6693,10 @@ connection_from_file_full(const char *filename, if (setting) nm_connection_add_setting(connection, setting); + setting = make_bond_port_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); + setting = make_team_port_setting(main_ifcfg); if (setting) nm_connection_add_setting(connection, setting); diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c index 134bdf68..3feb4440 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c @@ -112,7 +112,7 @@ nms_ifcfg_rh_storage_new_connection(NMSIfcfgRHPlugin * plugin, nm_assert(NM_IS_CONNECTION(connection_take)); nm_assert(_nm_connection_verify(connection_take, NULL) == NM_SETTING_VERIFY_SUCCESS); - nmtst_connection_assert_unchanging(connection_take); + nm_assert_connection_unchanging(connection_take); self = _storage_new(plugin, nm_connection_get_uuid(connection_take), filename); self->connection = connection_take; diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index febfc120..1afdf8ee 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -827,6 +827,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("BAND", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BONDING_MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BONDING_OPTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("BOND_PORT_QUEUE_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BOOTPROTO", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BRIDGE", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BRIDGE_MACADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN), @@ -891,6 +892,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("DHCPv6_DUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DHCPv6_IAID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DNS", NMS_IFCFG_KEY_TYPE_IS_NUMBERED), + _KEY_TYPE("DNS_OVER_TLS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("DOMAIN", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("ESSID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("ETHTOOL_OPTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index b7751ec9..6b396a9a 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -33,7 +33,7 @@ typedef struct { NMSIfcfgKeyTypeFlags key_flags; } NMSIfcfgKeyTypeInfo; -extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[251]; +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[253]; const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); 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 ef85b6bf..263c9253 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 @@ -19,6 +19,7 @@ #include "libnm-glib-aux/nm-str-buf.h" #include "libnm-glib-aux/nm-io-utils.h" #include "nm-manager.h" +#include "nm-setting-bond-port.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" @@ -204,18 +205,18 @@ write_object(NMSetting8021x * s_8021x, g_return_val_if_fail(ifcfg != NULL, FALSE); g_return_val_if_fail(objtype != NULL, FALSE); - scheme = (*(objtype->vtable->scheme_func)) (s_8021x); + scheme = (*(objtype->vtable->scheme_func))(s_8021x); switch (scheme) { case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: break; case NM_SETTING_802_1X_CK_SCHEME_BLOB: - blob = (*(objtype->vtable->blob_func)) (s_8021x); + blob = (*(objtype->vtable->blob_func))(s_8021x); break; case NM_SETTING_802_1X_CK_SCHEME_PATH: - value = (*(objtype->vtable->path_func)) (s_8021x); + value = (*(objtype->vtable->path_func))(s_8021x); break; case NM_SETTING_802_1X_CK_SCHEME_PKCS11: - value = (*(objtype->vtable->uri_func)) (s_8021x); + value = (*(objtype->vtable->uri_func))(s_8021x); break; default: g_set_error(error, @@ -228,8 +229,8 @@ write_object(NMSetting8021x * s_8021x, /* Set the password for certificate/private key. */ nm_sprintf_buf(secret_name, "%s_PASSWORD", objtype->ifcfg_rh_key); nm_sprintf_buf(secret_flags, "%s_PASSWORD_FLAGS", objtype->ifcfg_rh_key); - password = (*(objtype->vtable->passwd_func)) (s_8021x); - flags = (*(objtype->vtable->pwflag_func)) (s_8021x); + password = (*(objtype->vtable->passwd_func))(s_8021x); + flags = (*(objtype->vtable->pwflag_func))(s_8021x); set_secret(ifcfg, secrets, secret_name, password, secret_flags, flags); if (!objtype->vtable->format_func) @@ -1442,12 +1443,12 @@ write_vlan_setting(NMConnection *connection, shvarFile *ifcfg, gboolean *wired, svSetValueBoolean(ifcfg, "REORDER_HDR", NM_FLAGS_HAS(vlan_flags, NM_VLAN_FLAG_REORDER_HEADERS)); svSetValueBoolean(ifcfg, "GVRP", NM_FLAGS_HAS(vlan_flags, NM_VLAN_FLAG_GVRP)); - nm_utils_strbuf_init(s_buf, &s_buf_ptr, &s_buf_len); + nm_strbuf_init_arr(s_buf, &s_buf_ptr, &s_buf_len); if (NM_FLAGS_HAS(vlan_flags, NM_VLAN_FLAG_LOOSE_BINDING)) - nm_utils_strbuf_append_str(&s_buf_ptr, &s_buf_len, "LOOSE_BINDING"); + nm_strbuf_append_str(&s_buf_ptr, &s_buf_len, "LOOSE_BINDING"); if (!NM_FLAGS_HAS(vlan_flags, NM_VLAN_FLAG_REORDER_HEADERS)) - nm_utils_strbuf_append(&s_buf_ptr, &s_buf_len, "%sNO_REORDER_HDR", s_buf[0] ? "," : ""); + nm_strbuf_append(&s_buf_ptr, &s_buf_len, "%sNO_REORDER_HDR", s_buf[0] ? "," : ""); svSetValueStr(ifcfg, "VLAN_FLAGS", s_buf); @@ -1888,6 +1889,16 @@ write_bridge_port_setting(NMConnection *connection, shvarFile *ifcfg, GError **e return TRUE; } +static void +write_bond_port_setting(NMConnection *connection, shvarFile *ifcfg) +{ + NMSettingBondPort *s_port; + + s_port = _nm_connection_get_setting(connection, NM_TYPE_SETTING_BOND_PORT); + if (s_port) + svSetValueInt64(ifcfg, "BOND_PORT_QUEUE_ID", nm_setting_bond_port_get_queue_id(s_port)); +} + static gboolean write_team_port_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) { @@ -2020,8 +2031,7 @@ write_dcb_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) "APP_FCOE", nm_setting_dcb_get_app_fcoe_flags(s_dcb), nm_setting_dcb_get_app_fcoe_priority(s_dcb)); - if (nm_setting_dcb_get_app_fcoe_flags(s_dcb) & NM_SETTING_DCB_FLAG_ENABLE) - svSetValueStr(ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode(s_dcb)); + svSetValueStr(ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode(s_dcb)); write_dcb_app(ifcfg, "APP_ISCSI", @@ -2076,6 +2086,7 @@ write_connection_setting(NMSettingConnection *s_con, shvarFile *ifcfg) gint32 vint32; NMSettingConnectionMdns mdns; NMSettingConnectionLlmnr llmnr; + NMSettingConnectionDnsOverTls dns_over_tls; guint32 vuint32; const char * tmp, *mud_url; @@ -2259,6 +2270,14 @@ write_connection_setting(NMSettingConnection *s_con, shvarFile *ifcfg) if (llmnr != NM_SETTING_CONNECTION_LLMNR_DEFAULT) { svSetValueEnum(ifcfg, "LLMNR", nm_setting_connection_llmnr_get_type(), llmnr); } + + dns_over_tls = nm_setting_connection_get_dns_over_tls(s_con); + if (dns_over_tls != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) { + svSetValueEnum(ifcfg, + "DNS_OVER_TLS", + nm_setting_connection_dns_over_tls_get_type(), + dns_over_tls); + } } static char * @@ -2685,12 +2704,11 @@ write_dns_setting(shvarFile *ifcfg, NMConnection *connection, int addr_family) } } -static gboolean +static void write_ip4_setting(NMConnection *connection, shvarFile * ifcfg, shvarFile ** out_route_content_svformat, - GString ** out_route_content, - GError ** error) + GString ** out_route_content) { NMSettingIPConfig * s_ip4; const char * value; @@ -2713,7 +2731,7 @@ write_ip4_setting(NMConnection *connection, s_ip4 = nm_connection_get_setting_ip4_config(connection); if (!s_ip4) - return TRUE; + return; method = nm_setting_ip_config_get_method(s_ip4); @@ -2722,7 +2740,7 @@ write_ip4_setting(NMConnection *connection, method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - return TRUE; + return; num = nm_setting_ip_config_get_num_addresses(s_ip4); @@ -2881,8 +2899,6 @@ write_ip4_setting(NMConnection *connection, } svSetValueStr(ifcfg, "DHCP_REJECT_SERVERS", str->str); } - - return TRUE; } static void @@ -2968,11 +2984,8 @@ write_ip4_aliases(NMConnection *connection, const char *base_ifcfg_path) } } -static gboolean -write_ip6_setting(NMConnection *connection, - shvarFile * ifcfg, - GString ** out_route6_content, - GError ** error) +static void +write_ip6_setting(NMConnection *connection, shvarFile *ifcfg, GString **out_route6_content) { NMSettingIPConfig * s_ip6; const char * value; @@ -2991,17 +3004,15 @@ write_ip6_setting(NMConnection *connection, s_ip6 = nm_connection_get_setting_ip6_config(connection); if (!s_ip6) - return TRUE; + return; value = nm_setting_ip_config_get_method(s_ip6); g_assert(value); if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { svSetValueStr(ifcfg, "IPV6INIT", "no"); - return TRUE; } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { svSetValueStr(ifcfg, "IPV6_DISABLED", "yes"); svSetValueStr(ifcfg, "IPV6INIT", "no"); - return TRUE; } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { svSetValueStr(ifcfg, "IPV6INIT", "yes"); svSetValueStr(ifcfg, "IPV6_AUTOCONF", "yes"); @@ -3148,8 +3159,6 @@ write_ip6_setting(NMConnection *connection, write_res_options(ifcfg, s_ip6, "IPV6_RES_OPTIONS"); NM_SET_OUT(out_route6_content, write_route_file(s_ip6)); - - return TRUE; } static void @@ -3228,10 +3237,11 @@ do_write_construct(NMConnection * connection, GError ** error) { NMSettingConnection * s_con; - nm_auto_shvar_file_close shvarFile *ifcfg = NULL; - gs_free char * ifcfg_name = NULL; - gs_free char * route_path = NULL; - gs_free char * route6_path = NULL; + nm_auto_shvar_file_close shvarFile *ifcfg = NULL; + const char * ifcfg_name; + gs_free char * ifcfg_name_free = NULL; + gs_free char * route_path = NULL; + gs_free char * route6_path = NULL; const char * type; gs_unref_hashtable GHashTable *blobs = NULL; gs_unref_hashtable GHashTable *secrets = NULL; @@ -3255,11 +3265,7 @@ do_write_construct(NMConnection * connection, if (filename) { /* For existing connections, 'filename' should be full path to ifcfg file */ - ifcfg = svOpenFile(filename, error); - if (!ifcfg) - return FALSE; - - ifcfg_name = g_strdup(filename); + ifcfg_name = filename; } else if (ifcfg_dir) { gs_free char *escaped = NULL; int i_path; @@ -3280,21 +3286,27 @@ do_write_construct(NMConnection * connection, if (g_file_test(path_candidate, G_FILE_TEST_EXISTS)) continue; - ifcfg_name = g_steal_pointer(&path_candidate); + ifcfg_name_free = g_steal_pointer(&path_candidate); break; } - if (!ifcfg_name) { + if (!ifcfg_name_free) { g_set_error_literal(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Failed to find usable ifcfg file name"); return FALSE; } + ifcfg_name = ifcfg_name_free; + } else { + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "No file name given for storing profile to ifcfg-rh"); + g_return_val_if_reached(FALSE); + } - ifcfg = svCreateFile(ifcfg_name); - } else - ifcfg = svCreateFile("/tmp/ifcfg-dummy"); + ifcfg = svCreateFile(ifcfg_name); route_path = utils_get_route_path(svFileGetName(ifcfg)); if (!route_path) { @@ -3377,6 +3389,8 @@ do_write_construct(NMConnection * connection, if (!write_bridge_port_setting(connection, ifcfg, error)) return FALSE; + write_bond_port_setting(connection, ifcfg); + if (!write_team_port_setting(connection, ifcfg, error)) return FALSE; @@ -3441,15 +3455,12 @@ do_write_construct(NMConnection * connection, } else route_ignore = FALSE; - if (!write_ip4_setting(connection, - ifcfg, - !route_ignore && route_path_is_svformat ? &route_content_svformat : NULL, - !route_ignore && route_path_is_svformat ? NULL : &route_content, - error)) - return FALSE; + write_ip4_setting(connection, + ifcfg, + !route_ignore && route_path_is_svformat ? &route_content_svformat : NULL, + !route_ignore && route_path_is_svformat ? NULL : &route_content); - if (!write_ip6_setting(connection, ifcfg, !route_ignore ? &route6_content : NULL, error)) - return FALSE; + write_ip6_setting(connection, ifcfg, !route_ignore ? &route6_content : NULL); write_ip_routing_rules(connection, ifcfg, route_ignore); diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected index 240cd5c1..d2f5c453 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected @@ -16,6 +16,8 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="System test-wired-802-1X-subj-matches" UUID=${UUID} DEVICE=eth0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected index b288c04a..ccc0f35a 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected @@ -11,6 +11,9 @@ GATEWAY=1.1.1.1 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write Bond Main" UUID=${UUID} DEVICE=bond0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected index 80e96921..d4a978b6 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected @@ -5,6 +5,9 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write Permissions" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected index d3db19b2..f1b01a21 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected @@ -11,6 +11,9 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write Wifi LEAP" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected index 32db7262..60540fbe 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected @@ -10,6 +10,9 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write Wifi WEP 104 ASCII" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected index cc29a2cc..fe864c43 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected @@ -17,6 +17,8 @@ IPV4_FAILURE_FATAL=no ACD_TIMEOUT=400 ARPING_WAIT=1 IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="Test Write Wired Static Routes" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected index 9499278e..908cb917 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected @@ -8,6 +8,8 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="Test Write Wired with Match setting" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected index 44eb777c..6ad151aa 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected @@ -17,6 +17,8 @@ PREFIX=24 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="Vlan test-vlan-interface" UUID=${UUID} DEVICE=vlan43 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected index 56e233cc..fef36f2f 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected @@ -4,7 +4,6 @@ DCB_APP_FCOE_ENABLE=yes DCB_APP_FCOE_ADVERTISE=yes DCB_APP_FCOE_WILLING=yes DCB_APP_FCOE_PRIORITY=5 -DCB_APP_FCOE_MODE=fabric DCB_APP_ISCSI_ENABLE=yes DCB_APP_ISCSI_ADVERTISE=yes DCB_APP_ISCSI_WILLING=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected index ead3a047..1f5e04ff 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected @@ -8,6 +8,8 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="random wifi connection" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected index 7bc1ae6c..3dcdbda0 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected @@ -8,6 +8,8 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="random wifi connection 2" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-port b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-port new file mode 100644 index 00000000..111924c0 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-port @@ -0,0 +1,9 @@ +TYPE=Ethernet +NAME=eth0 +UUID=43737e70-7c4f-4b67-9f4f-6d2d4747b1ff +DEVICE=eth0 +ONBOOT=yes +LLDP=no +MASTER=bond99 +SLAVE=yes +BOND_PORT_QUEUE_ID=1 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected index cae51b89..b3199c01 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected @@ -6,6 +6,8 @@ DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6_DISABLED=yes IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="Test Write Wired Disabled IP6" UUID=${UUID} ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected index c882c479..a77c615d 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected @@ -12,6 +12,9 @@ GATEWAY=1.1.1.1 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write SR-IOV config" UUID=${UUID} DEVICE=eth0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected index 8197f320..41714df6 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected @@ -6,6 +6,8 @@ BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME=test-static-routes-legacy UUID=ba60d05a-7898-820d-c2db-427a88f8f2a5 DEVICE=eth0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected index 4df768b4..1125ef55 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected @@ -9,6 +9,9 @@ GATEWAY=1.1.1.1 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write TC config" UUID=${UUID} DEVICE=eth0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected index a67ca598..d87efd72 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected @@ -10,6 +10,9 @@ GATEWAY=1.1.1.1 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy NAME="Test Write TC config" UUID=${UUID} DEVICE=eth0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected index a7be14ce..2eaec850 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-vlanid-use.cexpected @@ -9,6 +9,8 @@ HWADDR= PROXY_METHOD=none BROWSER_ONLY=no IPV6INIT=no +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no NAME="Vlan test-vlan-vlanid-use" UUID=${UUID} DEVICE=eth0.9 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 d9829f84..b1cfdfec 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 @@ -167,9 +167,8 @@ _assert_expected_content(NMConnection *connection, const char *filename, const c g_string_erase(str, i, NM_STRLEN("${UUID}")); g_string_insert_len(str, i, uuid, j); - g_free(content_expectd); - len_expectd = str->len; - content_expectd = g_string_free(str, FALSE); + len_expectd = str->len; + nm_strdup_reset_take(&content_expectd, g_string_free(str, FALSE)); i += j; continue; } @@ -344,7 +343,7 @@ _writer_new_connection_reread(NMConnection * connection, { gboolean success; GError * error = NULL; - char * filename = NULL; + gs_free char * filename = NULL; gs_unref_object NMConnection *con_verified = NULL; gs_unref_object NMConnection *reread_copy = NULL; NMConnection **reread = out_reread ?: ((nmtst_get_rand_uint32() % 2) ? &reread_copy : NULL); @@ -372,11 +371,9 @@ _writer_new_connection_reread(NMConnection * connection, _assert_expected_content(con_verified, filename, expected); if (out_filename) - *out_filename = filename; - else { + *out_filename = g_steal_pointer(&filename); + else nmtst_file_unlink(filename); - g_free(filename); - } } static void @@ -467,12 +464,10 @@ test_read_netmask_1(void) connection = _connection_from_file(FILENAME, NULL, TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System netmask-1"); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpuint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); g_assert(ip4_addr); @@ -501,12 +496,12 @@ verify_cert_or_key(NMSetting8021x *s_compare, const char * privkey_password, const char * property) { - NMSetting8021x * s_8021x; - GError * error = NULL; - gboolean success = FALSE; - const char * expected = NULL, *setting = NULL; - gboolean phase2 = FALSE; - NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + gs_unref_object NMSetting8021x *s_8021x = NULL; + GError * error = NULL; + gboolean success = FALSE; + const char * expected = NULL, *setting = NULL; + gboolean phase2 = FALSE; + NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; if (strstr(property, "phase2")) phase2 = TRUE; @@ -615,28 +610,24 @@ verify_cert_or_key(NMSetting8021x *s_compare, setting = nm_setting_802_1x_get_private_key_path(s_compare); } g_assert_cmpstr(setting, ==, expected); - - g_object_unref(s_8021x); return TRUE; } static void test_read_basic(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - const char * mac; - char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + const char * mac; + char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-minimal", NULL, TYPE_ETHERNET, NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-minimal"); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); @@ -647,47 +638,38 @@ test_read_basic(void) * depending on where the tests are run. */ - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - /* MAC address */ mac = nm_setting_wired_get_mac_address(s_wired); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, ETH_ALEN)); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); g_assert(nm_setting_ip_config_get_never_default(s_ip4) == FALSE); - /* ===== IPv6 SETTING ===== */ - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE); g_assert(nm_setting_ip_config_get_never_default(s_ip6) == FALSE); - - g_object_unref(connection); } static void test_read_miscellaneous_variables(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - char * expected_mac_blacklist[3] = {"00:16:41:11:22:88", + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + char * expected_mac_blacklist[3] = {"00:16:41:11:22:88", "00:16:41:11:22:99", "6a:5d:5a:fa:dd:f0"}; - int mac_blacklist_num, i; - guint64 expected_timestamp = 0; + int mac_blacklist_num, i; + guint64 expected_timestamp = 0; NMTST_EXPECT_NM_WARN("*invalid MAC in HWADDR_BLACKLIST 'XX:aa:invalid'*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-misc-variables", @@ -696,19 +678,14 @@ test_read_miscellaneous_variables(void) NULL); g_test_assert_expected_messages(); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, expected_timestamp); g_assert(nm_setting_connection_get_autoconnect(s_con)); g_assert_cmpint(nm_setting_connection_get_autoconnect_retries(s_con), ==, 100); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - /* MAC blacklist */ mac_blacklist_num = nm_setting_wired_get_num_mac_blacklist_items(s_wired); g_assert_cmpint(mac_blacklist_num, ==, 3); for (i = 0; i < mac_blacklist_num; i++) @@ -717,26 +694,22 @@ test_read_miscellaneous_variables(void) expected_mac_blacklist[i], -1)); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); g_assert(nm_setting_ip_config_get_never_default(s_ip4) == FALSE); - - g_object_unref(connection); } static void test_read_variables_corner_cases(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - const char * mac; - char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + const char * mac; + char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; NMTST_EXPECT_NM_WARN("*key NAME is badly quoted and is treated as \"\"*"); NMTST_EXPECT_NM_WARN("*key ZONE is badly quoted and is treated as \"\"*"); @@ -746,9 +719,7 @@ test_read_variables_corner_cases(void) NULL); g_test_assert_expected_messages(); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-variables-corner-cases-1"); @@ -756,34 +727,27 @@ test_read_variables_corner_cases(void) g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0); - /* MAC address */ mac = nm_setting_wired_get_mac_address(s_wired); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, ETH_ALEN)); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); g_assert(nm_setting_ip_config_get_never_default(s_ip4) == FALSE); - - g_object_unref(connection); } static void test_read_unmanaged(void) { - NMConnection * connection; - NMSettingConnection *s_con; - char * unhandled_spec = NULL; - guint64 expected_timestamp = 0; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + gs_free char * unhandled_spec = NULL; + guint64 expected_timestamp = 0; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-nm-controlled", NULL, @@ -791,24 +755,19 @@ test_read_unmanaged(void) &unhandled_spec); g_assert_cmpstr(unhandled_spec, ==, "unmanaged:mac:00:11:22:33:f8:9f"); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-nm-controlled"); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, expected_timestamp); g_assert(nm_setting_connection_get_autoconnect(s_con)); - - g_free(unhandled_spec); - g_object_unref(connection); } static void test_read_unmanaged_unrecognized(void) { - NMConnection * connection; - NMSettingConnection *s_con; - gs_free char * unhandled_spec = NULL; - guint64 expected_timestamp = 0; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + gs_free char * unhandled_spec = NULL; + guint64 expected_timestamp = 0; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-nm-controlled-unrecognized", NULL, @@ -816,22 +775,18 @@ test_read_unmanaged_unrecognized(void) &unhandled_spec); g_assert_cmpstr(unhandled_spec, ==, "unmanaged:interface-name:=ipoac0"); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "PigeonNet"); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, expected_timestamp); - - g_object_unref(connection); } static void test_read_unrecognized(void) { - NMConnection * connection; - NMSettingConnection *s_con; - gs_free char * unhandled_spec = NULL; - guint64 expected_timestamp = 0; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + gs_free char * unhandled_spec = NULL; + guint64 expected_timestamp = 0; NMTST_EXPECT_NM_WARN("*key NAME is badly quoted and is treated as \"\"*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-unrecognized", @@ -841,30 +796,26 @@ test_read_unrecognized(void) g_test_assert_expected_messages(); g_assert_cmpstr(unhandled_spec, ==, "unrecognized:mac:00:11:22:33"); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-unrecognized"); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, expected_timestamp); - - g_object_unref(connection); } static void test_read_wired_static(gconstpointer test_data) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; - const char * mac; - char expected_mac_address[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xee}; - NMIPAddress * ip4_addr; - NMIPAddress * ip6_addr; - const char * file, *expected_id; - gpointer expect_ip6_p; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; + const char * mac; + char expected_mac_address[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xee}; + NMIPAddress *ip4_addr; + NMIPAddress *ip6_addr; + const char * file, *expected_id; + gpointer expect_ip6_p; nmtst_test_data_unpack(test_data, &file, &expected_id, &expect_ip6_p); @@ -873,26 +824,19 @@ test_read_wired_static(gconstpointer test_data) connection = _connection_from_file(file, NULL, TYPE_ETHERNET, &unmanaged); g_assert_cmpstr(unmanaged, ==, NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1492); - /* MAC address */ mac = nm_setting_wired_get_mac_address(s_wired); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, ETH_ALEN)); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -901,24 +845,19 @@ test_read_wired_static(gconstpointer test_data) g_assert(nm_setting_ip_config_has_dns_options(s_ip4)); g_assert_cmpint(nm_setting_ip_config_get_num_dns_options(s_ip4), ==, 0); - /* DNS Addresses */ g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 2); g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "4.2.2.1"); g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 1), ==, "4.2.2.2"); - /* IP addresses */ g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1); ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); g_assert(ip4_addr); g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 24); g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "192.168.1.5"); - /* Gateway */ g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.1"); - /* ===== IPv6 SETTING ===== */ - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); if (GPOINTER_TO_INT(expect_ip6_p)) { g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, @@ -951,19 +890,18 @@ test_read_wired_static(gconstpointer test_data) NM_SETTING_IP6_CONFIG_METHOD_IGNORE); g_assert(!nm_setting_ip_config_has_dns_options(s_ip6)); } - - g_object_unref(connection); } static void test_read_wired_static_no_prefix(gconstpointer user_data) { - guint32 expected_prefix = GPOINTER_TO_UINT(user_data); - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMIPAddress * ip4_addr; - char * file, *expected_id; + guint32 expected_prefix = GPOINTER_TO_UINT(user_data); + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMIPAddress * ip4_addr; + gs_free char * file = NULL; + gs_free char * expected_id = NULL; file = g_strdup_printf(TEST_IFCFG_DIR "/ifcfg-test-wired-static-no-prefix-%u", expected_prefix); expected_id = g_strdup_printf("System test-wired-static-no-prefix-%u", expected_prefix); @@ -972,14 +910,10 @@ test_read_wired_static_no_prefix(gconstpointer user_data) connection = _connection_from_file(file, NULL, TYPE_ETHERNET, NULL); g_test_assert_expected_messages(); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -991,23 +925,19 @@ test_read_wired_static_no_prefix(gconstpointer user_data) ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0); g_assert(ip4_addr); g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, expected_prefix); - - g_free(file); - g_free(expected_id); - g_object_unref(connection); } static void test_read_wired_dhcp(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; - char expected_mac_address[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xee}; - const char * mac; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; + char expected_mac_address[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xee}; + const char *mac; NMTST_EXPECT_NM_WARN("*key IPV6INIT is duplicated and the early occurrence ignored*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-dhcp", @@ -1017,25 +947,18 @@ test_read_wired_dhcp(void) g_test_assert_expected_messages(); g_assert(unmanaged == NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-dhcp"); g_assert_cmpuint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* MAC address */ mac = nm_setting_wired_get_mac_address(s_wired); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, sizeof(expected_mac_address))); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert_cmpstr(nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)), ==, @@ -1048,35 +971,29 @@ test_read_wired_dhcp(void) ==, NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE); - /* ===== IPv6 SETTING ===== */ - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DHCP); g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, "foo.bar"); g_assert_cmpuint(nm_setting_ip_config_get_dhcp_hostname_flags(s_ip6), ==, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS); - - g_object_unref(connection); } static void test_read_wired_dhcp_plus_ip(void) { - NMConnection * connection; - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; - NMIPAddress * ip4_addr; - NMIPAddress * ip6_addr; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + NMIPAddress * ip4_addr; + NMIPAddress * ip6_addr; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-dhcp-plus-ip", NULL, TYPE_ETHERNET, NULL); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_may_fail(s_ip4)); @@ -1100,9 +1017,7 @@ test_read_wired_dhcp_plus_ip(void) g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 16); g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "9.8.7.6"); - /* ===== IPv6 SETTING ===== */ - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); @@ -1127,25 +1042,21 @@ test_read_wired_dhcp_plus_ip(void) g_assert(ip6_addr); g_assert_cmpint(nm_ip_address_get_prefix(ip6_addr), ==, 96); g_assert_cmpstr(nm_ip_address_get_address(ip6_addr), ==, "3001:abba::3234"); - - g_object_unref(connection); } static void test_read_wired_shared_plus_ip(void) { - NMConnection * connection; - NMSettingIPConfig *s_ip4; - NMIPAddress * ip4_addr; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMIPAddress * ip4_addr; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-shared-plus-ip", NULL, TYPE_ETHERNET, NULL); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_SHARED); @@ -1160,19 +1071,16 @@ test_read_wired_shared_plus_ip(void) /* Gateway */ g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "1.1.1.1"); - - g_object_unref(connection); } static void test_read_wired_global_gateway(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMIPAddress * ip4_addr; - char * unmanaged = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMIPAddress * ip4_addr; + char * unmanaged = NULL; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-global-gateway", TEST_IFCFG_DIR "/network-test-wired-global-gateway", @@ -1180,18 +1088,12 @@ test_read_wired_global_gateway(void) &unmanaged); g_assert(unmanaged == NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-global-gateway"); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -1204,19 +1106,16 @@ test_read_wired_global_gateway(void) /* Gateway */ g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.2"); - - g_object_unref(connection); } /* Ignore GATEWAY from /etc/sysconfig/network for automatic connections */ static void test_read_wired_global_gateway_ignore(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - char * unmanaged = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + char * unmanaged = NULL; NMTST_EXPECT_NM_WARN("*ignoring GATEWAY (/etc/sysconfig/network) for * because the connection " "has no static addresses"); @@ -1227,20 +1126,14 @@ test_read_wired_global_gateway_ignore(void) g_test_assert_expected_messages(); g_assert(unmanaged == NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-global-gateway-ignore"); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); /* Addresses */ @@ -1248,25 +1141,21 @@ test_read_wired_global_gateway_ignore(void) /* Gateway */ g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, NULL); - - g_object_unref(connection); } static void test_read_wired_obsolete_gateway_n(void) { - NMConnection * connection; - NMSettingIPConfig *s_ip4; - NMIPAddress * ip4_addr; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMIPAddress * ip4_addr; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-obsolete-gateway-n", NULL, TYPE_ETHERNET, NULL); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -1280,8 +1169,6 @@ test_read_wired_obsolete_gateway_n(void) /* Gateway */ g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "1.1.1.1"); - - g_object_unref(connection); } static void @@ -1294,7 +1181,8 @@ test_user_1(void) connection = nmtst_create_minimal_connection("Test User 1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_user = NM_SETTING_USER(nm_setting_user_new()); + + s_user = _nm_connection_new_setting(connection, NM_TYPE_SETTING_USER); #define _USER_SET_DATA(s_user, key, val) \ G_STMT_START \ @@ -1330,8 +1218,6 @@ test_user_1(void) _USER_SET_DATA_X(s_user, "my.keys.1"); _USER_SET_DATA_X(s_user, "my.other.KEY.42"); - nm_connection_add_setting(connection, NM_SETTING(s_user)); - _writer_new_connec_exp(connection, TEST_SCRATCH_DIR, TEST_IFCFG_DIR "/ifcfg-Test_User_1.cexpected", @@ -1345,42 +1231,35 @@ test_user_1(void) static void test_read_wired_never_default(void) { - NMConnection * connection; - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-never-default", TEST_IFCFG_DIR "/network-test-wired-never-default", TYPE_ETHERNET, NULL); - /* ===== WIRED SETTING ===== */ - g_assert(nm_connection_get_setting_wired(connection)); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_never_default(s_ip4)); g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0); - /* ===== IPv6 SETTING ===== */ - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_never_default(s_ip6)); - - g_object_unref(connection); } static void test_read_wired_defroute_no(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-defroute-no", NULL, @@ -1388,33 +1267,28 @@ test_read_wired_defroute_no(void) &unmanaged); g_assert(unmanaged == NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-defroute-no"); - g_assert(nm_connection_get_setting_wired(connection)); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_never_default(s_ip4)); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_never_default(s_ip6)); - - g_object_unref(connection); } static void test_read_wired_defroute_no_gatewaydev_yes(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-defroute-no-gatewaydev-yes", @@ -1422,58 +1296,45 @@ test_read_wired_defroute_no_gatewaydev_yes(void) TYPE_ETHERNET, &unmanaged); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-defroute-no-gatewaydev-yes"); - g_assert(nm_connection_get_setting_wired(connection)); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_never_default(s_ip4) == FALSE); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); g_assert(nm_setting_ip_config_get_never_default(s_ip6) == FALSE); - - g_object_unref(connection); } static void test_read_wired_static_routes(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMIPRoute * ip4_route; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMIPRoute * ip4_route; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-static-routes", NULL, TYPE_ETHERNET, NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-static-routes"); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== IPv4 SETTING ===== */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - /* Routes */ g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 4); ip4_route = nm_setting_ip_config_get_route(s_ip4, 0); @@ -1524,19 +1385,16 @@ test_read_wired_static_routes(void) g_assert_cmpint(nm_ip_route_get_prefix(ip4_route), ==, 32); nmtst_assert_route_attribute_string(ip4_route, NM_IP_ROUTE_ATTRIBUTE_TYPE, "local"); nmtst_assert_route_attribute_byte(ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 254); - - g_object_unref(connection); } static void test_read_wired_static_routes_legacy(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - char * unmanaged = NULL; - NMIPRoute * ip4_route; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + char * unmanaged = NULL; + NMIPRoute * ip4_route; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-static-routes-legacy", NULL, @@ -1544,28 +1402,18 @@ test_read_wired_static_routes_legacy(void) &unmanaged); g_assert(!unmanaged); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-static-routes-legacy"); - /* ===== WIRED SETTING ===== */ - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - /* Routes */ g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 5); /* Route #1 */ @@ -1612,20 +1460,17 @@ test_read_wired_static_routes_legacy(void) g_assert(ip4_route != NULL); g_assert_cmpstr(nm_ip_route_get_dest(ip4_route), ==, "1.2.3.4"); nmtst_assert_route_attribute_string(ip4_route, NM_IP_ROUTE_ATTRIBUTE_TYPE, "local"); - - g_object_unref(connection); } static void test_read_wired_ipv4_manual(gconstpointer data) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - char * unmanaged = NULL; - NMIPAddress * ip4_addr; - const char * file, *expected_id; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + char * unmanaged = NULL; + NMIPAddress * ip4_addr; + const char * file, *expected_id; nmtst_test_data_unpack(data, &file, &expected_id); @@ -1634,21 +1479,12 @@ test_read_wired_ipv4_manual(gconstpointer data) connection = _connection_from_file(file, NULL, TYPE_ETHERNET, &unmanaged); g_assert(!unmanaged); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - /* ===== WIRED SETTING ===== */ - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - /* ===== IPv4 SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -1674,21 +1510,18 @@ test_read_wired_ipv4_manual(gconstpointer data) g_assert(ip4_addr != NULL); g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, "3.3.3.3"); g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, 8); - - g_object_unref(connection); } static void test_read_wired_ipv6_manual(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; - NMIPAddress * ip6_addr; - NMIPRoute * ip6_route; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; + NMIPAddress * ip6_addr; + NMIPRoute * ip6_route; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-ipv6-manual", NULL, @@ -1696,21 +1529,12 @@ test_read_wired_ipv6_manual(void) &unmanaged); g_assert(!unmanaged); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-ipv6-manual"); - /* ===== WIRED SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); /* DNS Addresses */ g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 2); @@ -1721,10 +1545,7 @@ test_read_wired_ipv6_manual(void) g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip4, 1), ==, "ipsum.org"); g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip4, 2), ==, "dolor.edu"); - /* ===== IPv6 SETTING ===== */ - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL); @@ -1794,22 +1615,19 @@ test_read_wired_ipv6_manual(void) /* DNS domains - none as domains are stuffed to 'ipv4' setting */ g_assert_cmpint(nm_setting_ip_config_get_num_dns_searches(s_ip6), ==, 0); - - g_object_unref(connection); } static void test_read_wired_ipv6_only(gconstpointer test_data) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; - NMIPAddress * ip6_addr; - const char * method; - const char * file, *expected_id; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; + NMIPAddress * ip6_addr; + const char * method; + const char * file, *expected_id; nmtst_test_data_unpack(test_data, &file, &expected_id); @@ -1818,29 +1636,17 @@ test_read_wired_ipv6_only(gconstpointer test_data) connection = _connection_from_file(file, NULL, TYPE_ETHERNET, &unmanaged); g_assert(!unmanaged); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - /* ===== WIRED SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); method = nm_setting_ip_config_get_method(s_ip4); g_assert_cmpstr(method, ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - /* ===== IPv6 SETTING ===== */ - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL); @@ -1863,20 +1669,17 @@ test_read_wired_ipv6_only(gconstpointer test_data) g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, 0), ==, "lorem.com"); g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, 1), ==, "ipsum.org"); g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, 2), ==, "dolor.edu"); - - g_object_unref(connection); } static void test_read_wired_dhcp6_only(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - char * unmanaged = NULL; - const char * method; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; + const char * method; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-dhcp6-only", NULL, @@ -1884,32 +1687,18 @@ test_read_wired_dhcp6_only(void) &unmanaged); g_assert(!unmanaged); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-dhcp6-only"); - /* ===== WIRED SETTING ===== */ - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - /* ===== IPv4 SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); method = nm_setting_ip_config_get_method(s_ip4); g_assert_cmpstr(method, ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - /* ===== IPv6 SETTING ===== */ - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DHCP); - - g_object_unref(connection); } static void @@ -1926,24 +1715,23 @@ test_read_wired_autoip(void) &unmanaged); g_assert(unmanaged == NULL); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL); g_assert(!nm_setting_ip_config_get_may_fail(s_ip4)); g_assert(nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - s_con = nm_connection_get_setting_connection(connection); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, 2600); } static void test_read_onboot_no(void) { - NMConnection * connection; - NMSettingConnection *s_con; - char * unmanaged = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + char * unmanaged = NULL; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-onboot-no", NULL, @@ -1951,39 +1739,32 @@ test_read_onboot_no(void) &unmanaged); g_assert(!unmanaged); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert(!nm_setting_connection_get_autoconnect(s_con)); - - g_object_unref(connection); } static void test_read_noip(void) { - NMConnection * connection; - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-noip", NULL, TYPE_ETHERNET, NULL); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); g_assert(nm_setting_ip_config_get_never_default(s_ip4) == FALSE); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE); g_assert(nm_setting_ip_config_get_never_default(s_ip6) == FALSE); - - g_object_unref(connection); } #define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT TEST_IFCFG_DIR "/test_ca_cert.pem" @@ -1991,16 +1772,15 @@ test_read_noip(void) static void test_read_wired_8021x_peap_mschapv2(void) { - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig *s_ip4; - NMSetting8021x * s_8021x; - NMSetting8021x * tmp_8021x; - char * unmanaged = NULL; - GError * error = NULL; - gboolean success = FALSE; - const char * expected_ca_cert_path; - const char * read_ca_cert_path; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSetting8021x * s_8021x; + gs_unref_object NMSetting8021x *tmp_8021x = NULL; + char * unmanaged = NULL; + GError * error = NULL; + gboolean success = FALSE; + const char * expected_ca_cert_path; + const char * read_ca_cert_path; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-8021x-peap-mschapv2", NULL, @@ -2008,20 +1788,12 @@ test_read_wired_8021x_peap_mschapv2(void) &unmanaged); g_assert(!unmanaged); - /* ===== WIRED SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); g_assert_cmpstr(nm_setting_802_1x_get_eap_method(s_8021x, 0), ==, "peap"); @@ -2049,33 +1821,26 @@ test_read_wired_8021x_peap_mschapv2(void) g_assert(read_ca_cert_path); g_assert_cmpstr(read_ca_cert_path, ==, expected_ca_cert_path); - - g_object_unref(tmp_8021x); - - g_object_unref(connection); } static void test_read_wired_8021x_tls_secret_flags(gconstpointer test_data) { - NMConnection * connection; - NMSettingWired *s_wired; - NMSetting8021x *s_8021x; - char * dirname, *tmp; - const char * ifcfg; - gpointer expected_flags_p; + gs_unref_object NMConnection *connection = NULL; + NMSetting8021x * s_8021x; + gs_free char * dirname = NULL; + gs_free char * tmp1 = NULL; + gs_free char * tmp2 = NULL; + const char * ifcfg; + gpointer expected_flags_p; nmtst_test_data_unpack(test_data, &ifcfg, &expected_flags_p); connection = _connection_from_file(ifcfg, NULL, TYPE_ETHERNET, NULL); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); g_assert_cmpstr(nm_setting_802_1x_get_eap_method(s_8021x, 0), ==, "tls"); g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "David Smith"); @@ -2084,18 +1849,13 @@ test_read_wired_8021x_tls_secret_flags(gconstpointer test_data) GPOINTER_TO_INT(expected_flags_p)); dirname = g_path_get_dirname(ifcfg); - tmp = g_build_path("/", dirname, "test_ca_cert.pem", NULL); - g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, tmp); - g_free(tmp); - tmp = g_build_path("/", dirname, "test1_key_and_cert.pem", NULL); - g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), ==, tmp); - g_assert_cmpstr(nm_setting_802_1x_get_private_key_path(s_8021x), ==, tmp); - g_free(tmp); + tmp1 = g_build_path("/", dirname, "test_ca_cert.pem", NULL); + g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, tmp1); - g_free(dirname); - - g_object_unref(connection); + tmp2 = g_build_path("/", dirname, "test1_key_and_cert.pem", NULL); + g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), ==, tmp2); + g_assert_cmpstr(nm_setting_802_1x_get_private_key_path(s_8021x), ==, tmp2); } static void @@ -2111,9 +1871,7 @@ test_read_write_802_1X_subj_matches(void) TYPE_ETHERNET, NULL); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); g_assert_cmpstr(nm_setting_802_1x_get_eap_method(s_8021x, 0), ==, "peap"); g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "Jara Cimrman"); @@ -2143,8 +1901,7 @@ test_read_write_802_1X_subj_matches(void) nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); /* Check 802.1X stuff of the re-read connection. */ - s_8021x = nm_connection_get_setting_802_1x(reread); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); g_assert_cmpstr(nm_setting_802_1x_get_eap_method(s_8021x, 0), ==, "peap"); g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "Jara Cimrman"); @@ -2168,8 +1925,8 @@ test_read_write_802_1X_subj_matches(void) static void test_read_802_1x_ttls_eapgtc(void) { - NMConnection * connection; - NMSetting8021x *s_8021x; + gs_unref_object NMConnection *connection = NULL; + NMSetting8021x * s_8021x; /* Test that EAP-* inner methods are correctly read into the * NMSetting8021x::autheap property. @@ -2180,9 +1937,7 @@ test_read_802_1x_ttls_eapgtc(void) TYPE_WIRELESS, NULL); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); /* EAP methods */ g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); @@ -2191,8 +1946,6 @@ test_read_802_1x_ttls_eapgtc(void) /* Auth methods */ g_assert_cmpstr(nm_setting_802_1x_get_phase2_auth(s_8021x), ==, NULL); g_assert_cmpstr(nm_setting_802_1x_get_phase2_autheap(s_8021x), ==, "gtc"); - - g_object_unref(connection); } static void @@ -2208,8 +1961,7 @@ test_read_802_1x_tls_p12_no_client_cert(void) TYPE_ETHERNET, NULL); - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_private_key_scheme(s_8021x), ==, @@ -2242,9 +1994,7 @@ test_read_write_802_1x_password_raw(void) TYPE_ETHERNET, NULL); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); bytes = nm_setting_802_1x_get_password_raw(s_8021x); g_assert(bytes); @@ -2269,18 +2019,18 @@ test_read_write_802_1x_password_raw(void) static void test_read_wired_aliases_good(gconstpointer test_data) { - const int N = GPOINTER_TO_INT(test_data); - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - int expected_num_addresses; - const char * expected_address_0[] = {"192.168.1.5", + const int N = GPOINTER_TO_INT(test_data); + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + int expected_num_addresses; + const char * expected_address_0[] = {"192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99", NULL}; - const char * expected_address_3[] = {"192.168.1.5", "192.168.1.6", NULL}; - const char * expected_label_0[] = { + const char * expected_address_3[] = {"192.168.1.5", "192.168.1.6", NULL}; + const char * expected_label_0[] = { NULL, "aliasem0:1", "aliasem0:2", @@ -2305,19 +2055,13 @@ test_read_wired_aliases_good(gconstpointer test_data) connection = _connection_from_file(path, NULL, TYPE_ETHERNET, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); if (N == 0) g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System aliasem0"); else g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System aliasem3"); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -2358,33 +2102,25 @@ test_read_wired_aliases_good(gconstpointer test_data) for (i = 0; i < expected_num_addresses; i++) g_assert(!expected_address[i]); - - g_object_unref(connection); } static void test_read_wired_aliases_bad(const char *base, const char *expected_id) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMIPAddress * ip4_addr; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMIPAddress * ip4_addr; g_assert(expected_id); connection = _connection_from_file(base, NULL, TYPE_ETHERNET, NULL); g_test_assert_expected_messages(); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, expected_id); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -2400,8 +2136,6 @@ test_read_wired_aliases_bad(const char *base, const char *expected_id) /* Gateway */ g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.1.1"); - - g_object_unref(connection); } static void @@ -2421,13 +2155,15 @@ test_read_wired_aliases_bad_2(void) static void test_read_dns_options(void) { - NMConnection * connection; - NMSettingIPConfig *s_ip4, *s_ip6; - char * unmanaged = NULL; - const char * option; - const char * options4[] = {"ndots:3", "single-request-reopen"}; - const char * options6[] = {"inet6"}; - guint32 i, num; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + char * unmanaged = NULL; + const char * option; + const char * options4[] = {"ndots:3", "single-request-reopen"}; + const char * options6[] = {"inet6"}; + guint32 num; + guint32 i; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-dns-options", NULL, @@ -2435,11 +2171,9 @@ test_read_dns_options(void) &unmanaged); g_assert_cmpstr(unmanaged, ==, NULL); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); num = nm_setting_ip_config_get_num_dns_options(s_ip4); g_assert_cmpint(num, ==, G_N_ELEMENTS(options4)); @@ -2456,8 +2190,6 @@ test_read_dns_options(void) option = nm_setting_ip_config_get_dns_option(s_ip6, i); g_assert_cmpstr(options6[i], ==, option); } - - g_object_unref(connection); } static void @@ -2477,8 +2209,7 @@ test_clear_master(void) &unmanaged); g_assert_cmpstr(unmanaged, ==, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "br0"); g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, "bridge"); @@ -2534,10 +2265,7 @@ test_write_dns_options(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test DNS options", @@ -2549,16 +2277,10 @@ test_write_dns_options(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NM_SETTING_WIRED_MTU, mtu, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -2576,10 +2298,7 @@ test_write_dns_options(void) nm_setting_ip_config_add_dns_option(s_ip4, "debug"); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_MANUAL, @@ -2608,23 +2327,20 @@ test_write_dns_options(void) static void test_read_wifi_open(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4, *s_ip6; - GBytes * ssid; - const char * mac; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + GBytes * ssid; + const char * mac; char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; const char *expected_ssid = "blahblah"; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-open", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-open)"); /* UUID can't be tested if the ifcfg does not contain the UUID key, because @@ -2636,109 +2352,83 @@ test_read_wifi_open(void) g_assert(nm_setting_connection_get_autoconnect(s_con)); g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), ==, -1); - /* ===== WIRELESS SETTING ===== */ + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* MAC address */ - mac = nm_setting_wireless_get_mac_address(s_wireless); + mac = nm_setting_wireless_get_mac_address(s_wifi); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, sizeof(expected_mac_address))); - g_assert_cmpint(nm_setting_wireless_get_mtu(s_wireless), ==, 0); + g_assert_cmpint(nm_setting_wireless_get_mtu(s_wifi), ==, 0); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - g_assert(!nm_setting_wireless_get_bssid(s_wireless)); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "infrastructure"); - g_assert_cmpint(nm_setting_wireless_get_channel(s_wireless), ==, 1); - - /* ===== Wi-Fi SECURITY SETTING ===== */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec == NULL); + g_assert(!nm_setting_wireless_get_bssid(s_wifi)); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "infrastructure"); + g_assert_cmpint(nm_setting_wireless_get_channel(s_wifi), ==, 1); - /* ===== IPv4 SETTING ===== */ + nmtst_connection_assert_no_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpint(nm_setting_ip_config_get_route_metric(s_ip4), ==, 104); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpint(nm_setting_ip_config_get_route_metric(s_ip6), ==, 106); - - g_object_unref(connection); } static void test_read_wifi_open_auto(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWireless * s_wireless; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-open-auto", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-open-auto)"); - /* ===== WIRELESS SETTING ===== */ - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "infrastructure"); - - g_object_unref(connection); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "infrastructure"); } static void test_read_wifi_open_ssid_hex(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWireless * s_wireless; - GBytes * ssid; - const char * expected_ssid = "blahblah"; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + GBytes * ssid; + const char * expected_ssid = "blahblah"; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-open-ssid-hex", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-open-ssid-hex)"); - /* ===== WIRELESS SETTING ===== */ + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - - g_object_unref(connection); } static void @@ -2746,7 +2436,7 @@ test_read_wifi_open_ssid_hex_bad(void) { gs_unref_object NMConnection *connection = NULL; NMSettingConnection * s_con; - NMSettingWireless * s_wireless; + NMSettingWireless * s_wifi; GBytes * ssid; const char * expected_ssid = "0x626cxx"; @@ -2755,16 +2445,14 @@ test_read_wifi_open_ssid_hex_bad(void) TYPE_WIRELESS, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System 0x626cxx (test-wifi-open-ssid-bad-hex)"); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), @@ -2781,50 +2469,42 @@ test_read_wifi_open_ssid_bad(gconstpointer data) static void test_read_wifi_open_ssid_quoted(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWireless * s_wireless; - GBytes * ssid; - const char * expected_ssid = "foo\"bar\\"; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + GBytes * ssid; + const char * expected_ssid = "foo\"bar\\"; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-open-ssid-quoted", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System foo\"bar\\ (test-wifi-open-ssid-quoted)"); - /* ===== WIRELESS SETTING ===== */ + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - - g_object_unref(connection); } static void test_read_wifi_wep(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4; - GBytes * ssid; - const char * mac; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingWirelessSecurity * s_wsec; + NMSettingIPConfig * s_ip4; + GBytes * ssid; + const char * mac; char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; const char * expected_ssid = "blahblah"; NMWepKeyType key_type; @@ -2832,10 +2512,7 @@ test_read_wifi_wep(void) connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-wep)"); /* UUID can't be tested if the ifcfg does not contain the UUID key, because @@ -2846,34 +2523,27 @@ test_read_wifi_wep(void) g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - /* MAC address */ - mac = nm_setting_wireless_get_mac_address(s_wireless); + mac = nm_setting_wireless_get_mac_address(s_wifi); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, sizeof(expected_mac_address))); /* MTU */ - g_assert_cmpint(nm_setting_wireless_get_mtu(s_wireless), ==, 0); + g_assert_cmpint(nm_setting_wireless_get_mtu(s_wifi), ==, 0); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - g_assert(!nm_setting_wireless_get_bssid(s_wireless)); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "infrastructure"); - g_assert_cmpint(nm_setting_wireless_get_channel(s_wireless), ==, 1); - - /* ===== WIRELESS SECURITY SETTING ===== */ + g_assert(!nm_setting_wireless_get_bssid(s_wifi)); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "infrastructure"); + g_assert_cmpint(nm_setting_wireless_get_channel(s_wifi), ==, 1); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "none"); g_assert_cmpstr(nm_setting_wireless_security_get_auth_alg(s_wsec), ==, "shared"); g_assert_cmpint(nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec), ==, 0); @@ -2888,35 +2558,27 @@ test_read_wifi_wep(void) g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 2)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 3)); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - g_object_unref(connection); } static void test_read_wifi_wep_adhoc(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4; - GBytes * ssid; - const char * expected_ssid = "blahblah"; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingWirelessSecurity * s_wsec; + NMSettingIPConfig * s_ip4; + GBytes * ssid; + const char * expected_ssid = "blahblah"; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-adhoc", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-wep-adhoc)"); @@ -2928,26 +2590,20 @@ test_read_wifi_wep_adhoc(void) g_assert(!nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRELESS SETTING ===== */ + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - g_assert(!nm_setting_wireless_get_bssid(s_wireless)); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "adhoc"); - g_assert_cmpint(nm_setting_wireless_get_channel(s_wireless), ==, 11); - - /* ===== WIRELESS SECURITY SETTING ===== */ + g_assert(!nm_setting_wireless_get_bssid(s_wifi)); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "adhoc"); + g_assert_cmpint(nm_setting_wireless_get_channel(s_wifi), ==, 11); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "none"); g_assert(!nm_setting_wireless_security_get_auth_alg(s_wsec)); g_assert_cmpint(nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec), ==, 0); @@ -2959,10 +2615,7 @@ test_read_wifi_wep_adhoc(void) g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 2)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 3)); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); /* Ignore auto DNS */ @@ -2972,37 +2625,24 @@ test_read_wifi_wep_adhoc(void) g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 2); g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "4.2.2.1"); g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 1), ==, "4.2.2.2"); - - g_object_unref(connection); } static void test_read_wifi_wep_passphrase(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-passphrase", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); - /* ===== WIRELESS SECURITY SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "none"); g_assert_cmpint(nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec), ==, 0); g_assert_cmpint(nm_setting_wireless_security_get_wep_key_type(s_wsec), @@ -3012,38 +2652,25 @@ test_read_wifi_wep_passphrase(void) g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 1)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 2)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 3)); - - g_object_unref(connection); } static void test_read_wifi_wep_40_ascii(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMWepKeyType key_type; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; + NMWepKeyType key_type; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-40-ascii", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); - - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); - /* ===== WIRELESS SECURITY SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "none"); g_assert_cmpint(nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec), ==, 0); @@ -3054,38 +2681,25 @@ test_read_wifi_wep_40_ascii(void) g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 1)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 2)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 3)); - - g_object_unref(connection); } static void test_read_wifi_wep_104_ascii(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMWepKeyType key_type; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; + NMWepKeyType key_type; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-104-ascii", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); - /* ===== WIRELESS SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== WIRELESS SECURITY SETTING ===== */ - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "none"); g_assert_cmpint(nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec), ==, 0); @@ -3096,64 +2710,45 @@ test_read_wifi_wep_104_ascii(void) g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 1)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 2)); g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 3)); - - g_object_unref(connection); } static void test_read_wifi_leap(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWirelessSecurity * s_wsec; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-leap", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-leap)"); - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== WIRELESS SECURITY SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "ieee8021x"); g_assert_cmpstr(nm_setting_wireless_security_get_auth_alg(s_wsec), ==, "leap"); g_assert_cmpstr(nm_setting_wireless_security_get_leap_username(s_wsec), ==, "Bill Smith"); g_assert_cmpstr(nm_setting_wireless_security_get_leap_password(s_wsec), ==, "foobarblah"); - - g_object_unref(connection); } static void test_read_wifi_leap_secret_flags(gconstpointer test_data) { - NMConnection * connection; - NMSettingWireless * s_wifi; - NMSettingWirelessSecurity *s_wsec; - const char * file; - gpointer expected_flags_p; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; + const char * file; + gpointer expected_flags_p; nmtst_test_data_unpack(test_data, &file, &expected_flags_p); connection = _connection_from_file(file, NULL, TYPE_WIRELESS, NULL); - /* ===== WIRELESS SETTING ===== */ - s_wifi = nm_connection_get_setting_wireless(connection); - g_assert(s_wifi); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - /* ===== WIRELESS SECURITY SETTING ===== */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert(g_strcmp0(nm_setting_wireless_security_get_key_mgmt(s_wsec), "ieee8021x") == 0); g_assert(g_strcmp0(nm_setting_wireless_security_get_auth_alg(s_wsec), "leap") == 0); @@ -3162,8 +2757,6 @@ test_read_wifi_leap_secret_flags(gconstpointer test_data) g_assert(nm_setting_wireless_security_get_leap_password_flags(s_wsec) == GPOINTER_TO_INT(expected_flags_p)); g_assert(nm_setting_wireless_security_get_leap_password(s_wsec) == NULL); - - g_object_unref(connection); } static void @@ -3179,13 +2772,13 @@ test_ifcfg_no_trailing_newline(void) static void test_read_wifi_wpa_psk(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4; - GBytes * ssid; - const char * mac; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingWirelessSecurity * s_wsec; + NMSettingIPConfig * s_ip4; + GBytes * ssid; + const char * mac; char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; const char *expected_ssid = "blahblah"; guint32 n, i; @@ -3201,10 +2794,7 @@ test_read_wifi_wpa_psk(void) connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-psk", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-wpa-psk)"); /* UUID can't be tested if the ifcfg does not contain the UUID key, because @@ -3215,32 +2805,26 @@ test_read_wifi_wpa_psk(void) g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - mac = nm_setting_wireless_get_mac_address(s_wireless); + mac = nm_setting_wireless_get_mac_address(s_wifi); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, sizeof(expected_mac_address))); - g_assert_cmpint(nm_setting_wireless_get_mtu(s_wireless), ==, 0); + g_assert_cmpint(nm_setting_wireless_get_mtu(s_wifi), ==, 0); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - g_assert(!nm_setting_wireless_get_bssid(s_wireless)); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "infrastructure"); - g_assert_cmpint(nm_setting_wireless_get_channel(s_wireless), ==, 1); + g_assert(!nm_setting_wireless_get_bssid(s_wifi)); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "infrastructure"); + g_assert_cmpint(nm_setting_wireless_get_channel(s_wifi), ==, 1); - /* ===== WIRELESS SECURITY SETTING ===== */ - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "wpa-psk"); g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, @@ -3295,13 +2879,8 @@ test_read_wifi_wpa_psk(void) g_assert(found_proto_wpa); g_assert(found_proto_rsn); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - g_object_unref(connection); } static void @@ -3309,7 +2888,7 @@ test_read_wifi_sae(void) { gs_unref_object NMConnection *connection = NULL; NMSettingConnection * s_con; - NMSettingWireless * s_wireless; + NMSettingWireless * s_wifi; NMSettingWirelessSecurity * s_wsec; GBytes * ssid; const char * expected_ssid = "blahblah"; @@ -3317,30 +2896,27 @@ test_read_wifi_sae(void) connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-sae", NULL, TYPE_WIRELESS, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-sae)"); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - g_assert_cmpint(nm_setting_wireless_get_mtu(s_wireless), ==, 0); + g_assert_cmpint(nm_setting_wireless_get_mtu(s_wifi), ==, 0); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - g_assert(!nm_setting_wireless_get_bssid(s_wireless)); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "infrastructure"); + g_assert(!nm_setting_wireless_get_bssid(s_wifi)); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "infrastructure"); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "sae"); g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, "The king is dead."); g_assert(!nm_setting_wireless_security_get_auth_alg(s_wsec)); @@ -3351,7 +2927,7 @@ test_read_wifi_owe(void) { gs_unref_object NMConnection *connection = NULL; NMSettingConnection * s_con; - NMSettingWireless * s_wireless; + NMSettingWireless * s_wifi; NMSettingWirelessSecurity * s_wsec; GBytes * ssid; const char * expected_ssid = "blahblah_owe"; @@ -3359,30 +2935,27 @@ test_read_wifi_owe(void) connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-owe", NULL, TYPE_WIRELESS, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah_owe (test-wifi-owe)"); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - g_assert_cmpint(nm_setting_wireless_get_mtu(s_wireless), ==, 0); + g_assert_cmpint(nm_setting_wireless_get_mtu(s_wifi), ==, 0); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); g_assert_cmpmem(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid), expected_ssid, strlen(expected_ssid)); - g_assert(!nm_setting_wireless_get_bssid(s_wireless)); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "infrastructure"); + g_assert(!nm_setting_wireless_get_bssid(s_wifi)); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "infrastructure"); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "owe"); g_assert(!nm_setting_wireless_security_get_psk(s_wsec)); g_assert(!nm_setting_wireless_security_get_auth_alg(s_wsec)); @@ -3391,71 +2964,47 @@ test_read_wifi_owe(void) static void test_read_wifi_wpa_psk_2(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWirelessSecurity * s_wsec; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-psk-2", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System ipsum (test-wifi-wpa-psk-2)"); - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - /* ===== WIRELESS SECURITY SETTING ===== */ - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, "They're really saying I love you. >>`<< '"); - - g_object_unref(connection); } static void test_read_wifi_wpa_psk_unquoted(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWirelessSecurity * s_wsec; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-psk-unquoted", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-wpa-psk-unquoted)"); - /* ===== WIRELESS SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== WIRELESS SECURITY SETTING ===== */ - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, "54336845e2f3f321c4c7"); - - g_object_unref(connection); } static void @@ -3472,36 +3021,27 @@ test_read_wifi_wpa_psk_unquoted2(void) static void test_read_wifi_wpa_psk_adhoc(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingWirelessSecurity * s_wsec; + NMSettingIPConfig * s_ip4; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-psk-adhoc", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-wpa-psk-adhoc)"); - /* ===== WIRELESS SETTING ===== */ + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, "adhoc"); - g_assert_cmpstr(nm_setting_wireless_get_mode(s_wireless), ==, "adhoc"); - - /* ===== WIRELESS SECURITY SETTING ===== */ - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "wpa-psk"); g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, @@ -3516,64 +3056,45 @@ test_read_wifi_wpa_psk_adhoc(void) g_assert_cmpint(nm_setting_wireless_security_get_num_protos(s_wsec), ==, 1); g_assert_cmpstr(nm_setting_wireless_security_get_proto(s_wsec, 0), ==, "rsn"); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - g_object_unref(connection); } static void test_read_wifi_wpa_psk_hex(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4; - GBytes * ssid; - const char * expected_ssid = "blahblah"; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; + NMSettingWirelessSecurity * s_wsec; + NMSettingIPConfig * s_ip4; + GBytes * ssid; + const char * expected_ssid = "blahblah"; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-psk-hex", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System blahblah (test-wifi-wpa-psk-hex)"); - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - ssid = nm_setting_wireless_get_ssid(s_wireless); + ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); - g_assert(nm_utils_gbytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); + g_assert(nm_g_bytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); - /* ===== WIRELESS SECURITY SETTING ===== */ - - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "wpa-psk"); g_assert_cmpstr(nm_setting_wireless_security_get_psk(s_wsec), ==, "1da190379817bc360dda52e85c388c439a21ea5c7bf819c64e9da051807deae6"); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - - g_object_unref(connection); } #define TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT TEST_IFCFG_DIR "/test_ca_cert.pem" @@ -3583,12 +3104,11 @@ test_read_wifi_wpa_psk_hex(void) static void test_read_wifi_wpa_eap_tls(void) { - NMConnection * connection; - NMSettingWireless *s_wireless; - NMSettingIPConfig *s_ip4; - NMSetting8021x * s_8021x; - char * unmanaged = NULL; - const char * expected_privkey_password = "test1"; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSetting8021x * s_8021x; + char * unmanaged = NULL; + const char * expected_privkey_password = "test1"; NMTST_EXPECT_NM_WARN("*key ONBOOT is duplicated and the early occurrence ignored*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-eap-tls", @@ -3598,20 +3118,12 @@ test_read_wifi_wpa_eap_tls(void) g_test_assert_expected_messages(); g_assert(!unmanaged); - /* ===== WIRELESS SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); g_assert_cmpstr(nm_setting_802_1x_get_eap_method(s_8021x, 0), ==, "tls"); g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "Bill Smith"); @@ -3638,8 +3150,6 @@ test_read_wifi_wpa_eap_tls(void) TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, expected_privkey_password, NM_SETTING_802_1X_PRIVATE_KEY); - - g_object_unref(connection); } /* Also use TLS defines from the previous test */ @@ -3647,12 +3157,11 @@ test_read_wifi_wpa_eap_tls(void) static void test_read_wifi_wpa_eap_ttls_tls(void) { - NMConnection * connection; - NMSettingWireless *s_wireless; - NMSettingIPConfig *s_ip4; - NMSetting8021x * s_8021x; - char * unmanaged = NULL; - const char * expected_privkey_password = "test1"; + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSetting8021x * s_8021x; + char * unmanaged = NULL; + const char * expected_privkey_password = "test1"; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-eap-ttls-tls", NULL, @@ -3660,20 +3169,12 @@ test_read_wifi_wpa_eap_ttls_tls(void) &unmanaged); g_assert(!unmanaged); - /* ===== WIRELESS SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); g_assert_cmpstr(nm_setting_802_1x_get_eap_method(s_8021x, 0), ==, "ttls"); g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "Chuck Shumer"); @@ -3709,59 +3210,40 @@ test_read_wifi_wpa_eap_ttls_tls(void) TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, expected_privkey_password, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - - g_object_unref(connection); } static void test_read_wifi_wpa_eap_suite_b_192_tls(void) { - NMConnection * connection; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wireless_sec; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-eap-suite-b-192-tls", NULL, TYPE_WIRELESS, NULL); - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== WIRELESS SECURITY SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless_sec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wireless_sec); - g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wireless_sec), - ==, - "wpa-eap-suite-b-192"); - - g_object_unref(connection); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); + g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "wpa-eap-suite-b-192"); } static void test_read_wifi_dynamic_wep_leap(void) { - NMConnection * connection; - NMSettingWireless * s_wifi; - NMSettingWirelessSecurity *s_wsec; - NMSetting8021x * s_8021x; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; + NMSetting8021x * s_8021x; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-dynamic-wep-leap", NULL, TYPE_WIRELESS, NULL); - /* ===== WIRELESS SETTING ===== */ - - s_wifi = nm_connection_get_setting_wireless(connection); - g_assert(s_wifi); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - /* ===== Wi-Fi SECURITY SETTING ===== */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); /* Key management */ g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "ieee8021x"); @@ -3775,9 +3257,7 @@ test_read_wifi_dynamic_wep_leap(void) g_assert_cmpstr(nm_setting_wireless_security_get_leap_username(s_wsec), ==, NULL); g_assert_cmpstr(nm_setting_wireless_security_get_leap_password(s_wsec), ==, NULL); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); /* EAP method should be "leap" */ g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); @@ -3786,19 +3266,16 @@ test_read_wifi_dynamic_wep_leap(void) /* username & password */ g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "bill smith"); g_assert_cmpstr(nm_setting_802_1x_get_password(s_8021x), ==, "foobar baz"); - - g_object_unref(connection); } static void test_read_wifi_wep_eap_ttls_chap(void) { - NMConnection * connection; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMSettingIPConfig * s_ip4; - NMSetting8021x * s_8021x; - char * unmanaged = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; + NMSettingIPConfig * s_ip4; + NMSetting8021x * s_8021x; + char * unmanaged = NULL; NMTST_EXPECT_NM_WARN("*key ONBOOT is duplicated and the early occurrence ignored*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-eap-ttls-chap", @@ -3808,25 +3285,15 @@ test_read_wifi_wep_eap_ttls_chap(void) g_test_assert_expected_messages(); g_assert(!unmanaged); - /* ===== WIRELESS SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - /* ===== 802.1x SETTING ===== */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "ieee8021x"); - /* ===== 802.1x SETTING ===== */ - s_8021x = nm_connection_get_setting_802_1x(connection); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); /* EAP methods */ g_assert_cmpint(nm_setting_802_1x_get_num_eap_methods(s_8021x), ==, 1); @@ -3841,38 +3308,32 @@ test_read_wifi_wep_eap_ttls_chap(void) g_assert_cmpstr(nm_setting_802_1x_get_phase2_auth(s_8021x), ==, "chap"); g_assert_cmpstr(nm_setting_802_1x_get_identity(s_8021x), ==, "David Smith"); g_assert_cmpstr(nm_setting_802_1x_get_password(s_8021x), ==, "foobar baz"); - - g_object_unref(connection); } static void test_read_wired_wake_on_lan(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-wake-on-lan", NULL, TYPE_WIRELESS, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRED_SETTING_NAME); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert_cmpint(nm_setting_wired_get_wake_on_lan(s_wired), ==, NM_SETTING_WIRED_WAKE_ON_LAN_ARP | NM_SETTING_WIRED_WAKE_ON_LAN_PHY | NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC); g_assert_cmpstr(nm_setting_wired_get_wake_on_lan_password(s_wired), ==, "00:11:22:33:44:55"); - - g_object_unref(connection); } static void @@ -3887,14 +3348,12 @@ test_read_wired_auto_negotiate_off(void) TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRED_SETTING_NAME); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 100); @@ -3913,14 +3372,12 @@ test_read_wired_auto_negotiate_on(void) TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRED_SETTING_NAME); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 0); @@ -3939,14 +3396,12 @@ test_read_wired_unknown_ethtool_opt(void) TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRED_SETTING_NAME); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); g_assert(!nm_setting_wired_get_speed(s_wired)); @@ -3980,8 +3435,8 @@ test_roundtrip_ethtool(void) NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_ethtool = nm_setting_ethtool_new(); - nm_connection_add_setting(connection, s_ethtool); + + 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-2.cexpected", @@ -3992,7 +3447,7 @@ test_roundtrip_ethtool(void) NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_wired = nm_connection_get_setting(connection, NM_TYPE_SETTING_WIRED); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); _writer_new_connec_exp(connection, TEST_SCRATCH_DIR, @@ -4004,8 +3459,8 @@ test_roundtrip_ethtool(void) NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_ethtool = nm_setting_ethtool_new(); - nm_connection_add_setting(connection, s_ethtool); + + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); nm_setting_option_set_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX, TRUE); _writer_new_connec_exp(connection, TEST_SCRATCH_DIR, @@ -4017,10 +3472,10 @@ test_roundtrip_ethtool(void) NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_wired = nm_connection_get_setting(connection, NM_TYPE_SETTING_WIRED); + 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_setting_ethtool_new(); - nm_connection_add_setting(connection, s_ethtool); + + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); nm_setting_option_set_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX, TRUE); _writer_new_connec_exp(connection, TEST_SCRATCH_DIR, @@ -4032,24 +3487,20 @@ test_roundtrip_ethtool(void) static void test_read_wifi_hidden(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWireless * s_wifi; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-hidden", NULL, TYPE_WIRELESS, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRELESS_SETTING_NAME); - s_wifi = nm_connection_get_setting_wireless(connection); - g_assert(s_wifi); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); g_assert(nm_setting_wireless_get_hidden(s_wifi) == TRUE); - - g_object_unref(connection); } static void @@ -4061,15 +3512,12 @@ test_write_wifi_hidden(void) NMSettingConnection * s_con; NMSettingWireless * s_wifi; shvarFile * f; - GBytes * ssid; - const unsigned char ssid_data[] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44}; + gs_unref_bytes GBytes *ssid = + nmtst_gbytes_from_arr(0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wi-Fi Hidden", @@ -4079,16 +3527,9 @@ test_write_wifi_hidden(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); - g_bytes_unref(ssid); - nmtst_assert_connection_verifies(connection); _writer_new_connec_exp(connection, @@ -4121,8 +3562,7 @@ test_read_wifi_mac_random(gconstpointer user_data) path = g_strdup_printf(TEST_IFCFG_DIR "/ifcfg-test-wifi-mac-random-%s", name); connection = _connection_from_file(path, NULL, TYPE_WIRELESS, NULL); - s_wifi = nm_connection_get_setting_wireless(connection); - g_assert(s_wifi); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); g_assert_cmpint(nm_setting_wireless_get_mac_address_randomization(s_wifi), ==, value); } @@ -4134,10 +3574,10 @@ test_write_wifi_mac_random(gconstpointer user_data) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingWireless * s_wifi; - char * val; + gs_free char * val = NULL; shvarFile * f; - GBytes * ssid; - const unsigned char ssid_data[] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44}; + gs_unref_bytes GBytes *ssid = + nmtst_gbytes_from_arr(0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44); const char * name, *write_expected; gpointer value_p; NMSettingMacRandomization value; @@ -4150,9 +3590,7 @@ test_write_wifi_mac_random(gconstpointer user_data) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); val = g_strdup_printf("Test Write Wi-Fi MAC %s", name); g_object_set(s_con, @@ -4163,13 +3601,8 @@ test_write_wifi_mac_random(gconstpointer user_data) NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); - g_free(val); - - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -4178,7 +3611,6 @@ test_write_wifi_mac_random(gconstpointer user_data) NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, value, NULL); - g_bytes_unref(ssid); nmtst_assert_connection_verifies(connection); @@ -4205,16 +3637,12 @@ test_write_wired_wake_on_lan(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingWired * s_wired; - NMSettingWiredWakeOnLan wol; - char * val; + gs_free char * val = NULL; shvarFile * f; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired Wake-on-LAN", @@ -4224,16 +3652,12 @@ test_write_wired_wake_on_lan(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - wol = NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST | NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST - | NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_WAKE_ON_LAN, - wol, + (guint) (NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST + | NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST + | NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC), NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, "00:00:00:11:22:33", NULL); @@ -4250,7 +3674,6 @@ test_write_wired_wake_on_lan(void) g_assert(val); g_assert(strstr(val, "wol")); g_assert(strstr(val, "sopass 00:00:00:11:22:33")); - g_free(val); svCloseFile(f); reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); @@ -4265,14 +3688,14 @@ test_write_wired_auto_negotiate_off(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingWired * s_wired; - char * val; + gs_free char * val = NULL; shvarFile * f; connection = nmtst_create_minimal_connection("Test Write Wired Auto-Negotiate", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_wired = nm_connection_get_setting_wired(connection); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, FALSE, @@ -4293,7 +3716,6 @@ test_write_wired_auto_negotiate_off(void) g_assert(strstr(val, "autoneg off")); g_assert(strstr(val, "speed 10")); g_assert(strstr(val, "duplex half")); - g_free(val); svCloseFile(f); reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); @@ -4309,20 +3731,19 @@ test_write_wired_auto_negotiate_on(void) gs_unref_object NMConnection *reread = NULL; NMSettingWired * s_wired; NMSettingEthtool * s_ethtool; - char * val; + gs_free char * val = NULL; shvarFile * f; connection = nmtst_create_minimal_connection("Test Write Wired Auto-Negotiate", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); - s_wired = nm_connection_get_setting_wired(connection); + 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_SETTING_ETHTOOL(nm_setting_ethtool_new()); + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); nm_setting_ethtool_set_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TX, NM_TERNARY_TRUE); nm_setting_ethtool_set_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN, NM_TERNARY_FALSE); - nm_connection_add_setting(connection, NM_SETTING(s_ethtool)); _writer_new_connec_exp(connection, TEST_SCRATCH_DIR, @@ -4335,7 +3756,6 @@ test_write_wired_auto_negotiate_on(void) g_assert(strstr(val, "autoneg on")); g_assert(!strstr(val, "speed")); g_assert(!strstr(val, "duplex")); - g_free(val); svCloseFile(f); reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); @@ -4344,8 +3764,7 @@ test_write_wired_auto_negotiate_on(void) nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); - s_ethtool = NM_SETTING_ETHTOOL(nm_connection_get_setting(reread, NM_TYPE_SETTING_ETHTOOL)); - g_assert(s_ethtool); + s_ethtool = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_ETHTOOL); g_assert_cmpint(nm_setting_ethtool_get_feature(s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TX), ==, NM_TERNARY_TRUE); @@ -4360,24 +3779,20 @@ test_write_wired_auto_negotiate_on(void) static void test_read_wifi_band_a(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWireless * s_wifi; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWireless * s_wifi; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-band-a", NULL, TYPE_WIRELESS, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRELESS_SETTING_NAME); - s_wifi = nm_connection_get_setting_wireless(connection); - g_assert(s_wifi); + s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); g_assert_cmpstr(nm_setting_wireless_get_band(s_wifi), ==, "a"); - - g_object_unref(connection); } static void @@ -4389,15 +3804,12 @@ test_write_wifi_band_a(void) NMSettingConnection * s_con; NMSettingWireless * s_wifi; shvarFile * f; - GBytes * ssid; - const unsigned char ssid_data[] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44}; + gs_unref_bytes GBytes *ssid = + nmtst_gbytes_from_arr(0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wi-Fi Band A", @@ -4407,12 +3819,7 @@ test_write_wifi_band_a(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -4422,8 +3829,6 @@ test_write_wifi_band_a(void) "a", NULL); - g_bytes_unref(ssid); - nmtst_assert_connection_verifies(connection); _writer_new_connec_exp(connection, @@ -4448,14 +3853,11 @@ test_write_wifi_ap_mode(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingWireless * s_wifi; - gs_unref_bytes GBytes *ssid = NULL; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("MySSID"); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wi-Fi AP Mode", @@ -4465,12 +3867,7 @@ test_write_wifi_ap_mode(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new("MySSID", NM_STRLEN("MySSID")); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -4523,12 +3920,12 @@ test_read_wifi_band_bg_channel_mismatch(void) static void test_read_wired_qeth_static(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - char * unmanaged = NULL; - const char *const * subchannels; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + char * unmanaged = NULL; + const char *const * subchannels; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-qeth-static", NULL, @@ -4536,16 +3933,10 @@ test_read_wired_qeth_static(void) &unmanaged); g_assert(!unmanaged); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-qeth-static"); - /* ===== WIRED SETTING ===== */ - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert(!nm_setting_wired_get_mac_address(s_wired)); @@ -4563,25 +3954,20 @@ test_read_wired_qeth_static(void) g_assert_cmpstr(nm_setting_wired_get_s390_option_by_key(s_wired, "portno"), ==, "0"); g_assert_cmpstr(nm_setting_wired_get_s390_option_by_key(s_wired, "layer2"), ==, "1"); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); - - g_object_unref(connection); } static void test_read_wired_ctc_static(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - char * unmanaged = NULL; - const char *const * subchannels; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + char * unmanaged = NULL; + const char *const * subchannels; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wired-ctc-static", NULL, @@ -4589,14 +3975,10 @@ test_read_wired_ctc_static(void) &unmanaged); g_assert(unmanaged == NULL); - /* ===== CONNECTION SETTING ===== */ - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con != NULL); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System test-wired-ctc-static"); - /* ===== WIRED SETTING ===== */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired != NULL); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); g_assert(nm_setting_wired_get_mac_address(s_wired) == NULL); @@ -4610,28 +3992,22 @@ test_read_wired_ctc_static(void) g_assert_cmpstr(nm_setting_wired_get_s390_nettype(s_wired), ==, "ctc"); g_assert_cmpstr(nm_setting_wired_get_s390_option_by_key(s_wired, "ctcprot"), ==, "0"); - - g_object_unref(connection); } static void test_read_wifi_wep_no_keys(void) { - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wsec; - NMWepKeyType key_type; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWirelessSecurity * s_wsec; + NMWepKeyType key_type; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-no-keys", NULL, TYPE_WIRELESS, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "System foobar (test-wifi-wep-no-keys)"); @@ -4641,15 +4017,9 @@ test_read_wifi_wep_no_keys(void) * depending on where the tests are run. */ - /* ===== WIRELESS SETTING ===== */ - - s_wireless = nm_connection_get_setting_wireless(connection); - g_assert(s_wireless); - - /* ===== WIRELESS SECURITY SETTING ===== */ + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); /* Key management */ g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wsec), ==, "none"); @@ -4663,26 +4033,21 @@ test_read_wifi_wep_no_keys(void) /* WEP key index 0; we don't expect it to be filled */ g_assert(!nm_setting_wireless_security_get_wep_key(s_wsec, 0)); - - g_object_unref(connection); } static void test_read_permissions(void) { - NMConnection * connection; - NMSettingConnection *s_con; - gboolean success; - guint32 num; - const char * tmp; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + gboolean success; + guint32 num; + const char * tmp; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-permissions", NULL, TYPE_ETHERNET, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); num = nm_setting_connection_get_num_permissions(s_con); g_assert_cmpint(num, ==, 3); @@ -4702,18 +4067,15 @@ test_read_permissions(void) success = nm_setting_connection_get_permission(s_con, 2, NULL, &tmp, NULL); g_assert(success); g_assert_cmpstr(tmp, ==, "johnny5"); - - g_object_unref(connection); } static void test_read_wifi_wep_agent_keys(void) { - NMConnection * connection; - NMSettingWireless * s_wifi; - NMSettingWirelessSecurity *s_wsec; - NMWepKeyType key_type; - NMSettingSecretFlags flags; + gs_unref_object NMConnection *connection = NULL; + NMSettingWirelessSecurity * s_wsec; + NMWepKeyType key_type; + NMSettingSecretFlags flags; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wep-agent-keys", NULL, @@ -4724,13 +4086,9 @@ test_read_wifi_wep_agent_keys(void) * we don't have any WEP keys because they are agent owned. */ - /* ===== WIRELESS SETTING ===== */ - s_wifi = nm_connection_get_setting_wireless(connection); - g_assert(s_wifi); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS); - /* ===== WIRELESS SECURITY SETTING ===== */ - s_wsec = nm_connection_get_setting_wireless_security(connection); - g_assert(s_wsec); + s_wsec = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_assert(strcmp(nm_setting_wireless_security_get_key_mgmt(s_wsec), "none") == 0); g_assert(nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec) == 0); @@ -4743,8 +4101,6 @@ test_read_wifi_wep_agent_keys(void) flags = nm_setting_wireless_security_get_wep_key_flags(s_wsec); g_assert(flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED); - - g_object_unref(connection); } static void @@ -4765,10 +4121,7 @@ test_write_wired_static(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired Static", @@ -4782,10 +4135,7 @@ test_write_wired_static(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", @@ -4793,10 +4143,7 @@ test_write_wired_static(void) (guint32) 1492, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -4824,10 +4171,7 @@ test_write_wired_static(void) nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com"); nm_setting_ip_config_add_dns_search(s_ip4, "lab.foobar.com"); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_MANUAL, @@ -4891,13 +4235,13 @@ test_write_wired_static(void) reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); - reread_s_ip4 = nm_connection_get_setting_ip4_config(reread); - reread_s_ip6 = nm_connection_get_setting_ip6_config(reread); + reread_s_ip4 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP4_CONFIG); + reread_s_ip6 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpint(nm_setting_ip_config_get_route_metric(reread_s_ip4), ==, 204); g_assert_cmpint(nm_setting_ip_config_get_route_metric(reread_s_ip6), ==, 206); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_equals(connection, FALSE, reread, FALSE); } @@ -4920,10 +4264,7 @@ test_write_wired_static_with_generic(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired Static", @@ -4937,10 +4278,7 @@ test_write_wired_static_with_generic(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", @@ -4948,10 +4286,7 @@ test_write_wired_static_with_generic(void) (guint32) 1492, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -4979,10 +4314,7 @@ test_write_wired_static_with_generic(void) nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com"); nm_setting_ip_config_add_dns_search(s_ip4, "lab.foobar.com"); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_MANUAL, @@ -5039,21 +4371,22 @@ test_write_wired_static_with_generic(void) nm_setting_ip_config_add_dns_search(s_ip6, "foobar6.com"); nm_setting_ip_config_add_dns_search(s_ip6, "lab6.foobar.com"); - nm_connection_add_setting(connection, nm_setting_generic_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_GENERIC); nmtst_assert_connection_verifies(connection); _writer_new_connection_FIXME(connection, TEST_SCRATCH_DIR, &testfile); route6file = utils_get_route6_path(testfile); - reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); - reread_s_ip4 = nm_connection_get_setting_ip4_config(reread); - reread_s_ip6 = nm_connection_get_setting_ip6_config(reread); + reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); + + reread_s_ip4 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP4_CONFIG); + reread_s_ip6 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP6_CONFIG); g_assert_cmpint(nm_setting_ip_config_get_route_metric(reread_s_ip4), ==, 204); g_assert_cmpint(nm_setting_ip_config_get_route_metric(reread_s_ip6), ==, 206); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); { gs_unref_hashtable GHashTable *diffs = NULL; @@ -5064,8 +4397,8 @@ test_write_wired_static_with_generic(void) g_assert(g_hash_table_lookup(diffs, "generic")); g_assert(!nm_connection_compare(connection, reread, NM_SETTING_COMPARE_FLAG_EXACT)); } - g_assert(!nm_connection_get_setting(reread, NM_TYPE_SETTING_GENERIC)); - nm_connection_add_setting(reread, nm_setting_generic_new()); + nmtst_connection_assert_no_setting(reread, NM_TYPE_SETTING_GENERIC); + _nm_connection_new_setting(reread, NM_TYPE_SETTING_GENERIC); { gs_unref_hashtable GHashTable *diffs = NULL; @@ -5082,16 +4415,12 @@ test_write_wired_dhcp(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired DHCP", @@ -5103,14 +4432,9 @@ test_write_wired_dhcp(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, @@ -5130,10 +4454,7 @@ test_write_wired_dhcp(void) nmtst_assert_connection_verifies(connection); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_DHCP, @@ -5195,15 +4516,12 @@ test_write_routing_rules(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; connection = nm_simple_connection_new(); - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Routing Rules", @@ -5215,17 +4533,12 @@ test_write_routing_rules(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_AUTO, NULL); _ip_routing_rule_add_to_setting(s_ip4, "pref 10 from 0.0.0.0/0 table 1"); @@ -5251,17 +4564,13 @@ test_write_wired_match(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingMatch * s_match; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired with Match setting", @@ -5273,31 +4582,26 @@ test_write_wired_match(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + 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, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NULL); - /* Match setting */ - s_match = (NMSettingMatch *) nm_setting_match_new(); + s_match = _nm_connection_new_setting(connection, NM_TYPE_SETTING_MATCH); nm_setting_match_add_interface_name(s_match, "ens*"); nm_setting_match_add_interface_name(s_match, "eth 1?"); nm_setting_match_add_interface_name(s_match, "!veth*"); nm_setting_match_add_driver(s_match, "!virtio"); nm_setting_match_add_driver(s_match, "e1000e"); nm_setting_match_add_kernel_command_line(s_match, "!ip="); - nm_connection_add_setting(connection, NM_SETTING(s_match)); nmtst_assert_connection_verifies(connection); _writer_new_connec_exp(connection, @@ -5343,10 +4647,8 @@ test_read_write_wired_dhcp_send_hostname(void) NULL); /* Check dhcp-hostname and dhcp-send-hostname */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip4); - g_assert(s_ip6); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert(nm_setting_ip_config_get_dhcp_send_hostname(s_ip4) == TRUE); g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip4), ==, "svata-pulec"); g_assert(!nm_setting_ip_config_get_dhcp_hostname(s_ip6)); @@ -5363,10 +4665,8 @@ test_read_write_wired_dhcp_send_hostname(void) nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); /* Check dhcp-hostname and dhcp-send-hostname from the re-read connection. */ - s_ip4 = nm_connection_get_setting_ip4_config(reread); - s_ip6 = nm_connection_get_setting_ip6_config(reread); - g_assert(s_ip4); - g_assert(s_ip6); + s_ip4 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP4_CONFIG); + s_ip6 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP6_CONFIG); g_assert(nm_setting_ip_config_get_dhcp_send_hostname(s_ip4) == FALSE); g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip4), ==, dhcp_hostname); g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, dhcp_hostname); @@ -5383,8 +4683,7 @@ test_read_wired_dhcpv6_hostname_fallback(void) TYPE_ETHERNET, NULL); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); + s_ip6 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_assert(nm_setting_ip_config_get_dhcp_send_hostname(s_ip6) == TRUE); g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, "fully.qualified.domain"); } @@ -5404,10 +4703,7 @@ test_write_wired_static_ip6_only(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired Static IP6 Only", @@ -5419,22 +4715,13 @@ test_write_wired_static_ip6_only(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_MANUAL, NULL); /* Add addresses */ @@ -5462,7 +4749,6 @@ test_write_ip6_disabled(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; @@ -5471,16 +4757,18 @@ test_write_ip6_disabled(void) NM_SETTING_WIRED_SETTING_NAME, &s_con); - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DISABLED, NULL); + 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_DISABLED, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NULL); nmtst_assert_connection_verifies(connection); @@ -5513,16 +4801,14 @@ test_write_wired_static_ip6_only_gw(gconstpointer user_data) NMSettingIPConfig * s_ip6; NMIPAddress * addr6; GError * error = NULL; - char * id = NULL; + gs_free char * id = NULL; gs_free char * written_ifcfg_gateway = NULL; const char * gateway6 = user_data; shvarFile * ifcfg; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); id = g_strdup_printf("Test Write Wired Static IP6 Only With Gateway %s", gateway6 ?: "NULL"); g_object_set(s_con, @@ -5535,24 +4821,14 @@ test_write_wired_static_ip6_only_gw(gconstpointer user_data) NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, NULL); - g_free(id); - - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_MANUAL, @@ -5582,14 +4858,14 @@ test_write_wired_static_ip6_only_gw(gconstpointer user_data) svCloseFile(ifcfg); /* access the gateway from the loaded connection. */ - s_ip6 = nm_connection_get_setting_ip6_config(reread); - g_assert(s_ip6 && nm_setting_ip_config_get_num_addresses(s_ip6) == 1); + s_ip6 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP6_CONFIG); + g_assert(nm_setting_ip_config_get_num_addresses(s_ip6) == 1); addr6 = nm_setting_ip_config_get_address(s_ip6, 0); g_assert(addr6); /* assert that the gateway was written and reloaded as expected */ if (!gateway6 || !strcmp(gateway6, "::")) { - g_assert(nm_setting_ip_config_get_gateway(s_ip6) == NULL); + g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, NULL); g_assert(written_ifcfg_gateway == NULL); } else { g_assert(nm_setting_ip_config_get_gateway(s_ip6) != NULL); @@ -5607,7 +4883,6 @@ test_read_write_static_routes_legacy(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; const char * tmp; @@ -5616,10 +4891,7 @@ test_read_write_static_routes_legacy(void) TYPE_ETHERNET, NULL); - /* ===== CONNECTION SETTING ===== */ - - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); /* ID */ tmp = nm_setting_connection_get_id(s_con); @@ -5628,15 +4900,9 @@ test_read_write_static_routes_legacy(void) /* Autoconnect */ g_assert(nm_setting_connection_get_autoconnect(s_con)); - /* ===== WIRED SETTING ===== */ - - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); + nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); - /* ===== IPv4 SETTING ===== */ - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert(!nm_setting_ip_config_get_never_default(s_ip4)); @@ -5676,10 +4942,7 @@ test_write_wired_static_routes(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired Static Routes", @@ -5691,10 +4954,7 @@ test_write_wired_static_routes(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "31:33:33:37:be:cd", @@ -5702,10 +4962,7 @@ test_write_wired_static_routes(void) (guint32) 1492, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -5746,15 +5003,14 @@ test_write_wired_static_routes(void) nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com"); nm_setting_ip_config_add_dns_search(s_ip4, "lab.foobar.com"); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); nmtst_assert_connection_verifies(connection); @@ -5770,8 +5026,7 @@ test_write_wired_static_routes(void) * connection equals. */ g_assert(!reread_same); nmtst_assert_connection_verifies_without_normalization(reread); - s_ip4 = nm_connection_get_setting_ip4_config(reread); - g_assert(s_ip4); + s_ip4 = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_IP4_CONFIG); g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip4), ==, 2); route = nm_setting_ip_config_get_route(s_ip4, 1); g_assert(route); @@ -5791,7 +5046,6 @@ test_write_wired_dhcp_8021x_peap_mschapv2(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMSetting8021x * s_8021x; @@ -5800,10 +5054,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired DHCP 802.1x PEAP MSCHAPv2", @@ -5815,31 +5066,22 @@ test_write_wired_dhcp_8021x_peap_mschapv2(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); - /* 802.1x setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - + s_8021x = _nm_connection_new_setting(connection, NM_TYPE_SETTING_802_1X); g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bob Saget", @@ -5854,7 +5096,6 @@ test_write_wired_dhcp_8021x_peap_mschapv2(void) NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", NULL); - nm_setting_802_1x_add_eap_method(s_8021x, "peap"); success = nm_setting_802_1x_set_ca_cert(s_8021x, @@ -5883,7 +5124,6 @@ test_write_wired_8021x_tls(gconstpointer test_data) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMSetting8021x * s_8021x; @@ -5891,7 +5131,9 @@ test_write_wired_8021x_tls(gconstpointer test_data) GError * error = NULL; NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; const char * pw; - char * tmp; + gs_free char * tmp1 = NULL; + gs_free char * tmp2 = NULL; + gs_free char * tmp3 = NULL; gpointer scheme_p, flags_p; NMSetting8021xCKScheme scheme; NMSettingSecretFlags flags; @@ -5902,10 +5144,7 @@ test_write_wired_8021x_tls(gconstpointer test_data) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired 802.1x TLS Blobs", @@ -5917,29 +5156,20 @@ test_write_wired_8021x_tls(gconstpointer test_data) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - - /* 802.1x setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); + s_8021x = _nm_connection_new_setting(connection, NM_TYPE_SETTING_802_1X); g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); nm_setting_802_1x_add_eap_method(s_8021x, "tls"); @@ -5992,8 +5222,7 @@ test_write_wired_8021x_tls(gconstpointer test_data) * matter what scheme was used in the original connection they will be read * back in as paths. */ - s_8021x = nm_connection_get_setting_802_1x(reread); - g_assert(s_8021x); + s_8021x = nmtst_connection_assert_setting(reread, NM_TYPE_SETTING_802_1X); g_assert_cmpint(nm_setting_802_1x_get_ca_cert_scheme(s_8021x), ==, NM_SETTING_802_1X_CK_SCHEME_PATH); @@ -6027,7 +5256,7 @@ test_write_wired_8021x_tls(gconstpointer test_data) * say it's not system-owned, and therefore it should not show up * in the re-read connection. */ - s_8021x = nm_connection_get_setting_802_1x(connection); + s_8021x = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_802_1X); g_object_set(s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, NULL, NULL); } @@ -6035,17 +5264,14 @@ test_write_wired_8021x_tls(gconstpointer test_data) } /* Clean up created certs and keys */ - tmp = utils_cert_path(testfile, "ca-cert", "der"); - nmtst_file_unlink_if_exists(tmp); - g_free(tmp); + tmp1 = utils_cert_path(testfile, "ca-cert", "der"); + nmtst_file_unlink_if_exists(tmp1); - tmp = utils_cert_path(testfile, "client-cert", "der"); - nmtst_file_unlink_if_exists(tmp); - g_free(tmp); + tmp2 = utils_cert_path(testfile, "client-cert", "der"); + nmtst_file_unlink_if_exists(tmp2); - tmp = utils_cert_path(testfile, "private-key", "pem"); - nmtst_file_unlink_if_exists(tmp); - g_free(tmp); + tmp3 = utils_cert_path(testfile, "private-key", "pem"); + nmtst_file_unlink_if_exists(tmp3); } static void @@ -6055,7 +5281,6 @@ test_write_wired_aliases(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; int num_addresses = 4; const char * ip[] = {"1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4"}; @@ -6072,10 +5297,7 @@ test_write_wired_aliases(void) connection = nm_simple_connection_new(); g_assert(connection); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "alias0", @@ -6085,14 +5307,9 @@ test_write_wired_aliases(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -6145,7 +5362,7 @@ test_write_wired_aliases(void) * aliases get read back in essentially random order. So just * verify the aliases manually. */ - s_ip4 = nm_connection_get_setting_ip4_config(connection); + s_ip4 = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_assert(nm_setting_ip_config_get_num_addresses(s_ip4) == num_addresses); /* Addresses */ @@ -6191,7 +5408,6 @@ test_write_gateway(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; GError * error = NULL; shvarFile * f; @@ -6199,10 +5415,7 @@ test_write_gateway(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Static Addresses Gateway", @@ -6212,14 +5425,9 @@ test_write_gateway(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -6270,16 +5478,13 @@ test_write_wifi_open(void) NMSettingWireless * s_wifi; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const unsigned char ssid_data[] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44}; - shvarFile * ifcfg; + gs_unref_bytes GBytes *ssid = + nmtst_gbytes_from_arr(0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44); + shvarFile *ifcfg; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi Open", @@ -6291,12 +5496,7 @@ test_write_wifi_open(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6314,23 +5514,17 @@ test_write_wifi_open(void) (guint32) 1345, NULL); - g_bytes_unref(ssid); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); nmtst_assert_connection_verifies(connection); @@ -6356,16 +5550,23 @@ test_write_wifi_open_hex_ssid(void) NMSettingWireless * s_wifi; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const unsigned char ssid_data[] = - {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd}; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_arr(0x11, + 0x22, + 0x33, + 0x44, + 0x55, + 0x66, + 0x77, + 0x88, + 0x99, + 0xaa, + 0xbb, + 0xcc, + 0xdd); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi Open Hex SSID", @@ -6377,12 +5578,7 @@ test_write_wifi_open_hex_ssid(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6390,18 +5586,10 @@ test_write_wifi_open_hex_ssid(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -6430,16 +5618,12 @@ test_write_wifi_wep(void) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; - struct stat statbuf; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + struct stat statbuf; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP", @@ -6451,12 +5635,7 @@ test_write_wifi_wep(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6464,12 +5643,7 @@ test_write_wifi_wep(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", @@ -6483,21 +5657,17 @@ test_write_wifi_wep(void) nm_setting_wireless_security_set_wep_key(s_wsec, 2, "aaaaaaaaaaaaaaaaaaaaaaaaaa"); nm_setting_wireless_security_set_wep_key(s_wsec, 3, "BBBBBBBBBBBBBBBBBBBBBBBBBB"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); nmtst_assert_connection_verifies(connection); @@ -6527,17 +5697,13 @@ test_write_wifi_wep_adhoc(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; GError * error = NULL; - GBytes * ssid; - const char * ssid_data = "blahblah"; - struct stat statbuf; - NMIPAddress * addr; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + struct stat statbuf; + NMIPAddress * addr; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP AdHoc", @@ -6549,27 +5715,14 @@ test_write_wifi_wep_adhoc(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NM_SETTING_WIRELESS_MODE, "adhoc", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); nm_setting_wireless_security_set_wep_key(s_wsec, 0, "0123456789abcdef0123456789"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -6585,10 +5738,7 @@ test_write_wifi_wep_adhoc(void) nm_setting_ip_config_add_dns(s_ip4, "4.2.2.1"); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -6622,16 +5772,12 @@ test_write_wifi_wep_passphrase(void) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; - struct stat statbuf; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + struct stat statbuf; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP Passphrase", @@ -6643,12 +5789,7 @@ test_write_wifi_wep_passphrase(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6656,12 +5797,7 @@ test_write_wifi_wep_passphrase(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", @@ -6674,16 +5810,10 @@ test_write_wifi_wep_passphrase(void) NULL); nm_setting_wireless_security_set_wep_key(s_wsec, 0, "asdfdjaslfjasd;flasjdfl;aksdf"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -6717,16 +5847,12 @@ test_write_wifi_wep_40_ascii(void) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah40"; - struct stat statbuf; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah40"); + struct stat statbuf; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP 40 ASCII", @@ -6738,12 +5864,7 @@ test_write_wifi_wep_40_ascii(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6751,12 +5872,7 @@ test_write_wifi_wep_40_ascii(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", @@ -6772,16 +5888,10 @@ test_write_wifi_wep_40_ascii(void) nm_setting_wireless_security_set_wep_key(s_wsec, 2, "dolor"); nm_setting_wireless_security_set_wep_key(s_wsec, 3, "donec"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -6815,16 +5925,12 @@ test_write_wifi_wep_104_ascii(void) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah104"; - struct stat statbuf; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah104"); + struct stat statbuf; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP 104 ASCII", @@ -6836,12 +5942,7 @@ test_write_wifi_wep_104_ascii(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6849,12 +5950,7 @@ test_write_wifi_wep_104_ascii(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", @@ -6870,16 +5966,10 @@ test_write_wifi_wep_104_ascii(void) nm_setting_wireless_security_set_wep_key(s_wsec, 2, "WEP-104 ASCII"); nm_setting_wireless_security_set_wep_key(s_wsec, 3, "thisismyascii"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -6916,16 +6006,12 @@ test_write_wifi_leap(void) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; - struct stat statbuf; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + struct stat statbuf; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi LEAP", @@ -6937,12 +6023,7 @@ test_write_wifi_leap(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -6950,12 +6031,7 @@ test_write_wifi_leap(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", @@ -6967,16 +6043,10 @@ test_write_wifi_leap(void) "foobar22", NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7013,17 +6083,13 @@ test_write_wifi_leap_secret_flags(gconstpointer data) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; - NMSettingSecretFlags flags = GPOINTER_TO_UINT(data); + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + NMSettingSecretFlags flags = GPOINTER_TO_UINT(data); connection = nm_simple_connection_new(); g_assert(connection); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi LEAP Secret Flags", @@ -7033,23 +6099,15 @@ test_write_wifi_leap_secret_flags(gconstpointer data) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NM_SETTING_WIRELESS_MODE, "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", @@ -7063,15 +6121,10 @@ test_write_wifi_leap_secret_flags(gconstpointer data) flags, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7108,8 +6161,7 @@ test_write_wifi_wpa_psk(gconstpointer test_data) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); struct { const char *name, *psk; gpointer wep_group_p, wpa_p, wpa2_p; @@ -7126,10 +6178,7 @@ test_write_wifi_wpa_psk(gconstpointer test_data) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, args.name, @@ -7141,12 +6190,7 @@ test_write_wifi_wpa_psk(gconstpointer test_data) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7154,12 +6198,7 @@ test_write_wifi_wpa_psk(gconstpointer test_data) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", @@ -7184,16 +6223,10 @@ test_write_wifi_wpa_psk(gconstpointer test_data) nm_setting_wireless_security_add_group(s_wsec, "ccmp"); } - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7225,16 +6258,12 @@ test_write_wifi_wpa_psk_adhoc(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; GError * error = NULL; - GBytes * ssid; - const char * ssid_data = "blahblah"; - NMIPAddress * addr; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + NMIPAddress * addr; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA PSK", @@ -7246,12 +6275,7 @@ test_write_wifi_wpa_psk_adhoc(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7263,12 +6287,7 @@ test_write_wifi_wpa_psk_adhoc(void) "bg", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", @@ -7280,10 +6299,7 @@ test_write_wifi_wpa_psk_adhoc(void) nm_setting_wireless_security_add_pairwise(s_wsec, "ccmp"); nm_setting_wireless_security_add_group(s_wsec, "ccmp"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -7299,10 +6315,7 @@ test_write_wifi_wpa_psk_adhoc(void) nm_setting_ip_config_add_dns(s_ip4, "4.2.2.1"); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7336,15 +6349,11 @@ test_write_wifi_wpa_eap_tls(void) NMSettingIPConfig * s_ip6; gboolean success; GError * error = NULL; - GBytes * ssid; - const char * ssid_data = "blahblah"; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TLS", @@ -7356,12 +6365,7 @@ test_write_wifi_wpa_eap_tls(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7369,12 +6373,7 @@ test_write_wifi_wpa_eap_tls(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", @@ -7385,17 +6384,14 @@ test_write_wifi_wpa_eap_tls(void) nm_setting_wireless_security_add_pairwise(s_wsec, "tkip"); nm_setting_wireless_security_add_group(s_wsec, "tkip"); - /* Wireless security setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + s_8021x = _nm_connection_new_setting(connection, NM_TYPE_SETTING_802_1X); g_object_set(s_8021x, + NM_SETTING_802_1X_IDENTITY, + "Bill Smith", NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, (guint) (NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE), NULL); - nm_setting_802_1x_add_eap_method(s_8021x, "tls"); success = nm_setting_802_1x_set_ca_cert(s_8021x, @@ -7420,16 +6416,10 @@ test_write_wifi_wpa_eap_tls(void) &error); nmtst_assert_success(success, error); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7463,15 +6453,11 @@ test_write_wifi_wpa_eap_ttls_tls(void) NMSettingIPConfig * s_ip6; gboolean success; GError * error = NULL; - GBytes * ssid; - const char * ssid_data = "blahblah"; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TTLS (TLS)", @@ -7483,12 +6469,7 @@ test_write_wifi_wpa_eap_ttls_tls(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7496,23 +6477,14 @@ test_write_wifi_wpa_eap_ttls_tls(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); nm_setting_wireless_security_add_proto(s_wsec, "rsn"); nm_setting_wireless_security_add_pairwise(s_wsec, "ccmp"); nm_setting_wireless_security_add_group(s_wsec, "ccmp"); - /* Wireless security setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - + s_8021x = _nm_connection_new_setting(connection, NM_TYPE_SETTING_802_1X); nm_setting_802_1x_add_eap_method(s_8021x, "ttls"); - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", @@ -7556,16 +6528,10 @@ test_write_wifi_wpa_eap_ttls_tls(void) &error); nmtst_assert_success(success, error); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7599,15 +6565,11 @@ test_write_wifi_wpa_eap_ttls_mschapv2(void) NMSettingIPConfig * s_ip6; gboolean success; GError * error = NULL; - GBytes * ssid; - const char * ssid_data = "blahblah"; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TTLS (MSCHAPv2)", @@ -7619,12 +6581,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7632,12 +6589,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); nm_setting_wireless_security_add_proto(s_wsec, "wpa"); nm_setting_wireless_security_add_proto(s_wsec, "rsn"); @@ -7646,12 +6598,8 @@ test_write_wifi_wpa_eap_ttls_mschapv2(void) nm_setting_wireless_security_add_group(s_wsec, "tkip"); nm_setting_wireless_security_add_group(s_wsec, "ccmp"); - /* Wireless security setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - + s_8021x = _nm_connection_new_setting(connection, NM_TYPE_SETTING_802_1X); nm_setting_802_1x_add_eap_method(s_8021x, "ttls"); - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", @@ -7670,16 +6618,10 @@ test_write_wifi_wpa_eap_ttls_mschapv2(void) &error); nmtst_assert_success(success, error); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -7704,14 +6646,14 @@ test_write_wifi_wpa_then_open(void) nmtst_auto_unlinkfile char *testfile = NULL; gs_free char * keyfile = NULL; gs_unref_object NMConnection *connection = NULL; - gs_unref_object NMConnection *reread = NULL; + gs_unref_object NMConnection *reread1 = NULL; + gs_unref_object NMConnection *reread2 = NULL; NMSettingConnection * s_con; NMSettingWireless * s_wifi; NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); /* Test that writing out a WPA config then changing that to an open * config doesn't leave various WPA-related keys lying around in the ifcfg. @@ -7719,10 +6661,7 @@ test_write_wifi_wpa_then_open(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "random wifi connection", @@ -7734,12 +6673,7 @@ test_write_wifi_wpa_then_open(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7747,12 +6681,7 @@ test_write_wifi_wpa_then_open(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", @@ -7768,30 +6697,26 @@ test_write_wifi_wpa_then_open(void) nm_setting_wireless_security_add_pairwise(s_wsec, "ccmp"); nm_setting_wireless_security_add_group(s_wsec, "ccmp"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); nmtst_assert_connection_verifies(connection); _writer_new_connection(connection, TEST_SCRATCH_DIR, &testfile); - reread = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); - - nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); + reread1 = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); - g_object_unref(reread); + nmtst_assert_connection_equals(connection, TRUE, reread1, FALSE); nmtst_connection_normalize(connection); @@ -7806,9 +6731,9 @@ test_write_wifi_wpa_then_open(void) keyfile = utils_get_keys_path(testfile); g_assert(!g_file_test(keyfile, G_FILE_TEST_EXISTS)); - reread = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); + reread2 = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); - nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); + nmtst_assert_connection_equals(connection, TRUE, reread2, FALSE); } static void @@ -7817,16 +6742,15 @@ test_write_wifi_wpa_then_wep_with_perms(void) nmtst_auto_unlinkfile char *testfile = NULL; nmtst_auto_unlinkfile char *keyfile = NULL; gs_unref_object NMConnection *connection = NULL; - gs_unref_object NMConnection *reread = NULL; + gs_unref_object NMConnection *reread1 = NULL; + gs_unref_object NMConnection *reread2 = NULL; NMSettingConnection * s_con; NMSettingWireless * s_wifi; NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; gboolean success; - GBytes * ssid; - char ** perms; - const char * ssid_data = "SomeSSID"; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("SomeSSID"); /* Test that writing out a WPA config then changing that to a WEP * config works and doesn't cause infinite loop or other issues. @@ -7835,11 +6759,7 @@ test_write_wifi_wpa_then_wep_with_perms(void) connection = nm_simple_connection_new(); g_assert(connection); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - - perms = g_strsplit("user:superman:", ",", -1); + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "random wifi connection 2", @@ -7848,19 +6768,13 @@ test_write_wifi_wpa_then_wep_with_perms(void) NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NM_SETTING_CONNECTION_PERMISSIONS, - perms, + NM_MAKE_STRV("user:superman:"), NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, NULL); - g_strfreev(perms); g_assert_cmpint(nm_setting_connection_get_num_permissions(s_con), ==, 1); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7868,12 +6782,7 @@ test_write_wifi_wpa_then_wep_with_perms(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", @@ -7889,38 +6798,31 @@ test_write_wifi_wpa_then_wep_with_perms(void) nm_setting_wireless_security_add_pairwise(s_wsec, "ccmp"); nm_setting_wireless_security_add_group(s_wsec, "ccmp"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); nmtst_assert_connection_verifies(connection); _writer_new_connection(connection, TEST_SCRATCH_DIR, &testfile); - reread = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); - - nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); + reread1 = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); - g_object_unref(reread); + nmtst_assert_connection_equals(connection, TRUE, reread1, FALSE); nmtst_connection_normalize(connection); /* Now change the connection to WEP and recheck */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); nm_setting_wireless_security_set_wep_key(s_wsec, 0, "abraka dabra"); @@ -7931,11 +6833,11 @@ test_write_wifi_wpa_then_wep_with_perms(void) testfile, TEST_IFCFG_DIR "/ifcfg-random_wifi_connection_2.cexpected"); - reread = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); + reread2 = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL); nmtst_connection_normalize(connection); success = nm_connection_compare(connection, - reread, + reread2, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS); g_assert(success); @@ -7956,15 +6858,12 @@ test_write_wifi_dynamic_wep_leap(void) NMSetting8021x * s_8021x; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - GBytes * ssid; - const char * ssid_data = "blahblah"; - shvarFile * ifcfg; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("blahblah"); + shvarFile * ifcfg; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi Dynamic WEP LEAP", @@ -7974,12 +6873,7 @@ test_write_wifi_dynamic_wep_leap(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(ssid_data, strlen(ssid_data)); - + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, @@ -7987,20 +6881,11 @@ test_write_wifi_dynamic_wep_leap(void) "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wireless security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); - + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", NULL); - /* Wireless security setting */ - s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s_8021x)); - + s_8021x = _nm_connection_new_setting(connection, NM_TYPE_SETTING_802_1X); nm_setting_802_1x_add_eap_method(s_8021x, "leap"); - g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", @@ -8008,15 +6893,10 @@ test_write_wifi_dynamic_wep_leap(void) ";alkdfja;dslkfjsad;lkfjsadf", NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); + 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, @@ -8054,14 +6934,10 @@ test_write_wired_qeth_dhcp(void) NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - char ** subchans; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired qeth Static", @@ -8073,34 +6949,23 @@ test_write_wired_qeth_dhcp(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - subchans = g_strsplit("0.0.600,0.0.601,0.0.602", ",", -1); + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, - subchans, + NM_MAKE_STRV("0.0.600", "0.0.601", "0.0.602"), NM_SETTING_WIRED_S390_NETTYPE, "qeth", NULL); - g_strfreev(subchans); nm_setting_wired_add_s390_option(s_wired, "portname", "FOOBAR"); nm_setting_wired_add_s390_option(s_wired, "portno", "1"); nm_setting_wired_add_s390_option(s_wired, "layer2", "0"); nm_setting_wired_add_s390_option(s_wired, "protocol", "blahbalh"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -8127,15 +6992,11 @@ test_write_wired_ctc_dhcp(void) NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - char ** subchans; shvarFile * ifcfg; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired ctc Static", @@ -8145,29 +7006,19 @@ test_write_wired_ctc_dhcp(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - subchans = g_strsplit("0.0.600,0.0.601", ",", -1); + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, - subchans, + NM_MAKE_STRV("0.0.600", "0.0.601"), NM_SETTING_WIRED_S390_NETTYPE, "ctc", NULL); - g_strfreev(subchans); nm_setting_wired_add_s390_option(s_wired, "ctcprot", "0"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -8201,16 +7052,12 @@ test_write_permissions(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Permissions", @@ -8226,20 +7073,12 @@ test_write_permissions(void) nm_setting_connection_add_permission(s_con, "user", "foobar", NULL); nm_setting_connection_add_permission(s_con, "user", "asdfasdf", NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, @@ -8270,16 +7109,12 @@ test_write_wifi_wep_agent_keys(void) NMSettingWirelessSecurity * s_wsec; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - const char * str_ssid = "foobarbaz"; - GBytes * ssid; + gs_unref_bytes GBytes *ssid = nmtst_gbytes_from_str("foobarbaz"); connection = nm_simple_connection_new(); g_assert(connection != NULL); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP Agent Owned", @@ -8289,39 +7124,28 @@ test_write_wifi_wep_agent_keys(void) NM_SETTING_WIRELESS_SETTING_NAME, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); - /* Wifi setting */ - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - - ssid = g_bytes_new(str_ssid, strlen(str_ssid)); + s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS); g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NM_SETTING_WIRELESS_MODE, "infrastructure", NULL); - g_bytes_unref(ssid); - - /* Wifi security setting */ - s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + s_wsec = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS_SECURITY); g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", @@ -8352,20 +7176,14 @@ test_write_wifi_wep_agent_keys(void) static void test_write_wired_pppoe(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingPppoe * s_pppoe; - NMSettingPpp * s_ppp; - GError * error = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingPppoe * s_pppoe; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Wired PPPoE", @@ -8377,21 +7195,13 @@ test_write_wired_pppoe(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* PPPoE setting */ - s_pppoe = (NMSettingPppoe *) nm_setting_pppoe_new(); - nm_connection_add_setting(connection, NM_SETTING(s_pppoe)); - - g_object_set(G_OBJECT(s_pppoe), + s_pppoe = _nm_connection_new_setting(connection, NM_TYPE_SETTING_PPPOE); + g_object_set(s_pppoe, NM_SETTING_PPPOE_SERVICE, "stupid-service", NM_SETTING_PPPOE_USERNAME, @@ -8400,33 +7210,24 @@ test_write_wired_pppoe(void) "test1", NULL); - /* PPP setting */ - s_ppp = (NMSettingPpp *) nm_setting_ppp_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ppp)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PPP); nmtst_assert_connection_verifies(connection); _writer_new_connection_fail(connection, TEST_SCRATCH_DIR, NULL); - - g_object_unref(connection); - g_clear_error(&error); } static void test_write_vpn(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingVpn * s_vpn; - GError * error = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingVpn * s_vpn; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write VPN", @@ -8438,10 +7239,7 @@ test_write_vpn(void) NM_SETTING_VPN_SETTING_NAME, NULL); - /* VPN setting */ - s_vpn = (NMSettingVpn *) nm_setting_vpn_new(); - nm_connection_add_setting(connection, NM_SETTING(s_vpn)); - + s_vpn = _nm_connection_new_setting(connection, NM_TYPE_SETTING_VPN); g_object_set(s_vpn, NM_SETTING_VPN_SERVICE_TYPE, "awesomevpn", @@ -8452,39 +7250,27 @@ test_write_vpn(void) nm_setting_vpn_add_data_item(s_vpn, "server", "vpn.somewhere.com"); nm_setting_vpn_add_secret(s_vpn, "password", "sup3rs3cr3t"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); nmtst_assert_connection_verifies(connection); _writer_new_connection_fail(connection, TEST_SCRATCH_DIR, NULL); - - g_object_unref(connection); - g_clear_error(&error); } static void test_write_mobile_broadband(gconstpointer data) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingIPConfig * s_ip4; - NMSettingGsm * s_gsm; - NMSettingCdma * s_cdma; - NMSettingPpp * s_ppp; - NMSettingSerial * s_serial; - GError * error = NULL; - gboolean gsm = GPOINTER_TO_UINT(data); + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingIPConfig * s_ip4; + NMSettingCdma * s_cdma; + NMSettingSerial * s_serial; + gboolean gsm = GPOINTER_TO_UINT(data); connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, gsm ? "Test Write GSM" : "Test Write CDMA", @@ -8496,22 +7282,14 @@ test_write_mobile_broadband(gconstpointer data) gsm ? NM_SETTING_GSM_SETTING_NAME : NM_SETTING_CDMA_SETTING_NAME, NULL); - if (gsm) { - /* GSM setting */ - s_gsm = (NMSettingGsm *) nm_setting_gsm_new(); - nm_connection_add_setting(connection, NM_SETTING(s_gsm)); - } else { - /* CDMA setting */ - s_cdma = (NMSettingCdma *) nm_setting_cdma_new(); - nm_connection_add_setting(connection, NM_SETTING(s_cdma)); - + if (gsm) + _nm_connection_new_setting(connection, NM_TYPE_SETTING_GSM); + else { + s_cdma = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CDMA); g_object_set(s_cdma, NM_SETTING_CDMA_NUMBER, "#777", NULL); } - /* Serial setting */ - s_serial = (NMSettingSerial *) nm_setting_serial_new(); - nm_connection_add_setting(connection, NM_SETTING(s_serial)); - + s_serial = _nm_connection_new_setting(connection, NM_TYPE_SETTING_SERIAL); g_object_set(s_serial, NM_SETTING_SERIAL_BAUD, 115200, @@ -8523,42 +7301,31 @@ test_write_mobile_broadband(gconstpointer data) 1, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* PPP setting */ - s_ppp = (NMSettingPpp *) nm_setting_ppp_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ppp)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PPP); nmtst_assert_connection_verifies(connection); _writer_new_connection_fail(connection, TEST_SCRATCH_DIR, NULL); - - g_object_unref(connection); - g_clear_error(&error); } static void test_read_bridge_main(void) { - NMConnection * connection; - NMSettingBridge *s_bridge; - NMSettingWired * s_wired; - const char * mac; - char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; + gs_unref_object NMConnection *connection = NULL; + NMSettingBridge * s_bridge; + NMSettingWired * s_wired; + const char * mac; + char expected_mac_address[ETH_ALEN] = {0x00, 0x16, 0x41, 0x11, 0x22, 0x33}; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bridge-main", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "br0"); - /* ===== Bridging SETTING ===== */ - - s_bridge = nm_connection_get_setting_bridge(connection); - g_assert(s_bridge); + s_bridge = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BRIDGE); g_assert_cmpuint(nm_setting_bridge_get_forward_delay(s_bridge), ==, 2); g_assert(nm_setting_bridge_get_stp(s_bridge)); g_assert_cmpuint(nm_setting_bridge_get_priority(s_bridge), ==, 32744); @@ -8570,14 +7337,10 @@ test_read_bridge_main(void) g_assert_cmpint(nm_setting_bridge_get_vlan_filtering(s_bridge), ==, TRUE); g_assert_cmpint(nm_setting_bridge_get_vlan_default_pvid(s_bridge), ==, 99); - /* MAC address */ - s_wired = nm_connection_get_setting_wired(connection); - g_assert(s_wired); - mac = nm_setting_wired_get_cloned_mac_address(s_wired); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); + mac = nm_setting_wired_get_cloned_mac_address(s_wired); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, ETH_ALEN)); - - g_object_unref(connection); } static void @@ -8588,8 +7351,8 @@ test_write_bridge_main(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingBridge * s_bridge; - NMSettingIPConfig * s_ip4, *s_ip6; - NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; NMIPAddress * addr; static const char * mac = "31:33:33:37:be:cd"; GError * error = NULL; @@ -8599,10 +7362,7 @@ test_write_bridge_main(void) connection = nm_simple_connection_new(); g_assert(connection); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Bridge Main", @@ -8616,9 +7376,7 @@ test_write_bridge_main(void) NM_SETTING_BRIDGE_SETTING_NAME, NULL); - /* bridge setting */ - s_bridge = (NMSettingBridge *) nm_setting_bridge_new(); - nm_connection_add_setting(connection, NM_SETTING(s_bridge)); + s_bridge = _nm_connection_new_setting(connection, NM_TYPE_SETTING_BRIDGE); vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); vlan = nm_bridge_vlan_new(10, 16); @@ -8644,10 +7402,7 @@ test_write_bridge_main(void) vlans, NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -8662,17 +7417,12 @@ test_write_bridge_main(void) nm_setting_ip_config_add_address(s_ip4, addr); nm_ip_address_unref(addr); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_verifies_without_normalization(connection); @@ -8686,29 +7436,25 @@ test_write_bridge_main(void) static void test_read_bridge_component(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingBridgePort *s_port; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingBridgePort * s_port; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bridge-component", NULL, TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "br0"); g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME); - s_port = nm_connection_get_setting_bridge_port(connection); - g_assert(s_port); + s_port = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BRIDGE_PORT); g_assert(nm_setting_bridge_port_get_hairpin_mode(s_port)); g_assert_cmpuint(nm_setting_bridge_port_get_priority(s_port), ==, 28); g_assert_cmpuint(nm_setting_bridge_port_get_path_cost(s_port), ==, 100); - - g_object_unref(connection); } static void @@ -8728,10 +7474,7 @@ test_write_bridge_component(void) connection = nm_simple_connection_new(); g_assert(connection); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Bridge Component", @@ -8747,10 +7490,7 @@ test_write_bridge_component(void) NM_SETTING_BRIDGE_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NM_SETTING_WIRED_MTU, mtu, NULL); /* Bridge port */ @@ -8765,8 +7505,7 @@ test_write_bridge_component(void) nm_bridge_vlan_set_pvid(vlan, TRUE); g_ptr_array_add(vlans, vlan); - s_port = nm_setting_bridge_port_new(); - nm_connection_add_setting(connection, s_port); + s_port = _nm_connection_new_setting(connection, NM_TYPE_SETTING_BRIDGE_PORT); g_object_set(s_port, NM_SETTING_BRIDGE_PORT_PRIORITY, 50, @@ -8791,8 +7530,8 @@ test_write_bridge_component(void) static void test_read_bridge_missing_stp(void) { - NMConnection * connection; - NMSettingBridge *s_bridge; + gs_unref_object NMConnection *connection = NULL; + NMSettingBridge * s_bridge; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bridge-missing-stp", NULL, @@ -8801,13 +7540,8 @@ test_read_bridge_missing_stp(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "br0"); - /* ===== Bridging SETTING ===== */ - - s_bridge = nm_connection_get_setting_bridge(connection); - g_assert(s_bridge); + s_bridge = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BRIDGE); g_assert(nm_setting_bridge_get_stp(s_bridge) == FALSE); - - g_object_unref(connection); } #define TEST_IFCFG_VLAN_INTERFACE TEST_IFCFG_DIR "/ifcfg-test-vlan-interface" @@ -8815,16 +7549,16 @@ test_read_bridge_missing_stp(void) static void test_read_vlan_interface(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; - guint32 from = 0, to = 0; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; + guint32 from = 0; + guint32 to = 0; connection = _connection_from_file(TEST_IFCFG_VLAN_INTERFACE, NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "vlan43"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth9"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 43); @@ -8857,8 +7591,6 @@ test_read_vlan_interface(void) g_assert(nm_setting_vlan_get_priority(s_vlan, NM_VLAN_EGRESS_MAP, 2, &from, &to)); g_assert_cmpint(from, ==, 14); g_assert_cmpint(to, ==, 7); - - g_object_unref(connection); } #define TEST_IFCFG_VLAN_ONLY_VLANID TEST_IFCFG_DIR "/ifcfg-test-vlan-only-vlanid" @@ -8866,21 +7598,18 @@ test_read_vlan_interface(void) static void test_read_vlan_only_vlan_id(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; connection = _connection_from_file(TEST_IFCFG_VLAN_ONLY_VLANID, NULL, TYPE_ETHERNET, NULL); g_assert(nm_connection_get_interface_name(connection) == NULL); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth9"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 43); g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS); - - g_object_unref(connection); } static void @@ -8898,8 +7627,7 @@ test_read_vlan_vlanid_use(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "eth0.9"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 10); @@ -8918,8 +7646,8 @@ test_read_vlan_vlanid_use(void) static void test_read_vlan_only_device(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-only-device", NULL, @@ -8928,40 +7656,34 @@ test_read_vlan_only_device(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "eth0.9"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 9); - - g_object_unref(connection); } static void test_read_vlan_physdev(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-physdev", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "vlan0.3"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 3); - - g_object_unref(connection); } static void test_read_vlan_reorder_hdr_1(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; NMTST_EXPECT_NM_WARN("*REORDER_HDR key is deprecated, use VLAN_FLAGS*"); connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-reorder-hdr-1", @@ -8972,22 +7694,19 @@ test_read_vlan_reorder_hdr_1(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "vlan0.3"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 3); /* Check that REORDER_HDR=0 is ignored */ g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS); - - g_object_unref(connection); } static void test_read_vlan_reorder_hdr_2(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-reorder-hdr-2", NULL, @@ -8996,61 +7715,52 @@ test_read_vlan_reorder_hdr_2(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "vlan0.3"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 3); /* Check that VLAN_FLAGS=NO_REORDER_HDR works */ g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_LOOSE_BINDING); - - g_object_unref(connection); } static void test_read_vlan_flags_1(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-flags-1", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "super-vlan"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth9"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 44); g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_LOOSE_BINDING | NM_VLAN_FLAG_REORDER_HEADERS); - - g_object_unref(connection); } static void test_read_vlan_flags_2(void) { - NMConnection * connection; - NMSettingVlan *s_vlan; + gs_unref_object NMConnection *connection = NULL; + NMSettingVlan * s_vlan; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-vlan-flags-2", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "super-vlan"); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth9"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 44); g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_GVRP | NM_VLAN_FLAG_LOOSE_BINDING | NM_VLAN_FLAG_REORDER_HEADERS); - - g_object_unref(connection); } static void @@ -9108,14 +7818,10 @@ test_write_vlan_reorder_hdr(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingVlan * s_vlan; - NMSettingWired * s_wired; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write VLAN reorder_hdr", @@ -9127,14 +7833,9 @@ test_write_vlan_reorder_hdr(void) NM_SETTING_VLAN_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* VLAN setting */ - s_vlan = (NMSettingVlan *) nm_setting_vlan_new(); - nm_connection_add_setting(connection, NM_SETTING(s_vlan)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_vlan = _nm_connection_new_setting(connection, NM_TYPE_SETTING_VLAN); g_object_set(s_vlan, NM_SETTING_VLAN_PARENT, "eth0", @@ -9161,16 +7862,12 @@ test_write_ethernet_missing_ipv6(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; connection = nm_simple_connection_new(); g_assert(connection); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Ethernet Without IPv6 Setting", @@ -9182,13 +7879,9 @@ test_write_ethernet_missing_ipv6(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, @@ -9227,31 +7920,26 @@ test_read_ibft_ignored(void) static void test_read_bond_main(void) { - NMConnection * connection; - NMSettingBond *s_bond; + gs_unref_object NMConnection *connection = NULL; + NMSettingBond * s_bond; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bond-main", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "bond0"); - /* ===== Bonding SETTING ===== */ - - s_bond = nm_connection_get_setting_bond(connection); - g_assert(s_bond); + s_bond = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BOND); g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MIIMON), ==, "100"); - - g_object_unref(connection); } static void test_read_bond_eth_type(void) { - NMConnection * connection; - NMSettingBond *s_bond; + gs_unref_object NMConnection *connection = NULL; + NMSettingBond * s_bond; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bond-eth-type", NULL, @@ -9260,10 +7948,7 @@ test_read_bond_eth_type(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "bond0"); - /* ===== Bonding SETTING ===== */ - - s_bond = nm_connection_get_setting_bond(connection); - g_assert(s_bond); + s_bond = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BOND); g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MIIMON), ==, @@ -9271,8 +7956,6 @@ test_read_bond_eth_type(void) g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_LACP_RATE), ==, "1"); - - g_object_unref(connection); } static void @@ -9285,16 +7968,12 @@ test_write_bond_main(void) NMSettingBond * s_bond; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; NMIPAddress * addr; GError * error = NULL; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Bond Main", @@ -9308,22 +7987,14 @@ test_write_bond_main(void) NM_SETTING_BOND_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* bond setting */ - s_bond = (NMSettingBond *) nm_setting_bond_new(); - nm_connection_add_setting(connection, NM_SETTING(s_bond)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_bond = _nm_connection_new_setting(connection, NM_TYPE_SETTING_BOND); nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "5"); nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_UPDELAY, "10"); nm_setting_bond_add_option(s_bond, NM_SETTING_BOND_OPTION_MIIMON, "100"); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -9338,13 +8009,10 @@ test_write_bond_main(void) nm_setting_ip_config_add_address(s_ip4, addr); nm_ip_address_unref(addr); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_verifies_without_normalization(connection); @@ -9361,21 +8029,18 @@ test_write_bond_main(void) static void test_read_bond_slave(void) { - NMConnection * connection; - NMSettingConnection *s_con; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bond-slave", NULL, TYPE_ETHERNET, NULL); g_test_assert_expected_messages(); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "bond0"); g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - - g_object_unref(connection); } static void @@ -9391,10 +8056,7 @@ test_write_bond_slave(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Bond Slave", @@ -9410,10 +8072,7 @@ test_write_bond_slave(void) NM_SETTING_BOND_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - + s_wired = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NM_SETTING_WIRED_MTU, mtu, NULL); nmtst_assert_connection_verifies(connection); @@ -9425,13 +8084,72 @@ test_write_bond_slave(void) nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); } +static void +test_read_bond_port(void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con = NULL; + NMSettingBondPort * s_port = NULL; + + connection = + _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bond-port", NULL, TYPE_ETHERNET, NULL); + + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); + g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "bond99"); + g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); + + s_port = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BOND_PORT); + g_assert_cmpuint(nm_setting_bond_port_get_queue_id(s_port), ==, 1); +} + +static void +test_write_bond_port(void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingConnection * s_con; + NMSettingBondPort * s_bond_port; + + 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 Bond Port", + NM_SETTING_CONNECTION_UUID, + nm_uuid_generate_random_str_a(), + NM_SETTING_CONNECTION_AUTOCONNECT, + TRUE, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_MASTER, + "bond0", + NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_BOND_SETTING_NAME, + NULL); + + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + + s_bond_port = _nm_connection_new_setting(connection, NM_TYPE_SETTING_BOND_PORT); + g_object_set(s_bond_port, NM_SETTING_BOND_PORT_QUEUE_ID, 1, NULL); + + nmtst_assert_connection_verifies(connection); + + _writer_new_connection(connection, TEST_SCRATCH_DIR, &testfile); + + reread = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); + + nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); +} + static void test_read_infiniband(void) { - NMConnection * connection; - NMSettingInfiniband *s_infiniband; - char * unmanaged = NULL; - const char * mac; + gs_unref_object NMConnection *connection = NULL; + NMSettingInfiniband * s_infiniband; + char * unmanaged = NULL; + const char * mac; char expected_mac_address[INFINIBAND_ALEN] = {0x80, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22}; @@ -9443,22 +8161,15 @@ test_read_infiniband(void) &unmanaged); g_assert(!unmanaged); - /* ===== INFINIBAND SETTING ===== */ + s_infiniband = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_INFINIBAND); - s_infiniband = nm_connection_get_setting_infiniband(connection); - g_assert(s_infiniband); - - /* MAC address */ mac = nm_setting_infiniband_get_mac_address(s_infiniband); g_assert(mac); g_assert(nm_utils_hwaddr_matches(mac, -1, expected_mac_address, sizeof(expected_mac_address))); - /* Transport mode */ transport_mode = nm_setting_infiniband_get_transport_mode(s_infiniband); g_assert(transport_mode); g_assert_cmpstr(transport_mode, ==, "connected"); - - g_object_unref(connection); } static void @@ -9478,10 +8189,7 @@ test_write_infiniband(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write InfiniBand", @@ -9493,10 +8201,7 @@ test_write_infiniband(void) NM_SETTING_INFINIBAND_SETTING_NAME, NULL); - /* InfiniBand setting */ - s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new(); - nm_connection_add_setting(connection, NM_SETTING(s_infiniband)); - + s_infiniband = _nm_connection_new_setting(connection, NM_TYPE_SETTING_INFINIBAND); g_object_set(s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, @@ -9506,10 +8211,7 @@ test_write_infiniband(void) "connected", NULL); - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); - + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -9524,10 +8226,7 @@ test_write_infiniband(void) nm_setting_ip_config_add_address(s_ip4, addr); nm_ip_address_unref(addr); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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); nmtst_assert_connection_verifies(connection); @@ -9548,8 +8247,7 @@ test_read_bond_slave_ib(void) connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bond-slave-ib", NULL, NULL, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "bond0"); g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); @@ -9567,10 +8265,7 @@ test_write_bond_slave_ib(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Bond Slave InfiniBand", @@ -9586,10 +8281,7 @@ test_write_bond_slave_ib(void) NM_SETTING_BOND_SETTING_NAME, NULL); - /* InfiniBand setting */ - s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new(); - nm_connection_add_setting(connection, NM_SETTING(s_infiniband)); - + s_infiniband = _nm_connection_new_setting(connection, NM_TYPE_SETTING_INFINIBAND); g_object_set(s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, @@ -9611,9 +8303,9 @@ test_write_bond_slave_ib(void) static void test_read_bond_opts_mode_numeric(void) { - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingBond * s_bond; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingBond * s_bond; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-bond-mode-numeric", NULL, @@ -9622,19 +8314,15 @@ test_read_bond_opts_mode_numeric(void) g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "bond0"); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_BOND_SETTING_NAME); - s_bond = nm_connection_get_setting_bond(connection); - g_assert(s_bond); + s_bond = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_BOND); g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, NM_SETTING_BOND_OPTION_MODE), ==, "802.3ad"); - - g_object_unref(connection); } #define DCB_ALL_FLAGS \ @@ -9643,20 +8331,19 @@ test_read_bond_opts_mode_numeric(void) static void test_read_dcb_basic(void) { - NMConnection *connection; - NMSettingDcb *s_dcb; - guint i; - guint expected_group_ids[8] = {0, 0, 0, 0, 1, 1, 1, 0xF}; - guint expected_group_bandwidths[8] = {25, 0, 0, 75, 0, 0, 0, 0}; - guint expected_bandwidths[8] = {5, 10, 30, 25, 10, 50, 5, 0}; - gboolean expected_strict[8] = {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE}; - guint expected_traffic_classes[8] = {7, 6, 5, 4, 3, 2, 1, 0}; - gboolean expected_pfcs[8] = {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE}; + gs_unref_object NMConnection *connection = NULL; + NMSettingDcb * s_dcb; + guint i; + guint expected_group_ids[8] = {0, 0, 0, 0, 1, 1, 1, 0xF}; + guint expected_group_bandwidths[8] = {25, 0, 0, 75, 0, 0, 0, 0}; + guint expected_bandwidths[8] = {5, 10, 30, 25, 10, 50, 5, 0}; + gboolean expected_strict[8] = {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE}; + guint expected_traffic_classes[8] = {7, 6, 5, 4, 3, 2, 1, 0}; + gboolean expected_pfcs[8] = {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE}; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-dcb", NULL, TYPE_ETHERNET, NULL); - s_dcb = nm_connection_get_setting_dcb(connection); - g_assert(s_dcb); + s_dcb = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_DCB); g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, DCB_ALL_FLAGS); g_assert_cmpint(nm_setting_dcb_get_app_fcoe_priority(s_dcb), ==, 7); @@ -9702,8 +8389,6 @@ test_read_dcb_basic(void) g_assert_cmpint(nm_setting_dcb_get_priority_traffic_class(s_dcb, i), ==, expected_traffic_classes[i]); - - g_object_unref(connection); } static void @@ -9713,7 +8398,6 @@ test_write_dcb_basic(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingDcb * s_dcb; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; @@ -9727,9 +8411,8 @@ test_write_dcb_basic(void) connection = nm_simple_connection_new(); - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - g_object_set(G_OBJECT(s_con), + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); + g_object_set(s_con, NM_SETTING_CONNECTION_ID, "dcb-test", NM_SETTING_CONNECTION_UUID, @@ -9740,30 +8423,16 @@ test_write_dcb_basic(void) "eth0", NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP stuff */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - g_object_set(G_OBJECT(s_ip6), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* DCB */ - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - nm_connection_add_setting(connection, NM_SETTING(s_dcb)); + 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_AUTO, NULL); - g_object_set(G_OBJECT(s_dcb), + s_dcb = _nm_connection_new_setting(connection, NM_TYPE_SETTING_DCB); + g_object_set(s_dcb, NM_SETTING_DCB_APP_FCOE_FLAGS, DCB_ALL_FLAGS, NM_SETTING_DCB_APP_FCOE_PRIORITY, @@ -9814,8 +8483,7 @@ test_read_dcb_default_app_priorities(void) TYPE_ETHERNET, NULL); - s_dcb = nm_connection_get_setting_dcb(connection); - g_assert(s_dcb); + s_dcb = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_DCB); g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, NM_SETTING_DCB_FLAG_ENABLE); g_assert_cmpint(nm_setting_dcb_get_app_fcoe_priority(s_dcb), ==, -1); @@ -9950,8 +8618,7 @@ test_read_fcoe_mode(gconstpointer user_data) file = g_strdup_printf(TEST_IFCFG_DIR "/ifcfg-test-fcoe-%s", expected_mode); connection = _connection_from_file(file, NULL, TYPE_ETHERNET, NULL); - s_dcb = nm_connection_get_setting_dcb(connection); - g_assert(s_dcb); + s_dcb = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_DCB); g_assert_cmpint(nm_setting_dcb_get_app_fcoe_flags(s_dcb), ==, NM_SETTING_DCB_FLAG_ENABLE); g_assert_cmpstr(nm_setting_dcb_get_app_fcoe_mode(s_dcb), ==, expected_mode); @@ -9965,7 +8632,6 @@ test_write_fcoe_mode(gconstpointer user_data) gs_unref_object NMConnection *reread = NULL; const char * expected_mode = user_data; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingDcb * s_dcb; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; @@ -9973,9 +8639,8 @@ test_write_fcoe_mode(gconstpointer user_data) connection = nm_simple_connection_new(); - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - g_object_set(G_OBJECT(s_con), + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); + g_object_set(s_con, NM_SETTING_CONNECTION_ID, "fcoe-test", NM_SETTING_CONNECTION_UUID, @@ -9986,30 +8651,16 @@ test_write_fcoe_mode(gconstpointer user_data) "eth0", NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP stuff */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - g_object_set(G_OBJECT(s_ip6), - NM_SETTING_IP_CONFIG_METHOD, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NULL); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* DCB */ - s_dcb = (NMSettingDcb *) nm_setting_dcb_new(); - nm_connection_add_setting(connection, NM_SETTING(s_dcb)); + 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_AUTO, NULL); - g_object_set(G_OBJECT(s_dcb), + s_dcb = _nm_connection_new_setting(connection, NM_TYPE_SETTING_DCB); + g_object_set(s_dcb, NM_SETTING_DCB_APP_FCOE_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NM_SETTING_DCB_APP_FCOE_MODE, @@ -10032,28 +8683,24 @@ test_write_fcoe_mode(gconstpointer user_data) static void test_read_team_master(gconstpointer user_data) { - const char *const PATH_NAME = user_data; - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingTeam * s_team; - const char * expected_config = + const char *const PATH_NAME = user_data; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingTeam * s_team; + const char * expected_config = "{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"; connection = _connection_from_file(PATH_NAME, NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "team0"); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_TEAM_SETTING_NAME); - s_team = nm_connection_get_setting_team(connection); - g_assert(s_team); + s_team = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_TEAM); g_assert_cmpstr(nm_setting_team_get_config(s_team), ==, expected_config); - - g_object_unref(connection); } static void @@ -10080,7 +8727,6 @@ test_write_team_master(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingTeam * s_team; - NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; const char * expected_config = @@ -10089,10 +8735,7 @@ test_write_team_master(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Team Master", @@ -10104,29 +8747,18 @@ test_write_team_master(void) NM_SETTING_TEAM_SETTING_NAME, NULL); - /* Team setting */ - s_team = (NMSettingTeam *) nm_setting_team_new(); - nm_connection_add_setting(connection, NM_SETTING(s_team)); - + s_team = _nm_connection_new_setting(connection, NM_TYPE_SETTING_TEAM); g_object_set(s_team, NM_SETTING_TEAM_CONFIG, expected_config, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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_AUTO, NULL); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_verifies_without_normalization(connection); @@ -10145,26 +8777,22 @@ test_write_team_master(void) static void test_read_team_port(gconstpointer user_data) { - const char *const PATH_NAME = user_data; - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingTeamPort * s_team_port; - const char * expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"; + const char *const PATH_NAME = user_data; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingTeamPort * s_team_port; + const char * expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"; connection = _connection_from_file(PATH_NAME, NULL, TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRED_SETTING_NAME); g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "team0"); - s_team_port = nm_connection_get_setting_team_port(connection); - g_assert(s_team_port); + s_team_port = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_TEAM_PORT); g_assert_cmpstr(nm_setting_team_port_get_config(s_team_port), ==, expected_config); - - g_object_unref(connection); } static void @@ -10175,16 +8803,12 @@ test_write_team_port(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingTeamPort * s_team_port; - NMSettingWired * s_wired; const char * expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"; shvarFile * f; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Team Port", @@ -10198,14 +8822,10 @@ test_write_team_port(void) NM_SETTING_TEAM_SETTING_NAME, NULL); - /* Team setting */ - s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new(); - nm_connection_add_setting(connection, NM_SETTING(s_team_port)); + s_team_port = _nm_connection_new_setting(connection, NM_TYPE_SETTING_TEAM_PORT); g_object_set(s_team_port, NM_SETTING_TEAM_PORT_CONFIG, expected_config, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); nmtst_assert_connection_verifies(connection); @@ -10234,16 +8854,13 @@ test_write_team_infiniband_port(void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; NMSettingTeamPort * s_team_port; - NMSettingInfiniband * s_inf; + NMSettingInfiniband * s_infiniband; const char * expected_config = "{\"inf1\": {\"prio\": -10, \"sticky\": true}}"; shvarFile * f; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Team Infiniband Port", @@ -10259,15 +8876,11 @@ test_write_team_infiniband_port(void) "inf1", NULL); - /* Team setting */ - s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new(); - nm_connection_add_setting(connection, NM_SETTING(s_team_port)); + s_team_port = _nm_connection_new_setting(connection, NM_TYPE_SETTING_TEAM_PORT); g_object_set(s_team_port, NM_SETTING_TEAM_PORT_CONFIG, expected_config, NULL); - /* Infiniband setting */ - s_inf = (NMSettingInfiniband *) nm_setting_infiniband_new(); - nm_connection_add_setting(connection, NM_SETTING(s_inf)); - g_object_set(s_inf, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); + s_infiniband = _nm_connection_new_setting(connection, NM_TYPE_SETTING_INFINIBAND); + g_object_set(s_infiniband, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); nmtst_assert_connection_verifies(connection); @@ -10291,28 +8904,26 @@ test_write_team_infiniband_port(void) static void test_read_team_port_empty_config(void) { - NMConnection * connection; - NMSettingConnection *s_con; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingTeamPort * s_team_port; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-team-port-empty-config", NULL, TYPE_ETHERNET, NULL); - s_con = nm_connection_get_setting_connection(connection); - g_assert(s_con); + s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION); g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con), ==, NM_SETTING_WIRED_SETTING_NAME); g_assert_cmpstr(nm_setting_connection_get_master(s_con), ==, "team0"); /* Normalization adds a team-port setting */ - g_assert(nm_connection_get_setting_team_port(connection)); + s_team_port = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_TEAM_PORT); /* empty/missing config */ - g_assert(!nm_setting_team_port_get_config(nm_connection_get_setting_team_port(connection))); - - g_object_unref(connection); + g_assert(!nm_setting_team_port_get_config(s_team_port)); } static void @@ -10359,7 +8970,7 @@ test_team_reread_slave(void) NM_SETTING_CONNECTION_SLAVE_TYPE, "team", NULL); - g_object_set(nm_connection_get_setting_vlan(connection_2), + g_object_set(nmtst_connection_assert_setting(connection_2, NM_TYPE_SETTING_VLAN), NM_SETTING_VLAN_FLAGS, 1, NM_SETTING_VLAN_ID, @@ -10367,7 +8978,9 @@ test_team_reread_slave(void) NM_SETTING_VLAN_PARENT, "enp31s0f1", NULL); - nm_connection_add_setting(connection_2, nm_setting_team_port_new()); + + _nm_connection_new_setting(connection_2, NM_TYPE_SETTING_TEAM_PORT); + nmtst_connection_normalize(connection_2); nmtst_assert_connection_equals(connection_1, FALSE, connection_2, FALSE); @@ -10392,8 +9005,8 @@ test_team_reread_slave(void) static void test_read_proxy_basic(void) { - NMConnection * connection; - NMSettingProxy *s_proxy; + gs_unref_object NMConnection *connection = NULL; + NMSettingProxy * s_proxy; /* Test basic proxy configuration */ @@ -10402,18 +9015,13 @@ test_read_proxy_basic(void) TYPE_ETHERNET, NULL); - /* ===== Proxy setting ===== */ - s_proxy = nm_connection_get_setting_proxy(connection); - g_assert(s_proxy); + s_proxy = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_PROXY); - /* Proxy method */ g_assert_cmpint(nm_setting_proxy_get_method(s_proxy), ==, NM_SETTING_PROXY_METHOD_AUTO); g_assert(nm_setting_proxy_get_browser_only(s_proxy)); g_assert_cmpstr(nm_setting_proxy_get_pac_url(s_proxy), ==, "http://wpad.mycompany.com/wpad.dat"); - - g_object_unref(connection); } static void @@ -10423,17 +9031,13 @@ test_write_proxy_basic(void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingConnection * s_con; - NMSettingWired * s_wired; NMSettingProxy * s_proxy; const char * expected_url = "https://wpad.neverland.org/wpad.dat"; shvarFile * f; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write Proxy Basic", @@ -10443,15 +9047,11 @@ test_write_proxy_basic(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Proxy setting */ - s_proxy = (NMSettingProxy *) nm_setting_proxy_new(); - nm_connection_add_setting(connection, NM_SETTING(s_proxy)); + s_proxy = _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); g_object_set(s_proxy, NM_SETTING_PROXY_METHOD, NM_SETTING_PROXY_METHOD_AUTO, NULL); g_object_set(s_proxy, NM_SETTING_PROXY_PAC_URL, expected_url, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); nmtst_assert_connection_verifies(connection); @@ -10919,12 +9519,12 @@ test_write_unknown(gconstpointer test_data) static void test_read_vlan_trailing_spaces(void) { - const char * testfile = TEST_IFCFG_DIR "/ifcfg-test-vlan-trailing-spaces"; - NMConnection * connection; - gboolean success; - GError * error = NULL; - NMSettingVlan *s_vlan; - char * contents = NULL; + const char * testfile = TEST_IFCFG_DIR "/ifcfg-test-vlan-trailing-spaces"; + gs_unref_object NMConnection *connection = NULL; + gboolean success; + GError * error = NULL; + NMSettingVlan * s_vlan; + gs_free char * contents = NULL; /* Ensure there is whitespace at the end of the VLAN interface name, * to prevent the whitespace getting stripped off and committed mistakenly @@ -10935,19 +9535,15 @@ test_read_vlan_trailing_spaces(void) g_assert(success); g_assert(contents && contents[0]); g_assert(strstr(contents, "DEVICE=\"vlan201\" \n")); - g_free(contents); connection = _connection_from_file(testfile, NULL, TYPE_ETHERNET, NULL); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); + s_vlan = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_VLAN); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "vlan201"); g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "enccw0.0.fb00"); g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 201); g_assert_cmpint(nm_setting_vlan_get_flags(s_vlan), ==, NM_VLAN_FLAG_REORDER_HEADERS); - - g_object_unref(connection); } /*****************************************************************************/ @@ -10998,31 +9594,28 @@ test_utils_name(void) static void do_test_utils_path_ifcfg(const char *desc, const char *path, const char *expected) { - char *result; + gs_free char *result = NULL; result = utils_get_ifcfg_path(path); g_assert_cmpstr(result, ==, expected); - g_free(result); } static void do_test_utils_path_keys(const char *desc, const char *path, const char *expected) { - char *result; + gs_free char *result = NULL; result = utils_get_keys_path(path); g_assert_cmpstr(result, ==, expected); - g_free(result); } static void do_test_utils_path_route(const char *desc, const char *path, const char *expected) { - char *result; + gs_free char *result = NULL; result = utils_get_route_path(path); g_assert_cmpstr(result, ==, expected); - g_free(result); } static void @@ -11092,15 +9685,15 @@ test_sriov_read(void) NMSriovVF * vf; GVariant * variant; GError * error = NULL; - char * str; + gs_free char * str1 = NULL; + gs_free char * str2 = NULL; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-sriov", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "eth0"); - s_sriov = NM_SETTING_SRIOV(nm_connection_get_setting(connection, NM_TYPE_SETTING_SRIOV)); - g_assert(s_sriov); + s_sriov = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_SRIOV); g_assert_cmpint(nm_setting_sriov_get_total_vfs(s_sriov), ==, 16); g_assert_cmpint(nm_setting_sriov_get_num_vfs(s_sriov), ==, 3); @@ -11122,18 +9715,16 @@ test_sriov_read(void) g_assert_cmpint(g_variant_get_boolean(variant), ==, TRUE); /* VF 12 */ - vf = nm_setting_sriov_get_vf(s_sriov, 1); - str = nm_utils_sriov_vf_to_str(vf, FALSE, &error); + vf = nm_setting_sriov_get_vf(s_sriov, 1); + str1 = nm_utils_sriov_vf_to_str(vf, FALSE, &error); g_assert_no_error(error); - g_assert_cmpstr(str, ==, "12 min-tx-rate=100 trust=false vlans=1.200.ad"); - g_free(str); + g_assert_cmpstr(str1, ==, "12 min-tx-rate=100 trust=false vlans=1.200.ad"); /* VF 15 */ - vf = nm_setting_sriov_get_vf(s_sriov, 2); - str = nm_utils_sriov_vf_to_str(vf, FALSE, &error); + vf = nm_setting_sriov_get_vf(s_sriov, 2); + str2 = nm_utils_sriov_vf_to_str(vf, FALSE, &error); g_assert_no_error(error); - g_assert_cmpstr(str, ==, "15 mac=01:23:45:67:89:ab max-tx-rate=200 vlans=2"); - g_free(str); + g_assert_cmpstr(str2, ==, "15 mac=01:23:45:67:89:ab max-tx-rate=200 vlans=2"); } static void @@ -11145,7 +9736,6 @@ test_sriov_write(void) NMSettingConnection * s_con; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; NMSettingSriov * s_sriov; NMSriovVF * vf; gs_unref_ptrarray GPtrArray *vfs = NULL; @@ -11154,10 +9744,7 @@ test_sriov_write(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write SR-IOV config", @@ -11171,14 +9758,9 @@ test_sriov_write(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -11193,15 +9775,10 @@ test_sriov_write(void) nm_setting_ip_config_add_address(s_ip4, addr); nm_ip_address_unref(addr); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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); - /* SRIOV setting */ - s_sriov = (NMSettingSriov *) nm_setting_sriov_new(); - nm_connection_add_setting(connection, NM_SETTING(s_sriov)); + s_sriov = _nm_connection_new_setting(connection, NM_TYPE_SETTING_SRIOV); vfs = g_ptr_array_new_with_free_func((GDestroyNotify) nm_sriov_vf_unref); @@ -11222,7 +9799,7 @@ test_sriov_write(void) NM_TERNARY_TRUE, NULL); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_verifies_without_normalization(connection); @@ -11241,18 +9818,17 @@ test_sriov_write(void) static void test_tc_read(void) { - NMConnection * connection; - NMSettingTCConfig *s_tc; - NMTCQdisc * qdisc; - NMTCTfilter * filter; - char * str; + gs_unref_object NMConnection *connection = NULL; + NMSettingTCConfig * s_tc; + NMTCQdisc * qdisc; + NMTCTfilter * filter; + gs_free char * str = NULL; connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-tc", NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "eth0"); - s_tc = nm_connection_get_setting_tc_config(connection); - g_assert(s_tc); + s_tc = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_TC_CONFIG); g_assert_cmpint(nm_setting_tc_config_get_num_qdiscs(s_tc), ==, 1); qdisc = nm_setting_tc_config_get_qdisc(s_tc, 0); @@ -11266,9 +9842,6 @@ test_tc_read(void) g_assert(filter); str = nm_utils_tc_tfilter_to_str(filter, NULL); g_assert_cmpstr(str, ==, "parent 1234: matchall action simple sdata Hello"); - g_free(str); - - g_object_unref(connection); } static void @@ -11280,17 +9853,12 @@ test_tc_write_empty(void) NMSettingConnection * s_con; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; - NMSettingTCConfig * s_tc; NMIPAddress * addr; GError * error = NULL; connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write TC config", @@ -11304,14 +9872,9 @@ test_tc_write_empty(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -11326,17 +9889,12 @@ test_tc_write_empty(void) nm_setting_ip_config_add_address(s_ip4, addr); nm_ip_address_unref(addr); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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); - /* TC setting */ - s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_tc)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_TC_CONFIG); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_verifies_without_normalization(connection); @@ -11359,7 +9917,6 @@ test_tc_write(void) NMSettingConnection * s_con; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - NMSettingWired * s_wired; NMSettingTCConfig * s_tc; NMTCQdisc * qdisc; NMTCTfilter * tfilter; @@ -11368,10 +9925,7 @@ test_tc_write(void) connection = nm_simple_connection_new(); - /* Connection setting */ - s_con = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(s_con)); - + s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, "Test Write TC config", @@ -11385,14 +9939,9 @@ test_tc_write(void) NM_SETTING_WIRED_SETTING_NAME, NULL); - /* Wired setting */ - s_wired = (NMSettingWired *) nm_setting_wired_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); - - /* IP4 setting */ - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip4)); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRED); + s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, @@ -11407,15 +9956,10 @@ test_tc_write(void) nm_setting_ip_config_add_address(s_ip4, addr); nm_ip_address_unref(addr); - /* IP6 setting */ - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_ip6)); - + 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); - /* TC setting */ - s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new(); - nm_connection_add_setting(connection, NM_SETTING(s_tc)); + s_tc = _nm_connection_new_setting(connection, NM_TYPE_SETTING_TC_CONFIG); qdisc = nm_tc_qdisc_new("pfifo_fast", TC_H_MAKE(0x2468 << 16, 0x2), &error); g_assert_no_error(error); @@ -11428,7 +9972,7 @@ test_tc_write(void) nm_setting_tc_config_add_tfilter(s_tc, tfilter); nm_tc_tfilter_unref(tfilter); - nm_connection_add_setting(connection, nm_setting_proxy_new()); + _nm_connection_new_setting(connection, NM_TYPE_SETTING_PROXY); nmtst_assert_connection_verifies_without_normalization(connection); @@ -12040,6 +10584,8 @@ main(int argc, char **argv) g_test_add_func(TPATH "bond/write-slave", test_write_bond_slave); g_test_add_func(TPATH "bond/write-slave-ib", test_write_bond_slave_ib); g_test_add_func(TPATH "bond/bonding-opts-numeric-mode", test_read_bond_opts_mode_numeric); + g_test_add_func(TPATH "bond/read-bond-port", test_read_bond_port); + g_test_add_func(TPATH "bond/write-bond-port", test_write_bond_port); g_test_add_func(TPATH "bridge/read-master", test_read_bridge_main); g_test_add_func(TPATH "bridge/write-master", test_write_bridge_main); diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c index a8a9c40a..84986877 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c @@ -112,7 +112,7 @@ _recursive_ifparser(if_parser *parser, const char *eni_file, int quiet) /* Check if interfaces file exists and open it */ if (!g_file_test(eni_file, G_FILE_TEST_EXISTS)) { if (!quiet) - _LOGW("interfaces file %s doesn't exist", eni_file); + _LOGI("interfaces file %s doesn't exist", eni_file); return; } inp = fopen(eni_file, "re"); diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c index db6b1aef..5bad2362 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -397,7 +397,7 @@ ifupdown_ip4_add_dns(NMSettingIPConfig *s_ip4, const char *dns) if (dns == NULL) return; - list = nm_utils_strsplit_set(dns, " \t"); + list = nm_strsplit_set(dns, " \t"); for (iter = list; iter && *iter; iter++) { if (!inet_pton(AF_INET, *iter, &addr)) { _LOGW(" ignoring invalid nameserver '%s'", *iter); @@ -497,7 +497,7 @@ update_ip4_setting_from_if_block(NMConnection *connection, if_block *block, GErr gs_free const char **list = NULL; const char ** iter; - list = nm_utils_strsplit_set(search_v, " \t"); + list = nm_strsplit_set(search_v, " \t"); for (iter = list; iter && *iter; iter++) { if (!nm_setting_ip_config_add_dns_search(s_ip4, *iter)) _LOGW(" duplicate DNS domain '%s'", *iter); @@ -521,7 +521,7 @@ ifupdown_ip6_add_dns(NMSettingIPConfig *s_ip6, const char *dns) if (dns == NULL) return; - list = nm_utils_strsplit_set(dns, " \t"); + list = nm_strsplit_set(dns, " \t"); for (iter = list; iter && *iter; iter++) { if (!inet_pton(AF_INET6, *iter, &addr)) { _LOGW(" ignoring invalid nameserver '%s'", *iter); @@ -605,7 +605,7 @@ update_ip6_setting_from_if_block(NMConnection *connection, if_block *block, GErr gs_free const char **list = NULL; const char ** iter; - list = nm_utils_strsplit_set(search_v, " \t"); + list = nm_strsplit_set(search_v, " \t"); for (iter = list; iter && *iter; iter++) { if (!nm_setting_ip_config_add_dns_search(s_ip6, *iter)) _LOGW(" duplicate DNS domain '%s'", *iter); diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 80a5638a..602a7327 100644 --- a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -189,7 +189,7 @@ _unmanaged_specs(GHashTable *eni_ifaces) GSList * specs = NULL; guint i, len; - keys = nm_utils_strdict_get_keys(eni_ifaces, TRUE, &len); + keys = nm_strdict_get_keys(eni_ifaces, TRUE, &len); for (i = len; i > 0;) { i--; specs = g_slist_prepend(specs, @@ -264,7 +264,7 @@ load_eni_ifaces(NMSIfupdownPlugin *self) _LOGD("parse: found bridge ports %s for %s", ports, block->name); - port_ifaces = nm_utils_strsplit_set(ports, " \t"); + port_ifaces = nm_strsplit_set(ports, " \t"); for (i = 0; port_ifaces && port_ifaces[i]; i++) { const char *token = port_ifaces[i]; @@ -323,7 +323,7 @@ load_eni_ifaces(NMSIfupdownPlugin *self) NM_PRINT_FMT_QUOTED(local, " (", local->message, ")", "")); sd = NULL; } else { - nmtst_connection_assert_unchanging(connection); + nm_assert_connection_unchanging(connection); uuid = nm_connection_get_uuid(connection); if (!storage) diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c index e8ae1814..aa36ee8f 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -101,27 +101,27 @@ _extra_flags_to_string(char * str, const char *str0 = str; if (!is_nm_generated && !is_volatile && !is_external) - nm_utils_strbuf_append_str(&str, &str_len, ""); + nm_strbuf_append_str(&str, &str_len, ""); else { char ch = '('; - nm_utils_strbuf_append_c(&str, &str_len, ' '); + nm_strbuf_append_c(&str, &str_len, ' '); if (is_nm_generated) { - nm_utils_strbuf_append_c(&str, &str_len, ch); - nm_utils_strbuf_append_str(&str, &str_len, "nm-generated"); + nm_strbuf_append_c(&str, &str_len, ch); + nm_strbuf_append_str(&str, &str_len, "nm-generated"); ch = ','; } if (is_volatile) { - nm_utils_strbuf_append_c(&str, &str_len, ch); - nm_utils_strbuf_append_str(&str, &str_len, "volatile"); + nm_strbuf_append_c(&str, &str_len, ch); + nm_strbuf_append_str(&str, &str_len, "volatile"); ch = ','; } if (is_external) { - nm_utils_strbuf_append_c(&str, &str_len, ch); - nm_utils_strbuf_append_str(&str, &str_len, "external"); + nm_strbuf_append_c(&str, &str_len, ch); + nm_strbuf_append_str(&str, &str_len, "external"); ch = ','; } - nm_utils_strbuf_append_c(&str, &str_len, ')'); + nm_strbuf_append_c(&str, &str_len, ')'); } return str0; diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-storage.c b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c index 8c526c81..ec0634c4 100644 --- a/src/core/settings/plugins/keyfile/nms-keyfile-storage.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c @@ -168,7 +168,7 @@ nms_keyfile_storage_new_connection(NMSKeyfilePlugin * plugin, nm_assert(filename && filename[0] == '/'); nm_assert(storage_type >= NMS_KEYFILE_STORAGE_TYPE_RUN && storage_type <= _NMS_KEYFILE_STORAGE_TYPE_LIB_LAST); - nmtst_connection_assert_unchanging(connection_take); + nm_assert_connection_unchanging(connection_take); self = _storage_new(plugin, nm_connection_get_uuid(connection_take), 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 a13c2586..4ceed49d 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -992,7 +992,7 @@ test_read_intlike_ssid(void) ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); - g_assert(nm_utils_gbytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); + g_assert(nm_g_bytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); } static void @@ -1010,7 +1010,7 @@ test_read_intlike_ssid_2(void) ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); - g_assert(nm_utils_gbytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); + g_assert(nm_g_bytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); } static void @@ -1774,7 +1774,7 @@ test_write_wired_8021x_tls_connection_blob(void) password_raw = nm_setting_802_1x_get_password_raw(s_8021x); g_assert(password_raw); - g_assert(nm_utils_gbytes_equal_mem(password_raw, PASSWORD_RAW, NM_STRLEN(PASSWORD_RAW))); + g_assert(nm_g_bytes_equal_mem(password_raw, PASSWORD_RAW, NM_STRLEN(PASSWORD_RAW))); unlink(testfile); @@ -2160,7 +2160,7 @@ test_read_new_wireless_group_names(void) ssid = nm_setting_wireless_get_ssid(s_wifi); g_assert(ssid); - g_assert(nm_utils_gbytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); + g_assert(nm_g_bytes_equal_mem(ssid, expected_ssid, strlen(expected_ssid))); g_assert_cmpstr(nm_setting_wireless_get_mode(s_wifi), ==, NM_SETTING_WIRELESS_MODE_INFRA); diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c index 1959a161..c486ba1d 100644 --- a/src/core/supplicant/nm-supplicant-config.c +++ b/src/core/supplicant/nm-supplicant-config.c @@ -417,7 +417,7 @@ nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self, port = nm_setting_macsec_get_port(setting); if (port > 0 && port < 65534) { - snprintf(buf, sizeof(buf), "%d", port); + g_snprintf(buf, sizeof(buf), "%d", port); if (!nm_supplicant_config_add_option(self, "macsec_port", buf, -1, NULL, error)) return FALSE; } diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index 1556e290..2d56b836 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -115,6 +115,9 @@ typedef struct _NMSupplicantInterfacePrivate { CList peer_lst_head; CList peer_initializing_lst_head; + in_addr_t p2p_assigned_addr; + guint8 p2p_assigned_plen; + gint64 last_scan_msec; NMSupplicantAuthState auth_state; @@ -693,7 +696,7 @@ _bss_info_properties_changed(NMSupplicantInterface *self, } else arr_len = 0; - if (!nm_utils_gbytes_equal_mem(bss_info->ssid, arr_data, arr_len)) { + if (!nm_g_bytes_equal_mem(bss_info->ssid, arr_data, arr_len)) { _nm_unused gs_unref_bytes GBytes *old_free = g_steal_pointer(&bss_info->ssid); bss_info->ssid = (arr_len == 0) ? NULL : g_bytes_new(arr_data, arr_len); @@ -915,23 +918,23 @@ _peer_info_properties_changed(NMSupplicantInterface *self, peer_info->signal_percent = nm_wifi_utils_level_to_quality(v_i32); if (nm_g_variant_lookup(properties, "DeviceName", "&s", &v_s)) - nm_utils_strdup_reset(&peer_info->device_name, v_s); + nm_strdup_reset(&peer_info->device_name, v_s); if (nm_g_variant_lookup(properties, "Manufacturer", "&s", &v_s)) - nm_utils_strdup_reset(&peer_info->manufacturer, v_s); + nm_strdup_reset(&peer_info->manufacturer, v_s); if (nm_g_variant_lookup(properties, "Model", "&s", &v_s)) - nm_utils_strdup_reset(&peer_info->model, v_s); + nm_strdup_reset(&peer_info->model, v_s); if (nm_g_variant_lookup(properties, "ModelNumber", "&s", &v_s)) - nm_utils_strdup_reset(&peer_info->model_number, v_s); + nm_strdup_reset(&peer_info->model_number, v_s); if (nm_g_variant_lookup(properties, "Serial", "&s", &v_s)) - nm_utils_strdup_reset(&peer_info->serial, v_s); + nm_strdup_reset(&peer_info->serial, v_s); if (nm_g_variant_lookup(properties, "Groups", "^a&o", &v_strv)) { g_free(peer_info->groups); - peer_info->groups = nm_utils_strv_dup_packed(v_strv, -1); + peer_info->groups = nm_strv_dup_packed(v_strv, -1); g_free(v_strv); } @@ -967,7 +970,7 @@ _peer_info_properties_changed(NMSupplicantInterface *self, v_v = nm_g_variant_lookup_value(properties, "IEs", G_VARIANT_TYPE_BYTESTRING); if (v_v) { arr_data = g_variant_get_fixed_array(v_v, &arr_len, 1); - if (!nm_utils_gbytes_equal_mem(peer_info->ies, arr_data, arr_len)) { + if (!nm_g_bytes_equal_mem(peer_info->ies, arr_data, arr_len)) { _nm_unused gs_unref_bytes GBytes *old_free = g_steal_pointer(&peer_info->ies); peer_info->ies = g_bytes_new(arr_data, arr_len); @@ -1904,11 +1907,11 @@ _properties_changed_main(NMSupplicantInterface *self, GVariant *properties) } if (nm_g_variant_lookup(properties, "Ifname", "&s", &v_s)) { - if (nm_utils_strdup_reset(&priv->ifname, v_s)) + if (nm_strdup_reset(&priv->ifname, v_s)) do_log_driver_info = TRUE; } if (nm_g_variant_lookup(properties, "Driver", "&s", &v_s)) { - if (nm_utils_strdup_reset(&priv->driver, v_s)) + if (nm_strdup_reset(&priv->driver, v_s)) do_log_driver_info = TRUE; } @@ -2305,7 +2308,7 @@ assoc_add_network_cb(GObject *source, GAsyncResult *result, gpointer user_data) self, NM_WPAS_DBUS_IFACE_INTERFACE, "AddBlob", - g_variant_new("(s@ay)", blob_name, nm_utils_gbytes_to_variant_ay(blob_data)), + g_variant_new("(s@ay)", blob_name, nm_g_bytes_to_variant_ay(blob_data)), G_VARIANT_TYPE("()"), G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT_MSEC, @@ -2609,7 +2612,7 @@ nm_supplicant_interface_request_scan(NMSupplicantInterface * se g_variant_builder_init(&ssids_builder, G_VARIANT_TYPE_BYTESTRING_ARRAY); for (i = 0; i < ssids_len; i++) { nm_assert(ssids[i]); - g_variant_builder_add(&ssids_builder, "@ay", nm_utils_gbytes_to_variant_ay(ssids[i])); + g_variant_builder_add(&ssids_builder, "@ay", nm_g_bytes_to_variant_ay(ssids[i])); } g_variant_builder_add(&builder, "{sv}", "SSIDs", g_variant_builder_end(&ssids_builder)); } @@ -2942,6 +2945,15 @@ _get_all_p2p_device_cb(GVariant *result, GError *error, gpointer user_data) _properties_changed(user_data, NM_WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE, properties, TRUE); } +static void +_set_p2p_assigned_addr(NMSupplicantInterface *self, gconstpointer addr, guint8 plen) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self); + + nm_ip_addr_set(AF_INET, &priv->p2p_assigned_addr, addr); + priv->p2p_assigned_plen = plen; +} + static void _signal_handle(NMSupplicantInterface *self, const char * signal_interface_name, @@ -3036,6 +3048,7 @@ _signal_handle(NMSupplicantInterface *self, gs_unref_object NMSupplicantInterface *iface = NULL; const char * group_path; const char * iface_path; + GVariant * v_v = NULL; g_variant_get(parameters, "(@a{sv})", &args); if (!g_variant_lookup(args, "group_object", "&o", &group_path)) @@ -3057,6 +3070,34 @@ _signal_handle(NMSupplicantInterface *self, } } + v_v = g_variant_lookup_value(args, "IpAddr", G_VARIANT_TYPE_BYTESTRING); + if (v_v) { + const guint8 *addr_data; + gsize addr_len = 0; + const guint8 *mask_data = NULL; + gsize mask_len = 0; + + /* The address is passed in network-byte-order */ + addr_data = g_variant_get_fixed_array(v_v, &addr_len, 1); + + /* TODO: Should we expose IpAddrGo? If yes, maybe as gateway? */ + v_v = g_variant_lookup_value(args, "IpAddrMask", G_VARIANT_TYPE_BYTESTRING); + if (v_v) + mask_data = g_variant_get_fixed_array(v_v, &mask_len, 1); + + if (addr_len == NM_AF_INET_SIZE && mask_len == NM_AF_INET_SIZE) { + guint32 netmask; + + memcpy(&netmask, mask_data, NM_AF_INET_SIZE); + + _set_p2p_assigned_addr(iface, + addr_data, + nm_utils_ip4_netmask_to_prefix(netmask)); + } else { + _LOGW("P2P: GroupStarted signaled invalid IP Address information"); + } + } + /* Signal existence of the (new) interface. */ g_signal_emit(self, signals[GROUP_STARTED], 0, iface); } @@ -3137,6 +3178,24 @@ nm_supplicant_interface_get_p2p_group_owner(NMSupplicantInterface *self) return NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self)->p2p_group_owner_cached; } +gboolean +nm_supplicant_interface_get_p2p_assigned_addr(NMSupplicantInterface *self, + in_addr_t * addr, + guint8 * plen) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self); + + if (nm_ip_addr_is_null(AF_INET, &priv->p2p_assigned_addr)) + return FALSE; + + if (addr) + nm_ip_addr_set(AF_INET, addr, &priv->p2p_assigned_addr); + if (plen) + *plen = priv->p2p_assigned_plen; + + return TRUE; +} + /*****************************************************************************/ static void diff --git a/src/core/supplicant/nm-supplicant-interface.h b/src/core/supplicant/nm-supplicant-interface.h index a62eeb62..4c5d8f64 100644 --- a/src/core/supplicant/nm-supplicant-interface.h +++ b/src/core/supplicant/nm-supplicant-interface.h @@ -164,6 +164,10 @@ const char *nm_supplicant_interface_get_p2p_group_path(NMSupplicantInterface *se gboolean nm_supplicant_interface_get_p2p_group_owner(NMSupplicantInterface *self); +gboolean nm_supplicant_interface_get_p2p_assigned_addr(NMSupplicantInterface *self, + in_addr_t * assigned_addr, + guint8 * plen); + void nm_supplicant_interface_p2p_start_find(NMSupplicantInterface *self, guint timeout); void nm_supplicant_interface_p2p_stop_find(NMSupplicantInterface *self); diff --git a/src/core/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c index e432889b..52beae78 100644 --- a/src/core/supplicant/nm-supplicant-manager.c +++ b/src/core/supplicant/nm-supplicant-manager.c @@ -244,8 +244,7 @@ nm_supplicant_manager_set_wfd_ies(NMSupplicantManager *self, GBytes *wfd_ies) g_variant_builder_add(¶ms, "s", NM_WPAS_DBUS_INTERFACE); g_variant_builder_add(¶ms, "s", "WFDIEs"); - g_variant_builder_add_value(¶ms, - g_variant_new_variant(nm_utils_gbytes_to_variant_ay(wfd_ies))); + g_variant_builder_add_value(¶ms, g_variant_new_variant(nm_g_bytes_to_variant_ay(wfd_ies))); g_dbus_connection_call(priv->dbus_connection, priv->name_owner->str, diff --git a/src/core/supplicant/nm-supplicant-settings-verify.c b/src/core/supplicant/nm-supplicant-settings-verify.c index 5e77b207..ceb4b6ae 100644 --- a/src/core/supplicant/nm-supplicant-settings-verify.c +++ b/src/core/supplicant/nm-supplicant-settings-verify.c @@ -223,7 +223,7 @@ validate_type_keyword(const struct Opt *opt, const char *value, const guint32 le s++; } - if (nm_utils_strv_find_first((char **) opt->str_allowed, -1, value) < 0) + if (nm_strv_find_first(opt->str_allowed, -1, value) < 0) return FALSE; if (!s) diff --git a/src/core/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h index c9b72de1..743ef8f0 100644 --- a/src/core/supplicant/nm-supplicant-types.h +++ b/src/core/supplicant/nm-supplicant-types.h @@ -14,9 +14,9 @@ #define NM_WPAS_DBUS_INTERFACE "fi.w1.wpa_supplicant1" #if HAVE_WEXT - #define NM_WPAS_DEFAULT_WIFI_DRIVER "nl80211,wext" +#define NM_WPAS_DEFAULT_WIFI_DRIVER "nl80211,wext" #else - #define NM_WPAS_DEFAULT_WIFI_DRIVER "nl80211" +#define NM_WPAS_DEFAULT_WIFI_DRIVER "nl80211" #endif #define NM_WPAS_DBUS_IFACE_INTERFACE NM_WPAS_DBUS_INTERFACE ".Interface" diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c index f28c4178..3524cb17 100644 --- a/src/core/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -1728,86 +1728,86 @@ test_nm_utils_strbuf_append(void) char buf[NM_STRLEN(BUF_ORIG) + 1]; char str[NM_STRLEN(BUF_ORIG) + 1]; -#define _strbuf_append(buf, len, format, ...) \ - G_STMT_START \ - { \ - char ** _buf = (buf); \ - gsize * _len = (len); \ - const char * _str_iter; \ - gs_free char *_str = NULL; \ - \ - switch (nmtst_get_rand_uint32() % 4) { \ - case 0: \ - nm_utils_strbuf_append(_buf, _len, (format), __VA_ARGS__); \ - break; \ - case 1: \ - _str = g_strdup_printf((format), __VA_ARGS__); \ - nm_utils_strbuf_append_str(_buf, _len, _str); \ - break; \ - case 2: \ - _str = g_strdup_printf((format), __VA_ARGS__); \ - nm_utils_strbuf_append_bin(_buf, _len, _str, strlen(_str)); \ - break; \ - case 3: \ - _str = g_strdup_printf((format), __VA_ARGS__); \ - if (!_str[0]) \ - nm_utils_strbuf_append_str(_buf, _len, _str); \ - for (_str_iter = _str; _str_iter[0]; _str_iter++) \ - nm_utils_strbuf_append_c(_buf, _len, _str_iter[0]); \ - break; \ - } \ - } \ +#define _strbuf_append(buf, len, format, ...) \ + G_STMT_START \ + { \ + char ** _buf = (buf); \ + gsize * _len = (len); \ + const char * _str_iter; \ + gs_free char *_str = NULL; \ + \ + switch (nmtst_get_rand_uint32() % 4) { \ + case 0: \ + nm_strbuf_append(_buf, _len, (format), __VA_ARGS__); \ + break; \ + case 1: \ + _str = g_strdup_printf((format), __VA_ARGS__); \ + nm_strbuf_append_str(_buf, _len, _str); \ + break; \ + case 2: \ + _str = g_strdup_printf((format), __VA_ARGS__); \ + nm_strbuf_append_bin(_buf, _len, _str, strlen(_str)); \ + break; \ + case 3: \ + _str = g_strdup_printf((format), __VA_ARGS__); \ + if (!_str[0]) \ + nm_strbuf_append_str(_buf, _len, _str); \ + for (_str_iter = _str; _str_iter[0]; _str_iter++) \ + nm_strbuf_append_c(_buf, _len, _str_iter[0]); \ + break; \ + } \ + } \ G_STMT_END -#define _strbuf_append_str(buf, len, str) \ - G_STMT_START \ - { \ - char ** _buf = (buf); \ - gsize * _len = (len); \ - const char *_str = (str); \ - \ - switch (nmtst_get_rand_uint32() % 4) { \ - case 0: \ - nm_utils_strbuf_append(_buf, _len, "%s", _str ?: ""); \ - break; \ - case 1: \ - nm_utils_strbuf_append_str(_buf, _len, _str); \ - break; \ - case 2: \ - nm_utils_strbuf_append_bin(_buf, _len, _str, _str ? strlen(_str) : 0); \ - break; \ - case 3: \ - if (!_str || !_str[0]) \ - nm_utils_strbuf_append_str(_buf, _len, _str); \ - for (; _str && _str[0]; _str++) \ - nm_utils_strbuf_append_c(_buf, _len, _str[0]); \ - break; \ - } \ - } \ +#define _strbuf_append_str(buf, len, str) \ + G_STMT_START \ + { \ + char ** _buf = (buf); \ + gsize * _len = (len); \ + const char *_str = (str); \ + \ + switch (nmtst_get_rand_uint32() % 4) { \ + case 0: \ + nm_strbuf_append(_buf, _len, "%s", _str ?: ""); \ + break; \ + case 1: \ + nm_strbuf_append_str(_buf, _len, _str); \ + break; \ + case 2: \ + nm_strbuf_append_bin(_buf, _len, _str, _str ? strlen(_str) : 0); \ + break; \ + case 3: \ + if (!_str || !_str[0]) \ + nm_strbuf_append_str(_buf, _len, _str); \ + for (; _str && _str[0]; _str++) \ + nm_strbuf_append_c(_buf, _len, _str[0]); \ + break; \ + } \ + } \ G_STMT_END -#define _strbuf_append_c(buf, len, ch) \ - G_STMT_START \ - { \ - char **_buf = (buf); \ - gsize *_len = (len); \ - char _ch = (ch); \ - \ - switch (nmtst_get_rand_uint32() % 4) { \ - case 0: \ - nm_utils_strbuf_append(_buf, _len, "%c", _ch); \ - break; \ - case 1: \ - nm_utils_strbuf_append_str(_buf, _len, ((char[2]){_ch, 0})); \ - break; \ - case 2: \ - nm_utils_strbuf_append_bin(_buf, _len, &_ch, 1); \ - break; \ - case 3: \ - nm_utils_strbuf_append_c(_buf, _len, _ch); \ - break; \ - } \ - } \ +#define _strbuf_append_c(buf, len, ch) \ + G_STMT_START \ + { \ + char **_buf = (buf); \ + gsize *_len = (len); \ + char _ch = (ch); \ + \ + switch (nmtst_get_rand_uint32() % 4) { \ + case 0: \ + nm_strbuf_append(_buf, _len, "%c", _ch); \ + break; \ + case 1: \ + nm_strbuf_append_str(_buf, _len, ((char[2]){_ch, 0})); \ + break; \ + case 2: \ + nm_strbuf_append_bin(_buf, _len, &_ch, 1); \ + break; \ + case 3: \ + nm_strbuf_append_c(_buf, _len, _ch); \ + break; \ + } \ + } \ G_STMT_END for (buf_len = 0; buf_len < 10; buf_len++) { @@ -1854,28 +1854,28 @@ test_nm_utils_strbuf_append(void) if (t_len > 0 && strlen(str) >= buf_len && (nmtst_get_rand_uint32() % 2)) { /* the string was truncated by g_snprintf(). That means, at the last position in the * buffer is now NUL. - * Replace the NUL by the actual character, and check that nm_utils_strbuf_seek_end() + * Replace the NUL by the actual character, and check that nm_strbuf_seek_end() * does the right thing: NUL terminate the buffer and seek past the end of the buffer. */ g_assert_cmpmem(t_buf, t_len - 1, str, t_len - 1); g_assert(t_buf[t_len - 1] == '\0'); g_assert(str[t_len - 1] != '\0'); t_buf[t_len - 1] = str[t_len - 1]; - nm_utils_strbuf_seek_end(&t_buf, &t_len); + nm_strbuf_seek_end(&t_buf, &t_len); g_assert(t_len == 0); g_assert(t_buf == &buf[buf_len]); g_assert(t_buf[-1] == '\0'); } else { - nm_utils_strbuf_seek_end(&t_buf, &t_len); + nm_strbuf_seek_end(&t_buf, &t_len); if (buf_len > 0 && strlen(str) + 1 > buf_len) { /* the buffer was truncated by g_snprintf() above. * - * But nm_utils_strbuf_seek_end() does not recognize that and returns + * But nm_strbuf_seek_end() does not recognize that and returns * a remaining length of 1. * - * Note that other nm_utils_strbuf_append*() functions recognize + * Note that other nm_strbuf_append*() functions recognize * truncation, and properly set the remaining length to zero. - * As the assertions below check for the behavior of nm_utils_strbuf_append*(), - * we assert here that nm_utils_strbuf_seek_end() behaved as expected, and then + * As the assertions below check for the behavior of nm_strbuf_append*(), + * we assert here that nm_strbuf_seek_end() behaved as expected, and then * adjust t_buf/t_len according to the "is-truncated" case. */ g_assert(t_len == 1); g_assert(t_buf == &buf[buf_len - 1]); @@ -2594,7 +2594,7 @@ main(int argc, char **argv) g_test_add_func("/general/test_logging_domains", test_logging_domains); g_test_add_func("/general/test_logging_error", test_logging_error); - g_test_add_func("/general/nm_utils_strbuf_append", test_nm_utils_strbuf_append); + g_test_add_func("/general/nm_strbuf_append", test_nm_utils_strbuf_append); g_test_add_func("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address); diff --git a/src/core/tests/test-ip6-config.c b/src/core/tests/test-ip6-config.c index ddf4c789..2e6d8aaa 100644 --- a/src/core/tests/test-ip6-config.c +++ b/src/core/tests/test-ip6-config.c @@ -327,7 +327,7 @@ test_nm_ip6_config_addresses_sort(void) 0, 0, 0, - IFA_F_TEMPORARY); + IFA_F_SECONDARY); ADDR_ADD("2607:f0d0:1002:51::8", NULL, 64, @@ -336,7 +336,7 @@ test_nm_ip6_config_addresses_sort(void) 0, 0, 0, - IFA_F_TEMPORARY); + IFA_F_SECONDARY); ADDR_ADD("2607:f0d0:1002:51::0", NULL, 64, @@ -345,7 +345,7 @@ test_nm_ip6_config_addresses_sort(void) 0, 0, 0, - IFA_F_TEMPORARY); + IFA_F_SECONDARY); ADDR_ADD("fec0::1", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0); ADDR_ADD("fe80::208:74ff:feda:625c", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0); ADDR_ADD("fe80::208:74ff:feda:625d", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0); @@ -374,7 +374,7 @@ test_nm_ip6_config_addresses_sort(void) 0, 0, 0, - IFA_F_TEMPORARY); + IFA_F_SECONDARY); ADDR_ADD("2607:f0d0:1002:51::4", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0); ADDR_ADD("2607:f0d0:1002:51::5", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0); ADDR_ADD("2607:f0d0:1002:51::8", @@ -385,7 +385,7 @@ test_nm_ip6_config_addresses_sort(void) 0, 0, 0, - IFA_F_TEMPORARY); + IFA_F_SECONDARY); ADDR_ADD("2607:f0d0:1002:51::0", NULL, 64, @@ -394,7 +394,7 @@ test_nm_ip6_config_addresses_sort(void) 0, 0, 0, - IFA_F_TEMPORARY); + IFA_F_SECONDARY); ADDR_ADD("2607:f0d0:1002:51::6", NULL, 64, diff --git a/src/core/tests/test-l3cfg.c b/src/core/tests/test-l3cfg.c index ba065c09..100c2496 100644 --- a/src/core/tests/test-l3cfg.c +++ b/src/core/tests/test-l3cfg.c @@ -2,8 +2,11 @@ #include "src/core/nm-default-daemon.h" +#include + #include "nm-l3cfg.h" #include "nm-l3-ipv4ll.h" +#include "nm-l3-ipv6ll.h" #include "nm-netns.h" #include "libnm-platform/nm-platform.h" @@ -132,6 +135,7 @@ typedef struct { NML3AcdDefendType acd_defend_type_a; TestL3cfgNotifyType notify_type; + guint pre_commit_event_count; guint post_commit_event_count; guint general_event_count; guint general_event_flags; @@ -151,6 +155,7 @@ _test_l3cfg_data_set_notify_type(TestL3cfgData *tdata, TestL3cfgNotifyType notif g_assert(tdata); tdata->notify_type = notify_type; + tdata->pre_commit_event_count = 0; tdata->post_commit_event_count = 0; tdata->general_event_count = 0; tdata->general_event_flags = 0; @@ -209,6 +214,10 @@ _test_l3cfg_signal_notify(NML3Cfg * l3cfg, case TEST_L3CFG_NOTIFY_TYPE_COMMIT_1: g_assert_cmpint(tdata->post_commit_event_count, ==, 0); switch (notify_data->notify_type) { + case NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT: + g_assert_cmpint(tdata->pre_commit_event_count, ==, 0); + tdata->pre_commit_event_count++; + return; case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: tdata->post_commit_event_count++; return; @@ -255,6 +264,7 @@ _test_l3cfg_signal_notify(NML3Cfg * l3cfg, 1 + 2 + (tdata->add_addr4_101 ? (tdata->has_addr4_101 ? 1 : 3) : 0); if (NM_IN_SET(notify_data->notify_type, + NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT, NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)) return; @@ -368,7 +378,8 @@ test_l3cfg(gconstpointer test_data) g_signal_connect(l3cfg0, NM_L3CFG_SIGNAL_NOTIFY, G_CALLBACK(_test_l3cfg_signal_notify), tdata); - commit_type_1 = nm_l3cfg_commit_type_register(l3cfg0, NM_L3_CFG_COMMIT_TYPE_UPDATE, NULL); + commit_type_1 = + nm_l3cfg_commit_type_register(l3cfg0, NM_L3_CFG_COMMIT_TYPE_UPDATE, NULL, "test1"); if (!nmtst_get_rand_one_case_in(4)) { commit_type_2 = @@ -376,7 +387,8 @@ test_l3cfg(gconstpointer test_data) nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_ASSUME, NM_L3_CFG_COMMIT_TYPE_UPDATE), - NULL); + NULL, + "test2"); } else commit_type_2 = NULL; @@ -389,7 +401,7 @@ test_l3cfg(gconstpointer test_data) { nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; - l3cd = nm_l3_config_data_new(f->multiidx, f->ifindex0); + l3cd = nm_l3_config_data_new(f->multiidx, f->ifindex0, NM_IP_CONFIG_SOURCE_UNKNOWN); nm_l3_config_data_add_address_4( l3cd, @@ -432,8 +444,11 @@ test_l3cfg(gconstpointer test_data) NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, 0, 0, + NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_DNS_PRIORITY_DEFAULT_NORMAL, tdata->acd_defend_type_a, tdata->acd_timeout_msec_a, + NM_L3CFG_CONFIG_FLAGS_NONE, NM_L3_CONFIG_MERGE_FLAGS_NONE); } @@ -445,6 +460,7 @@ test_l3cfg(gconstpointer test_data) _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_COMMIT_1); nm_l3cfg_commit(l3cfg0, NM_L3_CFG_COMMIT_TYPE_REAPPLY); + g_assert_cmpint(tdata->pre_commit_event_count, ==, 1); g_assert_cmpint(tdata->post_commit_event_count, ==, 1); _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); @@ -490,7 +506,7 @@ test_l3cfg(gconstpointer test_data) if (nmtst_get_rand_one_case_in(3)) _test_fixture_1_teardown(&test_fixture); - nm_l3cfg_remove_config_all(l3cfg0, GINT_TO_POINTER('a'), FALSE); + nm_l3cfg_remove_config_all(l3cfg0, GINT_TO_POINTER('a')); if (nmtst_get_rand_one_case_in(3)) _test_fixture_1_teardown(&test_fixture); @@ -593,16 +609,21 @@ _test_l3_ipv4ll_signal_notify(NML3Cfg * l3cfg, 105, 0, 0, + NM_DNS_PRIORITY_DEFAULT_NORMAL, + NM_DNS_PRIORITY_DEFAULT_NORMAL, NM_L3_ACD_DEFEND_TYPE_ONCE, nmtst_get_rand_bool() ? tdata->acd_timeout_msec : 0u, + NM_L3CFG_CONFIG_FLAGS_NONE, NM_L3_CONFIG_MERGE_FLAGS_NONE)) g_assert_not_reached(); - nm_l3cfg_commit_on_idle_schedule(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll)); + nm_l3cfg_commit_on_idle_schedule(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), + NM_L3_CFG_COMMIT_TYPE_AUTO); tdata->l3cfg_commit_type_1 = nm_l3cfg_commit_type_register(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), NM_L3_CFG_COMMIT_TYPE_UPDATE, - tdata->l3cfg_commit_type_1); + tdata->l3cfg_commit_type_1, + "test"); } } else if (nm_l3_ipv4ll_get_state(tdata->l3ipv4ll) != NM_L3_IPV4LL_STATE_DEFENDING && tdata->ready_seen > 0) { @@ -615,10 +636,10 @@ _test_l3_ipv4ll_signal_notify(NML3Cfg * l3cfg, _LOGT("remove address %s that previously passed ACD", _nm_utils_inet4_ntop(tdata->addr_commit_addr, sbuf_addr)); if (!nm_l3cfg_remove_config_all(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), - TEST_L3_IPV4LL_TAG(tdata, 1), - FALSE)) + TEST_L3_IPV4LL_TAG(tdata, 1))) g_assert_not_reached(); - nm_l3cfg_commit_on_idle_schedule(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll)); + nm_l3cfg_commit_on_idle_schedule(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), + NM_L3_CFG_COMMIT_TYPE_AUTO); nm_l3cfg_commit_type_unregister(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), g_steal_pointer(&tdata->l3cfg_commit_type_1)); } @@ -766,9 +787,7 @@ test_l3_ipv4ll(gconstpointer test_data) _LOGT("poll 1 end"); if (tdata->addr_commit || nmtst_get_rand_bool()) { - nm_l3cfg_remove_config_all(nm_l3_ipv4ll_get_l3cfg(l3ipv4ll), - TEST_L3_IPV4LL_TAG(tdata, 1), - FALSE); + nm_l3cfg_remove_config_all(nm_l3_ipv4ll_get_l3cfg(l3ipv4ll), TEST_L3_IPV4LL_TAG(tdata, 1)); } nmtstp_acd_defender_destroy(g_steal_pointer(&acd_defender_1)); @@ -781,6 +800,276 @@ test_l3_ipv4ll(gconstpointer test_data) /*****************************************************************************/ +#define _LLADDR_TEST1 "fe80::dd5a:8a44:48bc:3ad" +#define _LLADDR_TEST2 "fe80::878b:938e:46f9:4807" + +typedef struct { + const TestFixture1 *f; + NML3Cfg * l3cfg0; + NML3IPv6LL * l3ipv6ll; + int step; + int ipv6ll_callback_step; + bool steps_done : 1; + const NMPObject * lladdr0; +} TestL3IPv6LLData; + +static const NMPlatformIP6Address * +_test_l3_ipv6ll_find_lladdr(TestL3IPv6LLData *tdata, int ifindex) +{ + const NMPlatformIP6Address *found = NULL; + NMDedupMultiIter iter; + const NMPObject * obj; + NMPLookup lookup; + + g_assert(tdata); + + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex); + nm_platform_iter_obj_for_each (&iter, tdata->f->platform, &lookup, &obj) { + const NMPlatformIP6Address *a = NMP_OBJECT_CAST_IP6_ADDRESS(obj); + + if (!IN6_IS_ADDR_LINKLOCAL(&a->address)) + continue; + + if (!found) + found = a; + else + g_assert_not_reached(); + } + + return found; +} + +static const NMPObject * +_test_l3_ipv6ll_find_lladdr_wait(TestL3IPv6LLData *tdata, int ifindex) +{ + const NMPObject *obj = NULL; + + nmtst_main_context_iterate_until_assert(NULL, 3000, ({ + const NMPlatformIP6Address *a; + + a = _test_l3_ipv6ll_find_lladdr(tdata, ifindex); + if (a + && !NM_FLAGS_HAS(a->n_ifa_flags, + IFA_F_TENTATIVE)) + obj = NMP_OBJECT_UP_CAST(a); + obj; + })); + + return obj; +} + +static const NMPlatformIP6Address * +_test_l3_ipv6ll_find_inet6(TestL3IPv6LLData *tdata, const struct in6_addr *addr) +{ + const NMPlatformIP6Address *a; + + a = nmtstp_platform_ip6_address_find(nm_l3cfg_get_platform(tdata->l3cfg0), + nmtst_get_rand_bool() ? 0 : tdata->f->ifindex0, + addr); + if (a) { + g_assert_cmpint(a->ifindex, ==, tdata->f->ifindex0); + g_assert_cmpmem(addr, sizeof(*addr), &a->address, sizeof(a->address)); + } + + g_assert(a + == nm_platform_ip6_address_get(nm_l3cfg_get_platform(tdata->l3cfg0), + tdata->f->ifindex0, + addr)); + + return a; +} + +static void +_test_l3_ipv6ll_signal_notify(NML3Cfg * l3cfg, + const NML3ConfigNotifyData *notify_data, + TestL3IPv6LLData * tdata) +{ + g_assert_cmpint(tdata->step, >=, 1); + g_assert_cmpint(tdata->step, <=, 2); +} + +static void +_test_l3_ipv6ll_callback_changed(NML3IPv6LL * ipv6ll, + NML3IPv6LLState state, + const struct in6_addr *lladdr, + gpointer user_data) +{ + TestL3IPv6LLData * tdata = user_data; + int step = tdata->ipv6ll_callback_step++; + const NMPlatformIP6Address *a1; + + g_assert_cmpint(tdata->step, ==, 1); + g_assert(!tdata->steps_done); + + switch (step) { + case 0: + if (NM_IN_SET(tdata->f->test_idx, 1, 2, 4)) { + g_assert_cmpint(state, ==, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS); + g_assert_cmpstr(nmtst_inet6_to_string(lladdr), ==, _LLADDR_TEST1); + } else if (NM_IN_SET(tdata->f->test_idx, 3)) { + g_assert_cmpint(state, ==, NM_L3_IPV6LL_STATE_READY); + g_assert( + IN6_ARE_ADDR_EQUAL(lladdr, &NMP_OBJECT_CAST_IP6_ADDRESS(tdata->lladdr0)->address)); + tdata->steps_done = TRUE; + } else + g_assert_not_reached(); + break; + case 1: + if (NM_IN_SET(tdata->f->test_idx, 1, 2)) { + g_assert_cmpint(state, ==, NM_L3_IPV6LL_STATE_READY); + g_assert_cmpstr(nmtst_inet6_to_string(lladdr), ==, _LLADDR_TEST1); + a1 = _test_l3_ipv6ll_find_inet6(tdata, lladdr); + g_assert(a1); + g_assert(!NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_TENTATIVE)); + tdata->steps_done = TRUE; + } else if (NM_IN_SET(tdata->f->test_idx, 4)) { + g_assert_cmpint(state, ==, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS); + g_assert_cmpstr(nmtst_inet6_to_string(lladdr), ==, _LLADDR_TEST2); + } else + g_assert_not_reached(); + break; + case 2: + if (NM_IN_SET(tdata->f->test_idx, 4)) { + g_assert_cmpint(state, ==, NM_L3_IPV6LL_STATE_READY); + g_assert_cmpstr(nmtst_inet6_to_string(lladdr), ==, _LLADDR_TEST2); + a1 = _test_l3_ipv6ll_find_inet6(tdata, lladdr); + g_assert(a1); + g_assert(!NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_TENTATIVE)); + tdata->steps_done = TRUE; + } else + g_assert_not_reached(); + break; + default: + g_assert_not_reached(); + } +} + +static void +test_l3_ipv6ll(gconstpointer test_data) +{ + NMTST_UTILS_HOST_ID_CONTEXT("l3-ipv6ll"); + const int TEST_IDX = GPOINTER_TO_INT(test_data); + nm_auto(_test_fixture_1_teardown) TestFixture1 test_fixture = {}; + gs_unref_object NML3Cfg *l3cfg0 = NULL; + TestL3IPv6LLData tdata_stack = { + .step = 0, + .steps_done = FALSE, + }; + TestL3IPv6LLData *const tdata = &tdata_stack; + char sbuf1[sizeof(_nm_utils_to_string_buffer)]; + int r; + + _LOGD("test start (/l3-ipv6ll/%d)", TEST_IDX); + + if (nmtst_test_quick()) { + gs_free char *msg = + g_strdup_printf("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", + g_get_prgname() ?: "test-l3-ipv6ll"); + + g_test_skip(msg); + return; + } + + tdata->f = _test_fixture_1_setup(&test_fixture, TEST_IDX); + + if (NM_IN_SET(tdata->f->test_idx, 4)) { + _LOGD("add conflicting IPv6LL on other interface..."); + r = nm_platform_link_change_flags(tdata->f->platform, tdata->f->ifindex1, IFF_UP, FALSE); + g_assert_cmpint(r, >=, 0); + + r = nm_platform_link_set_inet6_addr_gen_mode(tdata->f->platform, + tdata->f->ifindex1, + NM_IN6_ADDR_GEN_MODE_NONE); + g_assert_cmpint(r, >=, 0); + + r = nm_platform_link_change_flags(tdata->f->platform, tdata->f->ifindex1, IFF_UP, TRUE); + g_assert_cmpint(r, >=, 0); + + nmtstp_ip6_address_add(tdata->f->platform, + -1, + tdata->f->ifindex1, + *nmtst_inet6_from_string(_LLADDR_TEST1), + 64, + in6addr_any, + NM_PLATFORM_LIFETIME_PERMANENT, + NM_PLATFORM_LIFETIME_PERMANENT, + 0); + + _LOGD("wait for IPv6 LL address..."); + tdata->lladdr0 = + nmp_object_ref(_test_l3_ipv6ll_find_lladdr_wait(tdata, tdata->f->ifindex1)); + } else if (NM_IN_SET(tdata->f->test_idx, 2, 3)) { + _LOGD("wait for IPv6 LL address..."); + tdata->lladdr0 = + nmp_object_ref(_test_l3_ipv6ll_find_lladdr_wait(tdata, tdata->f->ifindex0)); + } + + if (tdata->lladdr0) { + _LOGD("got IPv6 LL address %s", + nmp_object_to_string(tdata->lladdr0, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1))); + } + + l3cfg0 = _netns_access_l3cfg(tdata->f->netns, tdata->f->ifindex0); + tdata->l3cfg0 = l3cfg0; + + g_signal_connect(tdata->l3cfg0, + NM_L3CFG_SIGNAL_NOTIFY, + G_CALLBACK(_test_l3_ipv6ll_signal_notify), + tdata); + + tdata->l3ipv6ll = nm_l3_ipv6ll_new_stable_privacy(tdata->l3cfg0, + NM_IN_SET(tdata->f->test_idx, 3), + NM_UTILS_STABLE_TYPE_UUID, + tdata->f->ifname0, + "b6a5b934-c649-43dc-a524-3dfdb74f9419", + _test_l3_ipv6ll_callback_changed, + tdata); + + g_assert(nm_l3_ipv6ll_get_l3cfg(tdata->l3ipv6ll) == tdata->l3cfg0); + g_assert_cmpint(nm_l3_ipv6ll_get_ifindex(tdata->l3ipv6ll), ==, tdata->f->ifindex0); + + tdata->step = 1; + nmtst_main_context_iterate_until_assert(NULL, 7000, tdata->steps_done); + + g_assert_cmpint(tdata->step, ==, 1); + if (NM_IN_SET(tdata->f->test_idx, 3)) + g_assert_cmpint(tdata->ipv6ll_callback_step, ==, 1); + else if (NM_IN_SET(tdata->f->test_idx, 4)) + g_assert_cmpint(tdata->ipv6ll_callback_step, ==, 3); + else + g_assert_cmpint(tdata->ipv6ll_callback_step, ==, 2); + g_assert(tdata->steps_done); + + tdata->step = 2; + nmtst_main_context_iterate_until(NULL, nmtst_get_rand_uint32() % 1000, FALSE); + + g_assert_cmpint(tdata->step, ==, 2); + if (NM_IN_SET(tdata->f->test_idx, 3)) + g_assert_cmpint(tdata->ipv6ll_callback_step, ==, 1); + else if (NM_IN_SET(tdata->f->test_idx, 4)) + g_assert_cmpint(tdata->ipv6ll_callback_step, ==, 3); + else + g_assert_cmpint(tdata->ipv6ll_callback_step, ==, 2); + g_assert(tdata->steps_done); + g_assert(tdata->steps_done); + + tdata->step = 0; + tdata->steps_done = FALSE; + + g_signal_handlers_disconnect_by_func(tdata->l3cfg0, + G_CALLBACK(_test_l3_ipv6ll_signal_notify), + tdata); + + nm_l3_ipv6ll_destroy(tdata->l3ipv6ll); + + nm_clear_nmp_object(&tdata->lladdr0); +} + +/*****************************************************************************/ + NMTstpSetupFunc const _nmtstp_setup_platform_func = nm_linux_platform_setup; void @@ -798,4 +1087,8 @@ _nmtstp_setup_tests(void) g_test_add_data_func("/l3cfg/4", GINT_TO_POINTER(4), test_l3cfg); g_test_add_data_func("/l3-ipv4ll/1", GINT_TO_POINTER(1), test_l3_ipv4ll); g_test_add_data_func("/l3-ipv4ll/2", GINT_TO_POINTER(2), test_l3_ipv4ll); + g_test_add_data_func("/l3-ipv6ll/1", GINT_TO_POINTER(1), test_l3_ipv6ll); + g_test_add_data_func("/l3-ipv6ll/2", GINT_TO_POINTER(2), test_l3_ipv6ll); + g_test_add_data_func("/l3-ipv6ll/3", GINT_TO_POINTER(3), test_l3_ipv6ll); + g_test_add_data_func("/l3-ipv6ll/4", GINT_TO_POINTER(4), test_l3_ipv6ll); } diff --git a/src/core/tests/test-systemd.c b/src/core/tests/test-systemd.c index 12d2b911..be070248 100644 --- a/src/core/tests/test-systemd.c +++ b/src/core/tests/test-systemd.c @@ -36,14 +36,14 @@ test_dhcp_create(void) static void test_lldp_create(void) { - sd_lldp *lldp = NULL; - int r; + sd_lldp_rx *lldp = NULL; + int r; - r = sd_lldp_new(&lldp); + r = sd_lldp_rx_new(&lldp); g_assert(r == 0); g_assert(lldp); - sd_lldp_unref(lldp); + sd_lldp_rx_unref(lldp); } /*****************************************************************************/ diff --git a/src/core/tests/test-utils.c b/src/core/tests/test-utils.c index 1d562bde..59d5fd53 100644 --- a/src/core/tests/test-utils.c +++ b/src/core/tests/test-utils.c @@ -16,60 +16,55 @@ test_stable_privacy(void) struct in6_addr addr1; inet_pton(AF_INET6, "1234::", &addr1); - nm_utils_ipv6_addr_set_stable_privacy_impl(NM_UTILS_STABLE_TYPE_UUID, - &addr1, - "eth666", - "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", - 0, - (guint8 *) "key", - 3, - NULL); + nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NM_UTILS_STABLE_TYPE_UUID, + &addr1, + "eth666", + "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", + 0, + (guint8 *) "key", + 3); nmtst_assert_ip6_address(&addr1, "1234::4ceb:14cd:3d54:793f"); /* We get an address without the UUID. */ inet_pton(AF_INET6, "1::", &addr1); - nm_utils_ipv6_addr_set_stable_privacy_impl(NM_UTILS_STABLE_TYPE_UUID, - &addr1, - "eth666", - "", - 384, - (guint8 *) "key", - 3, - NULL); + nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NM_UTILS_STABLE_TYPE_UUID, + &addr1, + "eth666", + "", + 384, + (guint8 *) "key", + 3); nmtst_assert_ip6_address(&addr1, "1::11aa:2530:9144:dafa"); /* We get a different address in a different network. */ inet_pton(AF_INET6, "2::", &addr1); - nm_utils_ipv6_addr_set_stable_privacy_impl(NM_UTILS_STABLE_TYPE_UUID, - &addr1, - "eth666", - "", - 384, - (guint8 *) "key", - 3, - NULL); + nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NM_UTILS_STABLE_TYPE_UUID, + &addr1, + "eth666", + "", + 384, + (guint8 *) "key", + 3); nmtst_assert_ip6_address(&addr1, "2::338e:8d:c11:8726"); inet_pton(AF_INET6, "1234::", &addr1); - nm_utils_ipv6_addr_set_stable_privacy_impl(NM_UTILS_STABLE_TYPE_STABLE_ID, - &addr1, - "eth666", - "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", - 0, - (guint8 *) "key", - 3, - NULL); + nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NM_UTILS_STABLE_TYPE_STABLE_ID, + &addr1, + "eth666", + "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", + 0, + (guint8 *) "key", + 3); nmtst_assert_ip6_address(&addr1, "1234::ad4c:ae44:3d30:af1e"); inet_pton(AF_INET6, "1234::", &addr1); - nm_utils_ipv6_addr_set_stable_privacy_impl(NM_UTILS_STABLE_TYPE_STABLE_ID, - &addr1, - "eth666", - "stable-id-1", - 0, - (guint8 *) "key", - 3, - NULL); + nm_utils_ipv6_addr_set_stable_privacy_with_host_id(NM_UTILS_STABLE_TYPE_STABLE_ID, + &addr1, + "eth666", + "stable-id-1", + 0, + (guint8 *) "key", + 3); nmtst_assert_ip6_address(&addr1, "1234::4944:67b0:7a6c:1cf"); } diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index d06ca46a..d2034278 100644 --- a/src/core/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -1659,6 +1659,7 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict) s_ip, nm_setting_connection_get_mdns(s_con), nm_setting_connection_get_llmnr(s_con), + nm_setting_connection_get_dns_over_tls(s_con), route_table, route_metric); -- cgit 1.3.0-6-gf8a5