diff options
| author | Michael Biebl <biebl@debian.org> | 2020-12-06 21:57:59 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-12-06 21:57:59 +0100 |
| commit | 65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (patch) | |
| tree | 180827692f002e5f1dad6a0fa8ca489e6bb6438f /src | |
| parent | f2ddac4cbc895837ddcc55015fae112f9859cd0a (diff) | |
New upstream version 1.28.0 upstream/1.28.0
Diffstat (limited to 'src')
28 files changed, 1081 insertions, 236 deletions
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 3c27b349..48dcec1b 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -1027,6 +1027,7 @@ create_and_realize(NMDevice * device, const NMPlatformLink **out_plink, GError ** error) { + NMSettingWired * s_wired; NMSettingBridge * s_bridge; const char * iface = nm_device_get_iface(device); const char * hwaddr; @@ -1034,12 +1035,17 @@ create_and_realize(NMDevice * device, guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX]; NMPlatformLnkBridge props; int r; + guint32 mtu = 0; nm_assert(iface); s_bridge = nm_connection_get_setting_bridge(connection); nm_assert(s_bridge); + s_wired = nm_connection_get_setting_wired(connection); + if (s_wired) + mtu = nm_setting_wired_get_mtu(s_wired); + hwaddr = nm_setting_bridge_get_mac_address(s_bridge); if (!hwaddr && nm_device_hw_addr_get_cloned(device, connection, FALSE, &hwaddr_cloned, NULL, NULL)) { @@ -1097,10 +1103,17 @@ create_and_realize(NMDevice * device, to_sysfs_group_address_sys(nm_setting_bridge_get_group_address(s_bridge), &props.group_addr); + /* If mtu != 0, we set the MTU of the new bridge at creation time. However, kernel will still + * automatically adjust the MTU of the bridge based on the minimum of the slave's MTU. + * We don't want this automatism as the user asked for a fixed MTU. + * + * To workaround this behavior of kernel, we will later toggle the MTU twice. See + * NMDeviceClass.mtu_force_set. */ r = nm_platform_link_bridge_add(nm_device_get_platform(device), iface, hwaddr ? mac_address : NULL, hwaddr ? ETH_ALEN : 0, + mtu, &props, out_plink); if (r < 0) { @@ -1152,6 +1165,7 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass) device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_BRIDGE); device_class->is_master = TRUE; + device_class->mtu_force_set = TRUE; device_class->get_generic_capabilities = get_generic_capabilities; device_class->check_connection_compatible = check_connection_compatible; device_class->check_connection_available = check_connection_available; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 2dab5075..0be05f23 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -659,6 +659,8 @@ typedef struct _NMDevicePrivate { guint64 tx_bytes; guint64 rx_bytes; } stats; + + bool mtu_force_set_done : 1; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -10433,6 +10435,18 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) } } + 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) { + 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); + } else + _LOGW(LOGD_DEVICE, "mtu: failure to force-set MTU to %u", mtu_desired - 1); + } + } + _LOGT(LOGD_DEVICE, "mtu: device-mtu: %u%s, ipv6-mtu: %u%s, ifindex: %d", (guint) mtu_desired, @@ -15773,6 +15787,8 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type) priv->linklocal6_dad_counter = 0; + priv->mtu_force_set_done = FALSE; + /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 13782417..3eae9318 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -232,6 +232,17 @@ typedef struct _NMDeviceClass { * type (NMDeviceClass), not the actual device instance. */ bool is_master : 1; + /* Force setting the MTU actually means first setting the MTU + * to (desired_MTU-1) and then setting the desired_MTU + * so that kernel actually applies the MTU, otherwise + * kernel will ignore the request if the link's MTU is the + * same as the desired one. + * + * This is just a workaround made for bridges (ATM) that employ + * a auto-MTU adjust mechanism if no MTU is manually set. + */ + bool mtu_force_set : 1; + void (*state_changed)(NMDevice * device, NMDeviceState new_state, NMDeviceState old_state, diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index 9826c1b7..27ef789f 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -707,7 +707,7 @@ _add_interface(NMOvsdb * self, nm_auto_decref_json json_t *interfaces = NULL; nm_auto_decref_json json_t *new_interfaces = NULL; gboolean has_interface = FALSE; - gboolean interface_is_internal; + gboolean interface_is_local; gs_free char * bridge_cloned_mac = NULL; gs_free char * interface_cloned_mac = NULL; GError * error = NULL; @@ -721,10 +721,10 @@ _add_interface(NMOvsdb * self, new_ports = json_array(); new_interfaces = json_array(); - bridge_name = nm_connection_get_interface_name(bridge); - port_name = nm_connection_get_interface_name(port); - interface_name = nm_connection_get_interface_name(interface); - interface_is_internal = nm_streq0(bridge_name, interface_name); + bridge_name = nm_connection_get_interface_name(bridge); + port_name = nm_connection_get_interface_name(port); + interface_name = nm_connection_get_interface_name(interface); + interface_is_local = nm_streq0(bridge_name, interface_name); /* Determine cloned MAC addresses */ if (!nm_device_hw_addr_get_cloned(bridge_device, @@ -733,7 +733,7 @@ _add_interface(NMOvsdb * self, &bridge_cloned_mac, NULL, &error)) { - _LOGW("Cannot determine cloned mac for OVS %s '%s': %s", + _LOGW("Cannot determine cloned MAC for OVS %s '%s': %s", "bridge", bridge_name, error->message); @@ -746,18 +746,34 @@ _add_interface(NMOvsdb * self, &interface_cloned_mac, NULL, &error)) { - _LOGW("Cannot determine cloned mac for OVS %s '%s': %s", + _LOGW("Cannot determine cloned MAC for OVS %s '%s': %s", "interface", interface_name, error->message); g_clear_error(&error); } - if (interface_is_internal && !bridge_cloned_mac && interface_cloned_mac) { - _LOGT("'%s' is a local ovs-interface, the MAC will be set on ovs-bridge '%s'", - interface_name, - bridge_name); - bridge_cloned_mac = g_steal_pointer(&interface_cloned_mac); + /* For local interfaces, ovs complains if it finds a + * MAC address in the Interface table because it only takes + * the MAC from the Bridge table. + * Set any cloned MAC present in a local interface connection + * into the Bridge table, unless conflicting with the bridge MAC. */ + if (interface_is_local && interface_cloned_mac) { + if (bridge_cloned_mac && !nm_streq(interface_cloned_mac, bridge_cloned_mac)) { + _LOGW("Cloned MAC '%s' of local ovs-interface '%s' conflicts with MAC '%s' of bridge " + "'%s'", + interface_cloned_mac, + interface_name, + bridge_cloned_mac, + bridge_name); + nm_clear_g_free(&interface_cloned_mac); + } else { + nm_clear_g_free(&bridge_cloned_mac); + bridge_cloned_mac = g_steal_pointer(&interface_cloned_mac); + _LOGT("'%s' is a local ovs-interface, the MAC will be set on ovs-bridge '%s'", + interface_name, + bridge_name); + } } g_hash_table_iter_init(&iter, priv->bridges); @@ -823,7 +839,7 @@ _add_interface(NMOvsdb * self, g_return_if_fail(ovs_bridge); _expect_bridge_ports(params, ovs_bridge->name, ports); _set_bridge_ports(params, bridge_name, new_ports); - if (bridge_cloned_mac && interface_is_internal) + if (bridge_cloned_mac && interface_is_local) _set_bridge_mac(params, bridge_name, bridge_cloned_mac); } @@ -1175,8 +1191,12 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) } if (ovs) { - iter = json_object_iter(ovs); - priv->db_uuid = iter ? g_strdup(json_object_iter_key(iter)) : NULL; + const char *s; + + iter = json_object_iter(ovs); + s = json_object_iter_key(iter); + if (s) + nm_utils_strdup_reset(&priv->db_uuid, s); } /* Interfaces */ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 55062644..980916dd 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -1390,11 +1390,11 @@ _hw_addr_set_scanning(NMDeviceWifi *self, gboolean do_reset) * a new one.*/ priv->hw_addr_scan_expire = now + SCAN_RAND_MAC_ADDRESS_EXPIRE_SEC; - generate_mac_address_mask = - nm_config_data_get_device_config(NM_CONFIG_GET_DATA, - "wifi.scan-generate-mac-address-mask", - device, - NULL); + generate_mac_address_mask = nm_config_data_get_device_config( + NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_GENERATE_MAC_ADDRESS_MASK, + device, + NULL); priv->scan_last_request_started_at_msec = G_MININT64; priv->scan_periodic_next_msec = 0; diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index 6a562014..c7e99e0b 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -673,15 +673,16 @@ connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpoint gboolean mapped; KnownNetworkData * data; KnownNetworkId id; + gs_free char * ssid_str = NULL; id.security = nm_wifi_connection_get_iwd_security(conn, &mapped); if (!mapped) return; s_wireless = nm_connection_get_setting_wireless(conn); - id.name = _nm_utils_ssid_to_utf8(nm_setting_wireless_get_ssid(s_wireless)); + ssid_str = _nm_utils_ssid_to_utf8(nm_setting_wireless_get_ssid(s_wireless)); + id.name = ssid_str; data = g_hash_table_lookup(priv->known_networks, &id); - g_free((char *) id.name); if (!data) return; diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index fe26421d..55438a53 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -113,22 +113,26 @@ nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid) g_return_val_if_fail(NM_IS_WIFI_AP(ap), FALSE); - if (ssid) { - l = g_bytes_get_size(ssid); - if (l == 0 || l > 32) - g_return_val_if_reached(FALSE); + if (!ssid) { + /* we don't clear the SSID, once we have it. We can only update + * it by a better value. */ + return FALSE; } + l = g_bytes_get_size(ssid); + if (l == 0 || l > 32) + g_return_val_if_reached(FALSE); + priv = NM_WIFI_AP_GET_PRIVATE(ap); if (ssid == priv->ssid) return FALSE; - if (ssid && priv->ssid && g_bytes_equal(ssid, priv->ssid)) + if (priv->ssid && g_bytes_equal(ssid, priv->ssid)) return FALSE; + g_bytes_ref(ssid); nm_clear_pointer(&priv->ssid, g_bytes_unref); - if (ssid) - priv->ssid = g_bytes_ref(ssid); + priv->ssid = ssid; _notify(ap, PROP_SSID); return TRUE; diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 633878ce..7b3a13a3 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -39,8 +39,11 @@ MODEM_CAPS_3GPP(MMModemCapability caps) #define MODEM_CAPS_3GPP2(caps) (caps & (MM_MODEM_CAPABILITY_CDMA_EVDO)) -/* Maximum time to keep the DBus call waiting for a connection result */ -#define MODEM_CONNECT_TIMEOUT_SECS 120 +/* Maximum time to keep the DBus call waiting for a connection result. + * This value is greater than the default timeout in ModemManager (180s since + * 1.16), so that whenever possible the timeout happens first there instead of + * in NetworkManager. */ +#define MODEM_CONNECT_TIMEOUT_SECS 200 /*****************************************************************************/ diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index 451e4846..97f1dfab 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -820,11 +820,18 @@ add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfigD for (i = 0; i < num; i++) { addr = nm_ip_config_get_nameserver(ip_config, i); ip_addr_to_string(addr_family, addr, iface, ip_addr_to_string_buf); - for (j = 0; ip_data->domains.search[j]; j++) { - domain = nm_utils_parse_dns_domain(ip_data->domains.search[j], NULL); - add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, domain[0] ? domain : NULL); - } + if (!ip_data->domains.has_default_route_explicit && ip_data->domains.has_default_route) + add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, NULL); + if (ip_data->domains.search) { + for (j = 0; ip_data->domains.search[j]; j++) { + domain = nm_utils_parse_dns_domain(ip_data->domains.search[j], NULL); + add_dnsmasq_nameserver(self, + servers, + ip_addr_to_string_buf, + domain[0] ? domain : NULL); + } + } if (ip_data->domains.reverse) { for (j = 0; ip_data->domains.reverse[j]; j++) { add_dnsmasq_nameserver(self, diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 635e94f6..3fc9a396 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -222,6 +222,26 @@ _ASSERT_ip_config_data(const NMDnsIPConfigData *ip_data) nm_assert(NM_IS_IP_CONFIG(ip_data->ip_config)); nm_assert(c_list_contains(&ip_data->data->data_lst_head, &ip_data->data_lst)); nm_assert(ip_data->data->ifindex == nm_ip_config_get_ifindex(ip_data->ip_config)); +#if NM_MORE_ASSERTS > 5 + { + gboolean has_default = FALSE; + gsize i; + + for (i = 0; ip_data->domains.search && ip_data->domains.search; i++) { + const char *d = ip_data->domains.search[i]; + + d = nm_utils_parse_dns_domain(d, NULL); + nm_assert(d); + if (d[0] == '\0') + has_default = TRUE; + } + nm_assert(has_default == ip_data->domains.has_default_route_explicit); + if (ip_data->domains.has_default_route_explicit) + nm_assert(ip_data->domains.has_default_route_exclusive); + if (ip_data->domains.has_default_route_exclusive) + nm_assert(ip_data->domains.has_default_route); + } +#endif } static NMDnsIPConfigData * @@ -233,10 +253,12 @@ _ip_config_data_new(NMDnsConfigData *data, NMIPConfig *ip_config, NMDnsIPConfigT nm_assert(NM_IS_IP_CONFIG(ip_config)); nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); - ip_data = g_slice_new0(NMDnsIPConfigData); - ip_data->data = data; - ip_data->ip_config = g_object_ref(ip_config); - ip_data->ip_config_type = ip_config_type; + ip_data = g_slice_new(NMDnsIPConfigData); + *ip_data = (NMDnsIPConfigData){ + .data = data, + .ip_config = g_object_ref(ip_config), + .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_config_lst_head, &ip_data->ip_config_lst); @@ -267,7 +289,7 @@ _ip_config_data_free(NMDnsIPConfigData *ip_data) ip_data); g_object_unref(ip_data->ip_config); - g_slice_free(NMDnsIPConfigData, ip_data); + nm_g_slice_free(ip_data); } static NMDnsIPConfigData * @@ -292,7 +314,7 @@ _config_data_free(NMDnsConfigData *data) _ASSERT_config_data(data); nm_assert(c_list_is_empty(&data->data_lst_head)); - g_slice_free(NMDnsConfigData, data); + nm_g_slice_free(data); } static int @@ -1284,6 +1306,19 @@ get_ip_rdns_domains(NMIPConfig *ip_config) return _nm_utils_strv_cleanup(strv, FALSE, FALSE, TRUE); } +static gboolean +domain_ht_get_priority(GHashTable *ht, const char *domain, int *out_priority) +{ + gpointer ptr; + + if (!ht || !g_hash_table_lookup_extended(ht, domain, NULL, &ptr)) { + *out_priority = 0; + return FALSE; + } + *out_priority = GPOINTER_TO_INT(ptr); + return TRUE; +} + /* Check if the domain is shadowed by a parent domain with more negative priority */ static gboolean domain_is_shadowed(GHashTable * ht, @@ -1300,21 +1335,25 @@ domain_is_shadowed(GHashTable * ht, nm_assert(!g_hash_table_contains(ht, domain)); - parent_priority = GPOINTER_TO_INT(g_hash_table_lookup(ht, "")); - if (parent_priority < 0 && parent_priority < priority) { - *out_parent = ""; - *out_parent_priority = parent_priority; - return TRUE; + if (domain_ht_get_priority(ht, "", &parent_priority)) { + nm_assert(parent_priority <= priority); + if (parent_priority < 0 && parent_priority < priority) { + *out_parent = ""; + *out_parent_priority = parent_priority; + return TRUE; + } } parent = strchr(domain, '.'); while (parent && parent[1]) { parent++; - parent_priority = GPOINTER_TO_INT(g_hash_table_lookup(ht, parent)); - if (parent_priority < 0 && parent_priority < priority) { - *out_parent = parent; - *out_parent_priority = parent_priority; - return TRUE; + if (domain_ht_get_priority(ht, parent, &parent_priority)) { + nm_assert(parent_priority <= priority); + if (parent_priority < 0 && parent_priority < priority) { + *out_parent = parent; + *out_parent_priority = parent_priority; + return TRUE; + } } parent = strchr(parent, '.'); } @@ -1329,8 +1368,22 @@ rebuild_domain_lists(NMDnsManager *self) gs_unref_hashtable GHashTable *ht = NULL; gs_unref_hashtable GHashTable *wildcard_entries = NULL; CList * head; + int prev_priority = G_MININT; head = _ip_config_lst_head(self); + +#if NM_MORE_ASSERTS + /* we call clear_domain_lists() at the end of update. We + * don't expect any domain settings here. */ + c_list_for_each_entry (ip_data, head, ip_config_lst) { + nm_assert(!ip_data->domains.search); + nm_assert(!ip_data->domains.reverse); + nm_assert(!ip_data->domains.has_default_route_explicit); + nm_assert(!ip_data->domains.has_default_route_exclusive); + nm_assert(!ip_data->domains.has_default_route); + } +#endif + c_list_for_each_entry (ip_data, head, ip_config_lst) { NMIPConfig *ip_config = ip_data->ip_config; gboolean add_wildcard = FALSE; @@ -1368,8 +1421,11 @@ rebuild_domain_lists(NMDnsManager *self) guint n_domains; guint num_dom1; guint num_dom2; - guint cap_dom; + guint n_domains_allocated; guint i; + gboolean has_default_route_maybe = FALSE; + gboolean has_default_route_explicit = FALSE; + gboolean has_default_route_auto = FALSE; if (!nm_ip_config_get_num_nameservers(ip_config)) continue; @@ -1378,15 +1434,10 @@ rebuild_domain_lists(NMDnsManager *self) n_domains = nm_ip_config_get_num_domains(ip_config); priority = nm_ip_config_get_dns_priority(ip_config); - nm_assert(priority != 0); - - cap_dom = 2u + NM_MAX(n_domains, n_searches); - - g_free(ip_data->domains.search); - domains = g_new(const char *, cap_dom); - ip_data->domains.search = domains; - num_dom1 = 0; + nm_assert(priority != 0); + nm_assert(prev_priority <= priority); + prev_priority = priority; /* Add wildcard lookup domain to connections with the default route. * If there is no default route, add the wildcard domain to all non-VPN @@ -1398,12 +1449,17 @@ rebuild_domain_lists(NMDnsManager *self) * whether it is suitable for certain operations (like having an automatically * added "~" domain). */ if (g_hash_table_contains(wildcard_entries, ip_data)) - domains[num_dom1++] = "~"; + has_default_route_maybe = TRUE; } else { if (ip_data->ip_config_type != NM_DNS_IP_CONFIG_TYPE_VPN) - domains[num_dom1++] = "~"; + has_default_route_maybe = TRUE; } + n_domains_allocated = (n_searches > 0 ? n_searches : n_domains) + 1u; + domains = g_new(const char *, n_domains_allocated); + + num_dom1 = 0; + /* searches are preferred over domains */ if (n_searches > 0) { for (i = 0; i < n_searches; i++) @@ -1413,32 +1469,55 @@ rebuild_domain_lists(NMDnsManager *self) domains[num_dom1++] = nm_ip_config_get_domain(ip_config, i); } - nm_assert(num_dom1 < cap_dom); + nm_assert(num_dom1 < n_domains_allocated); num_dom2 = 0; - for (i = 0; i < num_dom1; i++) { + for (i = 0; TRUE; i++) { + const char *domain_full; const char *domain_clean; const char *parent; int old_priority; int parent_priority; - - domain_clean = nm_utils_parse_dns_domain(domains[i], NULL); + gboolean check_default_route; + + if (i < num_dom1) { + check_default_route = FALSE; + domain_full = domains[i]; + domain_clean = nm_utils_parse_dns_domain(domains[i], NULL); + } else if (i == num_dom1) { + if (!has_default_route_maybe) + continue; + if (has_default_route_explicit) + continue; + check_default_route = TRUE; + domain_full = "~"; + domain_clean = ""; + } else + break; /* Remove domains with lower priority */ - old_priority = GPOINTER_TO_INT(nm_g_hash_table_lookup(ht, domain_clean)); - if (old_priority != 0) { + if (domain_ht_get_priority(ht, domain_clean, &old_priority)) { + nm_assert(old_priority <= priority); if (old_priority < priority) { - _LOGT( - "plugin: drop domain '%s' (i=%d, p=%d) because it already exists with p=%d", - domains[i], - ip_data->data->ifindex, - priority, - old_priority); + _LOGT("plugin: drop domain %s%s%s (i=%d, p=%d) because it already exists " + "with p=%d", + NM_PRINT_FMT_QUOTED(!check_default_route, + "'", + domain_full, + "'", + "<auto-default>"), + ip_data->data->ifindex, + priority, + old_priority); continue; } } else if (domain_is_shadowed(ht, domain_clean, priority, &parent, &parent_priority)) { - _LOGT("plugin: drop domain '%s' (i=%d, p=%d) shadowed by '%s' (p=%d)", - domains[i], + _LOGT("plugin: drop domain %s%s%s (i=%d, p=%d) shadowed by '%s' (p=%d)", + NM_PRINT_FMT_QUOTED(!check_default_route, + "'", + domain_full, + "'", + "<auto-default>"), ip_data->data->ifindex, priority, parent, @@ -1446,20 +1525,55 @@ rebuild_domain_lists(NMDnsManager *self) continue; } - _LOGT("plugin: add domain '%s' (i=%d, p=%d)", - domains[i], - ip_data->data->ifindex, - priority); + _LOGT( + "plugin: add domain %s%s%s (i=%d, p=%d)", + NM_PRINT_FMT_QUOTED(!check_default_route, "'", domain_full, "'", "<auto-default>"), + ip_data->data->ifindex, + priority); + if (!ht) ht = g_hash_table_new(nm_str_hash, g_str_equal); g_hash_table_insert(ht, (gpointer) domain_clean, GINT_TO_POINTER(priority)); - domains[num_dom2++] = domains[i]; + + if (check_default_route) + has_default_route_auto = TRUE; + else { + nm_assert(num_dom2 <= num_dom1); + nm_assert(num_dom2 < n_domains_allocated); + domains[num_dom2++] = domain_full; + if (domain_clean[0] == '\0') + has_default_route_explicit = TRUE; + } } - nm_assert(num_dom2 < cap_dom); + nm_assert(num_dom2 < n_domains_allocated); domains[num_dom2] = NULL; - g_strfreev(ip_data->domains.reverse); - ip_data->domains.reverse = get_ip_rdns_domains(ip_config); + nm_assert(!ip_data->domains.search); + nm_assert(!ip_data->domains.reverse); + ip_data->domains.search = domains; + ip_data->domains.reverse = get_ip_rdns_domains(ip_config); + ip_data->domains.has_default_route_explicit = has_default_route_explicit; + ip_data->domains.has_default_route_exclusive = + has_default_route_explicit || (priority < 0 && has_default_route_auto); + ip_data->domains.has_default_route = + ip_data->domains.has_default_route_exclusive || has_default_route_auto; + + { + gs_free char *str1 = NULL; + gs_free char *str2 = NULL; + + _LOGT("plugin: settings: ifindex=%d, priority=%d, default-route=%d%s, search=%s, " + "reverse=%s", + ip_data->data->ifindex, + priority, + ip_data->domains.has_default_route, + ip_data->domains.has_default_route_explicit + ? " (explicit)" + : (ip_data->domains.has_default_route_exclusive ? " (exclusive)" : ""), + (str1 = g_strjoinv(",", (char **) ip_data->domains.search)), + (ip_data->domains.reverse ? (str2 = g_strjoinv(",", ip_data->domains.reverse)) + : "")); + } } } @@ -1473,6 +1587,9 @@ clear_domain_lists(NMDnsManager *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); + ip_data->domains.has_default_route_explicit = FALSE; + ip_data->domains.has_default_route_exclusive = FALSE; + ip_data->domains.has_default_route = FALSE; } } @@ -1697,7 +1814,7 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, priv = NM_DNS_MANAGER_GET_PRIVATE(self); - data = g_hash_table_lookup(priv->configs, GINT_TO_POINTER(ifindex)); + data = g_hash_table_lookup(priv->configs, &ifindex); if (!data) ip_data = NULL; else @@ -1713,7 +1830,7 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, /* deleting a config doesn't invalidate the configs' sort order. */ _ip_config_data_free(ip_data); if (c_list_is_empty(&data->data_lst_head)) - g_hash_table_remove(priv->configs, GINT_TO_POINTER(ifindex)); + g_hash_table_remove(priv->configs, &ifindex); goto changed; } @@ -1723,12 +1840,14 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, } if (!data) { - data = g_slice_new0(NMDnsConfigData); - data->ifindex = ifindex; - data->self = self; - c_list_init(&data->data_lst_head); + data = g_slice_new(NMDnsConfigData); + *data = (NMDnsConfigData){ + .ifindex = ifindex, + .self = self, + .data_lst_head = C_LIST_INIT(data->data_lst_head), + }; _ASSERT_config_data(data); - g_hash_table_insert(priv->configs, GINT_TO_POINTER(ifindex), data); + g_hash_table_add(priv->configs, data); } if (!ip_data) @@ -2381,8 +2500,11 @@ nm_dns_manager_init(NMDnsManager *self) priv->config = g_object_ref(nm_config_get()); - priv->configs = - g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _config_data_free); + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDnsConfigData, ifindex) == 0); + priv->configs = g_hash_table_new_full(nm_pint_hash, + nm_pint_equals, + (GDestroyNotify) _config_data_free, + NULL); /* Set the initial hash */ compute_hash(self, NULL, NM_DNS_MANAGER_GET_PRIVATE(self)->hash); diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h index f91d1556..fb2f36d2 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/dns/nm-dns-manager.h @@ -22,7 +22,7 @@ typedef enum { enum { NM_DNS_PRIORITY_DEFAULT_NORMAL = 100, - NM_DNS_PRIORITY_DEFAULT_VPN = -50, + NM_DNS_PRIORITY_DEFAULT_VPN = 50, }; struct _NMDnsConfigData; @@ -37,13 +37,35 @@ typedef struct { struct { const char **search; char ** reverse; + + /* Whether "search" explicitly contains a default route "~" + * or "". It is redundant information, but for faster lookup. */ + bool has_default_route_explicit : 1; + + /* Whether an explicit "~" search domain should be added. + * For systemd-resolved, this configured an explicit wildcard + * search domain, and should be used for profiles with negative + * DNS priority. + * + * If "has_default_route_explicit", this is always TRUE and implied. + * + * With systemd-resolved, if TRUE we will set a "." search domain. + */ + bool has_default_route_exclusive : 1; + + /* Whether the device should be used for any domains "~". + * + * If "has_default_route_exclusive", this is always TRUE and implied. + * + * With systemd-resolved, this is the value for SetLinkDefaultRoute(). */ + bool has_default_route : 1; } domains; } NMDnsIPConfigData; typedef struct _NMDnsConfigData { + int ifindex; struct _NMDnsManager *self; CList data_lst_head; - int ifindex; } NMDnsConfigData; #define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type()) diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c index 24c0ddb5..fe2e78af 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/dns/nm-dns-systemd-resolved.c @@ -34,6 +34,9 @@ #define SYSTEMD_RESOLVED_MANAGER_IFACE "org.freedesktop.resolve1.Manager" #define SYSTEMD_RESOLVED_DBUS_PATH "/org/freedesktop/resolve1" +/* define a variable, so that we can compare the operation with pointer equality. */ +static const char *const DBUS_OP_SET_LINK_DEFAULT_ROUTE = "SetLinkDefaultRoute"; + /*****************************************************************************/ typedef struct { @@ -42,15 +45,18 @@ typedef struct { } InterfaceConfig; typedef struct { - CList request_queue_lst; - const char *operation; - GVariant * argument; + CList request_queue_lst; + const char * operation; + GVariant * argument; + NMDnsSystemdResolved *self; + int ifindex; } RequestItem; /*****************************************************************************/ typedef struct { GDBusConnection *dbus_connection; + GHashTable * dirty_interfaces; GCancellable * cancellable; CList request_queue_lst_head; guint name_owner_changed_id; @@ -58,6 +64,8 @@ typedef struct { bool try_start_blocked : 1; bool dbus_has_owner : 1; bool dbus_initied : 1; + bool request_queue_to_send : 1; + NMTernary has_link_default_route : 3; } NMDnsSystemdResolvedPrivate; struct _NMDnsSystemdResolved { @@ -87,18 +95,26 @@ _request_item_free(RequestItem *request_item) { c_list_unlink_stale(&request_item->request_queue_lst); g_variant_unref(request_item->argument); - g_slice_free(RequestItem, request_item); + nm_g_slice_free(request_item); } static void -_request_item_append(CList *request_queue_lst_head, const char *operation, GVariant *argument) +_request_item_append(NMDnsSystemdResolved *self, + const char * operation, + int ifindex, + GVariant * argument) { - RequestItem *request_item; + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + RequestItem * request_item; - request_item = g_slice_new(RequestItem); - request_item->operation = operation; - request_item->argument = g_variant_ref_sink(argument); - c_list_link_tail(request_queue_lst_head, &request_item->request_queue_lst); + request_item = g_slice_new(RequestItem); + *request_item = (RequestItem){ + .operation = operation, + .argument = g_variant_ref_sink(argument), + .self = self, + .ifindex = ifindex, + }; + c_list_link_tail(&priv->request_queue_lst_head, &request_item->request_queue_lst); } /*****************************************************************************/ @@ -115,43 +131,69 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) { gs_unref_variant GVariant *v = NULL; gs_free_error GError * error = NULL; - NMDnsSystemdResolved * self = (NMDnsSystemdResolved *) user_data; + NMDnsSystemdResolved * self; NMDnsSystemdResolvedPrivate *priv; + RequestItem * request_item; + NMLogLevel log_level; v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), r, &error); - if (!v && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (nm_utils_error_is_cancelled(error)) return; - priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + request_item = user_data; + self = request_item->self; + priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); - if (!v) { - if (!priv->send_updates_warn_ratelimited) { - priv->send_updates_warn_ratelimited = TRUE; - _LOGW("send-updates failed to update systemd-resolved: %s", error->message); - } else - _LOGD("send-updates failed: %s", error->message); - } else + if (v) { + if (request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE + && priv->has_link_default_route == NM_TERNARY_DEFAULT) { + priv->has_link_default_route = NM_TERNARY_TRUE; + _LOGD("systemd-resolved support for SetLinkDefaultRoute(): 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) { + priv->has_link_default_route = NM_TERNARY_FALSE; + _LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported"); + } + return; + } + + log_level = LOGL_DEBUG; + if (!priv->send_updates_warn_ratelimited) { + priv->send_updates_warn_ratelimited = TRUE; + log_level = LOGL_WARN; + } + _NMLOG(log_level, + "send-updates %s@%d failed: %s", + request_item->operation, + request_item->ifindex, + error->message); } -static void +static gboolean update_add_ip_config(NMDnsSystemdResolved *self, GVariantBuilder * dns, GVariantBuilder * domains, NMDnsIPConfigData * data) { - int addr_family; - gsize addr_size; - guint i, n; - gboolean is_routing; - const char **iter; - const char * domain; + int addr_family; + gsize addr_size; + guint i, n; + gboolean is_routing; + const char *domain; + gboolean has_config = FALSE; addr_family = nm_ip_config_get_addr_family(data->ip_config); addr_size = nm_utils_addr_family_to_size(addr_family); - if (!data->domains.search || !data->domains.search[0]) - return; + if ((!data->domains.search || !data->domains.search[0]) + && !data->domains.has_default_route_exclusive && !data->domains.has_default_route) + return FALSE; n = nm_ip_config_get_num_nameservers(data->ip_config); for (i = 0; i < n; i++) { @@ -164,12 +206,22 @@ update_add_ip_config(NMDnsSystemdResolved *self, addr_size, 1)); g_variant_builder_close(dns); + has_config = TRUE; } - for (iter = data->domains.search; *iter; iter++) { - domain = nm_utils_parse_dns_domain(*iter, &is_routing); - g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + if (!data->domains.has_default_route_explicit && data->domains.has_default_route_exclusive) { + g_variant_builder_add(domains, "(sb)", ".", TRUE); + has_config = TRUE; } + if (data->domains.search) { + for (i = 0; data->domains.search[i]; i++) { + domain = nm_utils_parse_dns_domain(data->domains.search[i], &is_routing); + g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + has_config = TRUE; + } + } + + return has_config; } static void @@ -183,15 +235,17 @@ free_pending_updates(NMDnsSystemdResolved *self) _request_item_free(request_item); } -static void +static gboolean prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) { - NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); - GVariantBuilder dns, 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; + 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; g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))")); g_variant_builder_add(&dns, "i", ic->ifindex); @@ -205,7 +259,10 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) NMDnsIPConfigData *data = elem->data; NMIPConfig * ip_config = data->ip_config; - update_add_ip_config(self, &dns, &domains, data); + has_config |= update_add_ip_config(self, &dns, &domains, data); + + if (data->domains.has_default_route) + has_default_route = TRUE; if (NM_IS_IP4_CONFIG(ip_config)) { mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_IP4_CONFIG(ip_config))); @@ -248,16 +305,25 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) } nm_assert(llmnr_arg); - _request_item_append(&priv->request_queue_lst_head, "SetLinkDNS", g_variant_builder_end(&dns)); - _request_item_append(&priv->request_queue_lst_head, - "SetLinkDomains", - g_variant_builder_end(&domains)); - _request_item_append(&priv->request_queue_lst_head, + if (!nm_str_is_empty(mdns_arg) || !nm_str_is_empty(llmnr_arg)) + has_config = TRUE; + + _request_item_append(self, "SetLinkDomains", ic->ifindex, g_variant_builder_end(&domains)); + _request_item_append(self, + DBUS_OP_SET_LINK_DEFAULT_ROUTE, + ic->ifindex, + g_variant_new("(ib)", ic->ifindex, has_default_route)); + _request_item_append(self, "SetLinkMulticastDNS", + ic->ifindex, g_variant_new("(is)", ic->ifindex, mdns_arg ?: "")); - _request_item_append(&priv->request_queue_lst_head, + _request_item_append(self, "SetLinkLLMNR", + ic->ifindex, g_variant_new("(is)", ic->ifindex, llmnr_arg ?: "")); + _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); + + return has_config; } static void @@ -266,7 +332,7 @@ send_updates(NMDnsSystemdResolved *self) NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); RequestItem * request_item; - if (c_list_is_empty(&priv->request_queue_lst_head)) { + if (!priv->request_queue_to_send) { /* nothing to do. */ return; } @@ -296,15 +362,30 @@ send_updates(NMDnsSystemdResolved *self) return; } - _LOGT("send-updates: start %lu requests", c_list_length(&priv->request_queue_lst_head)); - 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; + } + + _LOGT("send-updates: start %lu requests", c_list_length(&priv->request_queue_lst_head)); + priv->cancellable = g_cancellable_new(); - while ( - (request_item = - c_list_first_entry(&priv->request_queue_lst_head, RequestItem, request_queue_lst))) { + priv->request_queue_to_send = FALSE; + + c_list_for_each_entry (request_item, &priv->request_queue_lst_head, request_queue_lst) { + 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. + * We detected that it is not supported, and skip the call. There + * is no special workaround, because in this case we rely on systemd-resolved + * to do the right thing automatically. */ + 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 @@ -324,8 +405,7 @@ send_updates(NMDnsSystemdResolved *self) -1, priv->cancellable, call_done, - self); - _request_item_free(request_item); + request_item); } } @@ -336,19 +416,22 @@ update(NMDnsPlugin * plugin, const char * hostname, GError ** error) { - NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin); + NMDnsSystemdResolved * self = NM_DNS_SYSTEMD_RESOLVED(plugin); + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); gs_unref_hashtable GHashTable *interfaces = NULL; gs_free gpointer * interfaces_keys = NULL; guint interfaces_len; - guint i; + int ifindex; + gpointer pointer; NMDnsIPConfigData *ip_data; + GHashTableIter iter; + guint i; interfaces = g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _interface_config_free); c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) { InterfaceConfig *ic = NULL; - int ifindex; ifindex = ip_data->data->ifindex; nm_assert(ifindex == nm_ip_config_get_ifindex(ip_data->ip_config)); @@ -371,11 +454,33 @@ update(NMDnsPlugin * plugin, for (i = 0; i < interfaces_len; i++) { InterfaceConfig *ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(interfaces_keys[i])); - prepare_one_interface(self, ic); + if (prepare_one_interface(self, ic)) + g_hash_table_add(priv->dirty_interfaces, GINT_TO_POINTER(ic->ifindex)); + else + g_hash_table_remove(priv->dirty_interfaces, GINT_TO_POINTER(ic->ifindex)); } - send_updates(self); + /* If we previously configured an ifindex with non-empty values in + * resolved, and the current update doesn't contain that interface, + * reset the resolved configuration for that ifindex. */ + g_hash_table_iter_init(&iter, priv->dirty_interfaces); + while (g_hash_table_iter_next(&iter, (gpointer *) &pointer, NULL)) { + ifindex = GPOINTER_TO_INT(pointer); + if (!g_hash_table_contains(interfaces, GINT_TO_POINTER(ifindex))) { + InterfaceConfig ic; + + _LOGT("clear previously configured ifindex %d", ifindex); + ic = (InterfaceConfig){ + .ifindex = ifindex, + .configs_lst_head = C_LIST_INIT(ic.configs_lst_head), + }; + prepare_one_interface(self, &ic); + g_hash_table_iter_remove(&iter); + } + } + priv->request_queue_to_send = TRUE; + send_updates(self); return TRUE; } @@ -394,8 +499,11 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner) _LOGT("D-Bus name for systemd-resolved has owner %s", owner); priv->dbus_has_owner = !!owner; - if (owner) - priv->try_start_blocked = FALSE; + if (owner) { + priv->try_start_blocked = FALSE; + priv->request_queue_to_send = TRUE; + } else + priv->has_link_default_route = NM_TERNARY_DEFAULT; send_updates(self); } @@ -468,7 +576,10 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) { NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); + priv->has_link_default_route = NM_TERNARY_DEFAULT; + c_list_init(&priv->request_queue_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); if (!priv->dbus_connection) { @@ -510,6 +621,7 @@ dispose(GObject *object) nm_clear_g_cancellable(&priv->cancellable); 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); } diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h index cac01cb8..69c24b1b 100644 --- a/src/initrd/nm-initrd-generator.h +++ b/src/initrd/nm-initrd-generator.h @@ -11,17 +11,23 @@ #define NMI_WAIT_DEVICE_TIMEOUT_MS 60000 -static inline gboolean -guess_ip_address_family(const char *str) +static inline int +get_ip_address_family(const char *str, gboolean with_prefix) { - if (str == NULL) - return AF_UNSPEC; - else if (strchr(str, '.')) - return AF_INET; - else if (strchr(str, ':')) - return AF_INET6; - else + 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); diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 5e610e15..1c1b43eb 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -24,6 +24,8 @@ 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; @@ -41,8 +43,11 @@ reader_new(void) reader = g_slice_new(Reader); *reader = (Reader){ - .hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_object_unref), - .array = g_ptr_array_new(), + .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; @@ -54,6 +59,8 @@ 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); @@ -383,6 +390,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) 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; @@ -411,17 +419,37 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) /* ip={dhcp|on|any|dhcp6|auto6|ibft} */ kind = tmp; } else { - client_ip_family = guess_ip_address_family(tmp); - if (client_ip_family != AF_UNSPEC) { - /* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>: */ - client_ip = tmp; - peer = get_word(&argument, ':'); + tmp2 = get_word(&argument, ':'); + if (NM_IN_STRSET(tmp2, + "none", + "off", + "dhcp", + "on" + "any", + "dhcp6", + "auto", + "auto6", + "ibft")) { + /* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|ibft} */ + iface_spec = tmp; + kind = tmp2; + } else { + /* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */ + 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, ':'); - } else { - iface_spec = tmp; + kind = get_word(&argument, ':'); } if (client_hostname && !nm_sd_hostname_is_valid(client_hostname, FALSE)) @@ -432,16 +460,12 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) reader->hostname = g_strdup(client_hostname); } - /* <ifname>:{none|off|dhcp|on|any|dhcp6|auto6|ibft} */ - - kind = get_word(&argument, ':'); - tmp = get_word(&argument, ':'); - dns_addr_family[0] = guess_ip_address_family(tmp); + 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] = guess_ip_address_family(dns[1]); + dns_addr_family[1] = get_ip_address_family(dns[1], FALSE); if (*argument) _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument); } else { @@ -461,6 +485,8 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) else connection = reader_get_default_connection(reader); + g_hash_table_add(reader->explicit_ip_connections, g_object_ref(connection)); + s_ip4 = nm_connection_get_setting_ip4_config(connection); s_ip6 = nm_connection_get_setting_ip6_config(connection); @@ -506,9 +532,8 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) _LOGW(LOGD_CORE, "Invalid address '%s': %s", client_ip, error->message); g_clear_error(&error); } - } else { - _LOGW(LOGD_CORE, "Unrecognized address: %s", client_ip); - } + } else + nm_assert_not_reached(); if (address) { switch (client_ip_family) { @@ -531,7 +556,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) nm_setting_ip_config_add_address(s_ip6, address); break; default: - _LOGW(LOGD_CORE, "Unknown address family: %s", client_ip); + nm_assert_not_reached(); break; } nm_ip_address_unref(address); @@ -543,7 +568,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) 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, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED, NULL); } if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) { @@ -618,22 +643,16 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) _LOGW(LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer); if (gateway_ip && *gateway_ip) { - int addr_family = guess_ip_address_family(gateway_ip); - - if (nm_utils_ipaddr_is_valid(addr_family, gateway_ip)) { - switch (addr_family) { - 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, "Unknown address family: %s", gateway_ip); - break; - } - } else { + 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; } } @@ -842,6 +861,9 @@ reader_parse_vlan(Reader *reader, char *argument) 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 @@ -941,7 +963,7 @@ reader_add_nameservers(Reader *reader, GPtrArray *nameservers) for (i = 0; i < nameservers->len; i++) { ns = nameservers->pdata[i]; - addr_family = guess_ip_address_family(ns); + addr_family = get_ip_address_family(ns, FALSE); if (addr_family == AF_UNSPEC) { _LOGW(LOGD_CORE, "Unknown address family: %s", ns); continue; @@ -1085,6 +1107,33 @@ nmi_cmdline_reader_parse(const char *sysfs_dir, const char *const *argv, char ** } } + 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) { diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c index 80b2e5f9..b7ce4671 100644 --- a/src/initrd/nmi-ibft-reader.c +++ b/src/initrd/nmi-ibft-reader.c @@ -165,9 +165,9 @@ ip_setting_add_from_block(GHashTable *nic, NMConnection *connection, GError **er NULL); } - family = guess_ip_address_family(s_ipaddr); + family = get_ip_address_family(s_ipaddr, FALSE); if (family == AF_UNSPEC) - family = guess_ip_address_family(s_gateway); + family = get_ip_address_family(s_gateway, FALSE); switch (family) { case AF_INET: diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index c3511332..14a83c08 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -80,6 +80,116 @@ test_auto(void) } 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; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 1); + g_assert_cmpstr(hostname, ==, "host1"); + + connection = g_hash_table_lookup(connections, "default_connection"); + g_assert(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_hashtable GHashTable *connections = NULL; + NMConnection * connection; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 1); + g_assert_cmpstr(hostname, ==, NULL); + + connection = g_hash_table_lookup(connections, "default_connection"); + g_assert(connection); + 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), ==, "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_if_auto_with_mtu(void) { gs_unref_hashtable GHashTable *connections = NULL; @@ -235,7 +345,9 @@ test_if_ip4_manual(void) 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_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"); @@ -305,6 +417,52 @@ test_if_ip6_manual(void) } 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; + gs_free char * hostname = NULL; + 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 = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, G_N_ELEMENTS(conn_expected)); + g_assert_cmpstr(hostname, ==, NULL); + + for (int i = 0; i < G_N_ELEMENTS(conn_expected); ++i) { + connection = g_hash_table_lookup(connections, conn_expected[i].name); + g_assert(connection); + 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; @@ -353,8 +511,9 @@ static void test_multiple_merge(void) { gs_unref_hashtable GHashTable *connections = NULL; - const char *const *ARGV = NM_MAKE_STRV("ip=192.0.2.2:::::eth0", "ip=[2001:db8::2]:::56::eth0"); - NMConnection * connection; + const char *const * ARGV = + NM_MAKE_STRV("ip=192.0.2.2/16:::::eth0", "ip=[2001:db8::2]:::56::eth0"); + NMConnection * connection; NMSettingConnection *s_con; NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; @@ -389,6 +548,7 @@ test_multiple_merge(void) 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); @@ -454,7 +614,7 @@ test_bootdev(void) connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); + g_assert_cmpint(g_hash_table_size(connections), ==, 3); g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "ens3"); @@ -483,6 +643,18 @@ test_bootdev(void) 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"); + g_assert(connection); + 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 @@ -729,7 +901,9 @@ test_bond_ip(void) 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_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)); @@ -1168,6 +1342,229 @@ test_team(void) } 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; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 2); + g_assert_cmpstr(hostname, ==, NULL); + + /* VLAN eth0.100 */ + connection = g_hash_table_lookup(connections, "eth0.100"); + g_assert(connection); + 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"); + g_assert(connection); + 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; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 2); + g_assert_cmpstr(hostname, ==, NULL); + + /* VLAN eth0.100 */ + connection = g_hash_table_lookup(connections, "eth0.100"); + g_assert(connection); + 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"); + g_assert(connection); + 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; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 4); + g_assert_cmpstr(hostname, ==, NULL); + + /* VLAN vlan1 */ + connection = g_hash_table_lookup(connections, "vlan1"); + g_assert(connection); + 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"); + g_assert(connection); + 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"); @@ -1784,12 +2181,15 @@ 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/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_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); @@ -1799,6 +2199,9 @@ main(int argc, char **argv) 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); diff --git a/src/nm-config.c b/src/nm-config.c index 1d751343..8f46661d 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -884,6 +884,7 @@ static const ConfigGroup config_groups[] = { NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS, 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, NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE, NM_CONFIG_KEYFILE_KEY_STOP_MATCH, ), }, diff --git a/src/nm-config.h b/src/nm-config.h index 698482e3..9f866f29 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -85,7 +85,9 @@ #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_CARRIER_WAIT_TIMEOUT "carrier-wait-timeout" +#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_MATCH_DEVICE "match-device" #define NM_CONFIG_KEYFILE_KEY_STOP_MATCH "stop-match" diff --git a/src/nm-l3cfg.c b/src/nm-l3cfg.c index 36aaf0fd..7b1e6f22 100644 --- a/src/nm-l3cfg.c +++ b/src/nm-l3cfg.c @@ -605,8 +605,8 @@ _load_link(NML3Cfg *self, gboolean initial) gboolean nacd_changed; gboolean nacd_new_valid; gboolean nacd_old_valid; - const guint8 * nacd_old_addr; - const guint8 * nacd_new_addr; + const guint8 * nacd_old_addr = NULL; + const guint8 * nacd_new_addr = NULL; gboolean nacd_link_now_up; AcdData * acd_data; diff --git a/src/nm-manager.c b/src/nm-manager.c index a04ca0e6..46f81c7c 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2445,7 +2445,8 @@ _device_auth_done_fail_on_idle(gpointer user_data, GCancellable *cancellable) NMManagerDeviceAuthRequestFunc callback; gpointer callback_user_data; - nm_utils_user_data_unpack(&self, + nm_utils_user_data_unpack(user_data, + &self, &device, &context, &subject, @@ -2858,15 +2859,20 @@ recheck_assume_connection(NMManager *self, NMDevice *device) activation_type_assume = TRUE; if (generated) { + gs_unref_object NMConnection *con2 = NULL; + + con2 = nm_simple_connection_new_clone( + nm_settings_connection_get_connection(sett_conn)); + /* Reset the IPv4 setting to empty method=auto, regardless of what assumption guessed. */ - nm_connection_add_setting(nm_settings_connection_get_connection(sett_conn), + nm_connection_add_setting(con2, g_object_new(NM_TYPE_SETTING_IP4_CONFIG, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL)); nm_settings_connection_update(sett_conn, - NULL, + con2, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE diff --git a/src/nm-policy.c b/src/nm-policy.c index 60f5fb02..038b89cf 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -143,6 +143,11 @@ _dns_manager_set_ip_config(NMDnsManager * dns_manager, NMDnsIPConfigType ip_config_type, NMDevice * device) { + if (device && nm_device_sys_iface_state_is_external(device)) { + nm_dns_manager_set_ip_config(dns_manager, ip_config, NM_DNS_IP_CONFIG_TYPE_REMOVED); + return; + } + if (NM_IN_SET(ip_config_type, NM_DNS_IP_CONFIG_TYPE_DEFAULT, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) && device && nm_device_get_route_metric_default(nm_device_get_device_type(device)) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 94c3f0e8..5bb0b426 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -225,7 +225,8 @@ link_add_pre(NMPlatform *platform, const char *name, NMLinkType type, const void *address, - size_t address_len) + size_t address_len, + guint32 mtu) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform); NMFakePlatformLink * device; @@ -251,6 +252,7 @@ link_add_pre(NMPlatform *platform, link->ifindex = name ? ifindex : 0; link->type = type; link->kind = g_intern_string(nm_link_type_to_string(type)); + link->mtu = mtu; link->initialized = TRUE; if (name) strcpy(link->name, name); @@ -285,6 +287,7 @@ link_add(NMPlatform * platform, int parent, const void * address, size_t address_len, + guint32 mtu, gconstpointer extra_data, const NMPlatformLink **out_link) { @@ -300,7 +303,7 @@ link_add(NMPlatform * platform, NMPObject * dev_obj; NMPObject * dev_lnk = NULL; - device = link_add_pre(platform, name, type, address, address_len); + device = link_add_pre(platform, name, type, address, address_len, mtu); g_assert(device); @@ -326,7 +329,7 @@ link_add(NMPlatform * platform, case NM_LINK_TYPE_VETH: veth_peer = extra_data; g_assert(veth_peer); - device_veth = link_add_pre(platform, veth_peer, type, NULL, 0); + device_veth = link_add_pre(platform, veth_peer, type, NULL, 0, 0); break; case NM_LINK_TYPE_VLAN: { @@ -401,7 +404,7 @@ link_add_one(NMPlatform *platform, NMPCacheOpsType cache_op; int ifindex; - device = link_add_pre(platform, name, NM_LINK_TYPE_VLAN, NULL, 0); + device = link_add_pre(platform, name, NM_LINK_TYPE_VLAN, NULL, 0, 0); ifindex = NMP_OBJECT_CAST_LINK(device->obj)->ifindex; @@ -1313,10 +1316,10 @@ nm_fake_platform_setup(void) nm_platform_setup(platform); - link_add(platform, NM_LINK_TYPE_LOOPBACK, "lo", 0, NULL, 0, NULL, NULL); - link_add(platform, NM_LINK_TYPE_ETHERNET, "eth0", 0, NULL, 0, NULL, NULL); - link_add(platform, NM_LINK_TYPE_ETHERNET, "eth1", 0, NULL, 0, NULL, NULL); - link_add(platform, NM_LINK_TYPE_ETHERNET, "eth2", 0, NULL, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_LOOPBACK, "lo", 0, NULL, 0, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_ETHERNET, "eth0", 0, NULL, 0, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_ETHERNET, "eth1", 0, NULL, 0, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_ETHERNET, "eth2", 0, NULL, 0, 0, NULL, NULL); } static void diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 3fa70bbc..b377c85e 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -7341,6 +7341,7 @@ link_add(NMPlatform * platform, int parent, const void * address, size_t address_len, + guint32 mtu, gconstpointer extra_data, const NMPlatformLink **out_link) { @@ -7368,6 +7369,9 @@ link_add(NMPlatform * platform, 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; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index d1ff6fbc..7969206c 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1230,11 +1230,13 @@ nm_platform_link_add(NMPlatform * self, 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]; @@ -1254,6 +1256,7 @@ nm_platform_link_add(NMPlatform * self, "\"%s\"" /* name */ "%s%s" /* parent */ "%s%s" /* address */ + "%s%s" /* mtu */ "%s" /* extra_data */ "", nm_link_type_to_string(type), @@ -1263,6 +1266,8 @@ nm_platform_link_add(NMPlatform * self, 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); @@ -1345,7 +1350,8 @@ nm_platform_link_add(NMPlatform * self, buf; })); - return klass->link_add(self, type, name, parent, address, address_len, extra_data, out_link); + return klass + ->link_add(self, type, name, parent, address, address_len, mtu, extra_data, out_link); } /** diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index c7b8017a..a1314000 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1085,6 +1085,7 @@ typedef struct { 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); @@ -1532,6 +1533,7 @@ int nm_platform_link_add(NMPlatform * self, int parent, const void * address, size_t address_len, + guint32 mtu, gconstpointer extra_data, const NMPlatformLink **out_link); @@ -1541,13 +1543,13 @@ nm_platform_link_veth_add(NMPlatform * self, const char * peer, const NMPlatformLink **out_link) { - return nm_platform_link_add(self, NM_LINK_TYPE_VETH, name, 0, NULL, 0, peer, 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, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_DUMMY, name, 0, NULL, 0, 0, NULL, out_link); } static inline int @@ -1555,6 +1557,7 @@ 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) { @@ -1564,6 +1567,7 @@ nm_platform_link_bridge_add(NMPlatform * self, 0, address, address_len, + mtu, props, out_link); } @@ -1571,19 +1575,19 @@ nm_platform_link_bridge_add(NMPlatform * self, 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, NULL, 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, NULL, 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, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_WIREGUARD, name, 0, NULL, 0, 0, NULL, out_link); } static inline int @@ -1602,6 +1606,7 @@ nm_platform_link_gre_add(NMPlatform * self, 0, address, address_len, + 0, props, out_link); } @@ -1612,7 +1617,7 @@ nm_platform_link_sit_add(NMPlatform * self, const NMPlatformLnkSit *props, const NMPlatformLink ** out_link) { - return nm_platform_link_add(self, NM_LINK_TYPE_SIT, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_SIT, name, 0, NULL, 0, 0, props, out_link); } static inline int @@ -1632,6 +1637,7 @@ nm_platform_link_vlan_add(NMPlatform * self, parent, NULL, 0, + 0, &((NMPlatformLnkVlan){ .id = vlanid, .flags = vlanflags, @@ -1645,7 +1651,7 @@ nm_platform_link_vrf_add(NMPlatform * self, const NMPlatformLnkVrf *props, const NMPlatformLink ** out_link) { - return nm_platform_link_add(self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, 0, props, out_link); } static inline int @@ -1654,7 +1660,7 @@ nm_platform_link_vxlan_add(NMPlatform * self, const NMPlatformLnkVxlan *props, const NMPlatformLink ** out_link) { - return nm_platform_link_add(self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, 0, props, out_link); } static inline int @@ -1663,7 +1669,15 @@ nm_platform_link_6lowpan_add(NMPlatform * self, int parent, const NMPlatformLink **out_link) { - return nm_platform_link_add(self, NM_LINK_TYPE_6LOWPAN, name, parent, NULL, 0, NULL, out_link); + return nm_platform_link_add(self, + NM_LINK_TYPE_6LOWPAN, + name, + parent, + NULL, + 0, + 0, + NULL, + out_link); } static inline int @@ -1675,7 +1689,7 @@ nm_platform_link_ip6tnl_add(NMPlatform * self, 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, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_IP6TNL, name, 0, NULL, 0, 0, props, out_link); } static inline int @@ -1695,6 +1709,7 @@ nm_platform_link_ip6gre_add(NMPlatform * self, 0, address, address_len, + 0, props, out_link); } @@ -1707,7 +1722,7 @@ nm_platform_link_ipip_add(NMPlatform * self, { g_return_val_if_fail(props, -NME_BUG); - return nm_platform_link_add(self, NM_LINK_TYPE_IPIP, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_IPIP, name, 0, NULL, 0, 0, props, out_link); } static inline int @@ -1720,7 +1735,15 @@ nm_platform_link_macsec_add(NMPlatform * self, 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, props, out_link); + return nm_platform_link_add(self, + NM_LINK_TYPE_MACSEC, + name, + parent, + NULL, + 0, + 0, + props, + out_link); } static inline int @@ -1739,6 +1762,7 @@ nm_platform_link_macvlan_add(NMPlatform * self, parent, NULL, 0, + 0, props, out_link); } diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index e305357a..fb430046 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1534,7 +1534,7 @@ nmtstp_link_bridge_add(NMPlatform * platform, } if (!pllink) { - r = nm_platform_link_bridge_add(platform, name, NULL, 0, lnk, &pllink); + r = nm_platform_link_bridge_add(platform, name, NULL, 0, 0, lnk, &pllink); } _assert_pllink(platform, r == 0, pllink, name, NM_LINK_TYPE_BRIDGE); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 829abcc9..5fd67ec4 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -101,6 +101,7 @@ software_add(NMLinkType link_type, const char *name) name, NULL, 0, + 0, &nm_platform_lnk_bridge_default, NULL)); case NM_LINK_TYPE_BOND: @@ -131,6 +132,7 @@ software_add(NMLinkType link_type, const char *name) PARENT_NAME, NULL, 0, + 0, &nm_platform_lnk_bridge_default, NULL))) accept_signal(parent_added); @@ -581,6 +583,7 @@ test_bridge_addr(void) DEVICE_NAME, addr, sizeof(addr), + 0, &nm_platform_lnk_bridge_default, &plink))); g_assert(plink); diff --git a/src/settings/plugins/ifcfg-rh/meson.build b/src/settings/plugins/ifcfg-rh/meson.build index e193ff96..10b93d0a 100644 --- a/src/settings/plugins/ifcfg-rh/meson.build +++ b/src/settings/plugins/ifcfg-rh/meson.build @@ -18,6 +18,7 @@ libnmdbus_ifcfg_rh = static_library( name, sources: dbus_sources, dependencies: glib_dep, + c_args: introspection_extra_cflags, ) core_sources = files( |