diff options
| author | Michael Biebl <biebl@debian.org> | 2020-06-29 22:15:58 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-06-29 22:15:58 +0200 |
| commit | 10ae7d8cd706062742d0cdb1803d49909aef9e06 (patch) | |
| tree | cb89e8b475cec18f22b1abfe45f1d63da7e3f440 /src | |
| parent | a54ac63bbf9b2c71026ac9028a8ffaf186cf3c82 (diff) | |
New upstream version 1.25.91 upstream/1.25.91
Diffstat (limited to 'src')
20 files changed, 400 insertions, 127 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 63fa5a5c..90178b68 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -6353,85 +6353,13 @@ check_connection_compatible (NMDevice *self, NMConnection *connection, GError ** return FALSE; } - { - const char *const*proc_cmdline; - gboolean pos_patterns = FALSE; - guint i; - - patterns = nm_setting_match_get_kernel_command_lines (s_match, &num_patterns); - proc_cmdline = nm_utils_proc_cmdline_split (); - - for (i = 0; i < num_patterns; i++) { - const char *patterns_i = patterns[i]; - const char *const*proc_cmdline_i; - gboolean negative = FALSE; - gboolean found = FALSE; - const char *equal; - - if (patterns_i[0] == '!') { - ++patterns_i; - negative = TRUE; - } else - pos_patterns = TRUE; - - equal = strchr (patterns_i, '='); - - proc_cmdline_i = proc_cmdline; - while (*proc_cmdline_i) { - if (equal) { - /* if pattern contains = compare full key=value */ - found = nm_streq (*proc_cmdline_i, patterns_i); - } else { - gsize l = strlen (patterns_i); - - /* otherwise consider pattern as key only */ - if ( strncmp (*proc_cmdline_i, patterns_i, l) == 0 - && NM_IN_SET ((*proc_cmdline_i)[l], '\0', '=')) - found = TRUE; - } - if ( found - && negative) { - /* first negative match */ - nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "device does not satisfy match.kernel-command-line property %s", - patterns[i]); - return FALSE; - } - proc_cmdline_i++; - } - - /* FIXME(release-blocker): match.interface-name and match.driver have the meaning, - * that any of the matches may yield success. For match.kernel-command-line, we - * do here that all must match. This inconsistency is undesired. - * - * 1) improve gtk-doc documentation explaining how these options match. - * - * 2) possibly unify the behavior so that kernel-command-line behaves like other - * matches (and ANY may match). Note that this would be contrary to systemd's - * Conditions, which by default requires that ALL conditions match (AND). We - * should be consistent within our match options, and not with systemd here. - * - * 2b) Note that systemd supports special token like "=|", to indicate that - * ANY behavior. If we want, we could also introduce two special prefixes - * "&..." and "|...", to support either. It's slightly complicated how - * these work in combinations with "!". - * Unless we fully decide what we do about this, NMSettingMatch.verify() should - * reject matches that start with '&' or '|', because these will be reserved for - * future use. - * - * 3) while fixing this, this code should move to a separate function so we - * can unit test the match of kernel command lines. - */ - if ( pos_patterns - && !found) { - /* positive patterns configured but no match */ - nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "device does not satisfy any match.kernel-command-line property %s...", - patterns[0]); - return FALSE; - } - } - } + patterns = nm_setting_match_get_kernel_command_lines (s_match, &num_patterns); + if ( num_patterns > 0 + && !nm_utils_kernel_cmdline_match_check (nm_utils_proc_cmdline_split (), + patterns, + num_patterns, + error)) + return FALSE; device_driver = nm_device_get_driver (self); patterns = nm_setting_match_get_drivers (s_match, &num_patterns); @@ -10934,8 +10862,11 @@ act_stage3_ip_config_start (NMDevice *self, platform = nm_device_get_platform (self); if (ifindex > 0) { + gs_unref_object NMIP6Config *config = nm_device_ip6_config_new (self); + nm_platform_ip_route_flush (platform, AF_INET6, ifindex); nm_platform_ip_address_flush (platform, AF_INET6, ifindex); + nm_device_set_ip_config (self, AF_INET6, (NMIPConfig *) config, FALSE, NULL); } } else { gboolean ipv6ll_handle_old = priv->ipv6ll_handle; diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 7513b4c9..69e5e56d 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -464,7 +464,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) 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, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); } if (nm_setting_ip_config_get_num_addresses (s_ip4) == 0) { @@ -479,7 +479,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) 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_IGNORE, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); } } else if (nm_streq0 (kind, "dhcp6")) { diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 5379c3a3..11077055 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -186,11 +186,12 @@ 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::192.0.2.53", + "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; NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; NMIPAddress *ip_addr; gs_free char *hostname = NULL; @@ -219,6 +220,11 @@ test_if_ip4_manual (void) 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_AUTO); + g_assert (nm_setting_ip_config_get_may_fail (s_ip6)); + connection = g_hash_table_lookup (connections, "eth4"); g_assert (connection); nmtst_assert_connection_verifies_without_normalization (connection); @@ -237,6 +243,11 @@ test_if_ip4_manual (void) 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 @@ -1086,7 +1097,7 @@ test_bootif (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_IGNORE); + 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)); } @@ -1124,7 +1135,7 @@ test_bootif_hwtype (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_IGNORE); + 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"); diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 019d1e60..3950c3c3 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -1698,30 +1698,109 @@ nm_match_spec_join (GSList *specs) return g_string_free (str, FALSE); } +static void +_pattern_parse (const char *input, + const char **out_pattern, + gboolean *out_is_inverted, + gboolean *out_is_mandatory) +{ + gboolean is_inverted = FALSE; + gboolean is_mandatory = FALSE; + + if (input[0] == '&') { + input++; + is_mandatory = TRUE; + if (input[0] == '!') { + input++; + is_inverted = TRUE; + } + goto out; + } + + if (input[0] == '|') { + input++; + if (input[0] == '!') { + input++; + is_inverted = TRUE; + } + goto out; + } + + if (input[0] == '!') { + input++; + is_inverted = TRUE; + is_mandatory = TRUE; + goto out; + } + +out: + if (input[0] == '\\') + input++; + + *out_pattern = input; + *out_is_inverted = is_inverted; + *out_is_mandatory = is_mandatory; +} + gboolean nm_wildcard_match_check (const char *str, const char *const *patterns, guint num_patterns) { - gsize i, neg = 0; + gboolean has_optional = FALSE; + gboolean has_any_optional = FALSE; + guint i; for (i = 0; i < num_patterns; i++) { - if (patterns[i][0] == '!') { - neg++; - if (!str) - continue; - if (!fnmatch (patterns[i] + 1, str, 0)) + gboolean is_inverted; + gboolean is_mandatory; + gboolean match; + const char *p; + + _pattern_parse (patterns[i], &p, &is_inverted, &is_mandatory); + + match = (fnmatch (p, str, 0) == 0); + if (is_inverted) + match = !match; + + if (is_mandatory) { + if (!match) return FALSE; + } else { + has_any_optional = TRUE; + if (match) + has_optional = TRUE; } } - if (neg == num_patterns) - return TRUE; + return has_optional + || !has_any_optional; +} + +/*****************************************************************************/ - if (str) { - for (i = 0; i < num_patterns; i++) { - if ( patterns[i][0] != '!' - && !fnmatch (patterns[i], str, 0)) +static gboolean +_kernel_cmdline_match (const char *const*proc_cmdline, + const char *pattern) +{ + + if (proc_cmdline) { + gboolean has_equal = (!!strchr (pattern, '=')); + gsize pattern_len = strlen (pattern); + + for (; proc_cmdline[0]; proc_cmdline++) { + const char *c = proc_cmdline[0]; + + if (has_equal) { + /* if pattern contains '=' compare full key=value */ + if (nm_streq (c, pattern)) + return TRUE; + continue; + } + + /* otherwise consider pattern as key only */ + if ( strncmp (c, pattern, pattern_len) == 0 + && NM_IN_SET (c[pattern_len], '\0', '=')) return TRUE; } } @@ -1729,6 +1808,53 @@ nm_wildcard_match_check (const char *str, return FALSE; } +gboolean +nm_utils_kernel_cmdline_match_check (const char *const*proc_cmdline, + const char *const*patterns, + guint num_patterns, + GError **error) +{ + gboolean has_optional = FALSE; + gboolean has_any_optional = FALSE; + guint i; + + for (i = 0; i < num_patterns; i++) { + const char *element = patterns[i]; + gboolean is_inverted = FALSE; + gboolean is_mandatory = FALSE; + gboolean match; + const char *p; + + _pattern_parse (element, &p, &is_inverted, &is_mandatory); + + match = _kernel_cmdline_match (proc_cmdline, p); + if (is_inverted) + match = !match; + + if (is_mandatory) { + if (!match) { + nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "device does not satisfy match.kernel-command-line property %s", + patterns[i]); + return FALSE; + } + } else { + has_any_optional = TRUE; + if (match) + has_optional = TRUE; + } + } + + if ( !has_optional + && has_any_optional) { + nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "device does not satisfy any match.kernel-command-line property"); + return FALSE; + } + + return TRUE; +} + /*****************************************************************************/ char * @@ -2778,19 +2904,13 @@ nm_utils_proc_cmdline_split (void) again: proc_cmdline = g_atomic_pointer_get (&proc_cmdline_cached); if (G_UNLIKELY (!proc_cmdline)) { - gs_free const char **split = NULL; - - /* FIXME(release-blocker): support quotation, like systemd's proc_cmdline_extract_first(). - * For that, add a new NMUtilsStrsplitSetFlags flag. */ - split = nm_utils_strsplit_set_full (nm_utils_proc_cmdline (), - NM_ASCII_WHITESPACES, - NM_UTILS_STRSPLIT_SET_FLAGS_NONE); - proc_cmdline = split - ?: NM_PTRARRAY_EMPTY (const char *); - if (!g_atomic_pointer_compare_and_exchange (&proc_cmdline_cached, NULL, proc_cmdline)) + gs_strfreev char **split = NULL; + + split = nm_utils_strsplit_quoted (nm_utils_proc_cmdline ()); + if (!g_atomic_pointer_compare_and_exchange (&proc_cmdline_cached, NULL, (gpointer) split)) goto again; - g_steal_pointer (&split); + proc_cmdline = (const char *const*) g_steal_pointer (&split); } return proc_cmdline; diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index e30d7b36..fae7adbf 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -230,6 +230,11 @@ gboolean nm_wildcard_match_check (const char *str, const char *const *patterns, guint num_patterns); +gboolean nm_utils_kernel_cmdline_match_check (const char *const*proc_cmdline, + const char *const*patterns, + guint num_patterns, + GError **error); + /*****************************************************************************/ gboolean nm_utils_connection_has_default_route (NMConnection *connection, diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 0feb7b2c..62b41478 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -860,8 +860,26 @@ _nm_ip_config_merge_route_attributes (int addr_family, (dst) = (dflt); \ } G_STMT_END + 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; + + type = nm_utils_route_type_by_name (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); + } else + r->type_coerced = nm_platform_route_type_coerce (RTN_UNICAST); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0); - r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN)); + + if ( !table + && r->type_coerced == nm_platform_route_type_coerce (RTN_LOCAL)) + r->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL); + else + r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN)); if (addr_family == AF_INET) { guint8 scope; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index e2c45c88..710a6f91 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -3257,14 +3257,16 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only) rtm = nlmsg_data (nlh); /***************************************************************** - * only handle ~normal~ routes. + * only handle ~supported~ routes. *****************************************************************/ if (!NM_IN_SET (rtm->rtm_family, AF_INET, AF_INET6)) return NULL; - if (rtm->rtm_type != RTN_UNICAST) - return NULL; + if (!NM_IN_SET (rtm->rtm_type, + RTN_UNICAST, + RTN_LOCAL)) + return NULL; if (nlmsg_parse_arr (nlh, sizeof (struct rtmsg), @@ -4491,7 +4493,7 @@ _nl_msg_new_route (int nlmsg_type, .rtm_scope = is_v4 ? nm_platform_route_scope_inv (obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, - .rtm_type = RTN_UNICAST, + .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 diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index c023f435..c8b8c6e8 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -4518,8 +4518,12 @@ _ip_route_scope_inv_get_normalized (const NMPlatformIP4Route *route) * so that the default equals zero (~(RT_SCOPE_NOWHERE)). **/ if (route->scope_inv == 0) { - return nm_platform_route_scope_inv (!route->gateway - ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); + 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; } @@ -6079,6 +6083,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi 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_type[30]; 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]; @@ -6093,6 +6098,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi _to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev)); g_snprintf (buf, len, + "%s" /* type */ "%s" /* table */ "%s/%d" " via %s" @@ -6110,6 +6116,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi "%s" /* initrwnd */ "%s" /* mtu */ "", + route->type_coerced ? nm_sprintf_buf (str_type, "type %s ", nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), NULL, 0)) : "", route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "", s_network, route->plen, @@ -6152,6 +6159,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi 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]; @@ -6178,6 +6186,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi _to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev)); g_snprintf (buf, len, + "%s" /* type */ "%s" /* table */ "%s/%d" " via %s" @@ -6195,6 +6204,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi "%s" /* mtu */ "%s" /* pref */ "", + route->type_coerced ? nm_sprintf_buf (str_type, "type %s ", nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), NULL, 0)) : "", route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "", s_network, route->plen, @@ -7274,6 +7284,7 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: nm_hash_update_vals (h, + obj->type_coerced, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), nm_utils_ip4_address_clear_host_address (obj->network, obj->plen), obj->plen, @@ -7301,6 +7312,7 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: nm_hash_update_vals (h, + obj->type_coerced, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), obj->ifindex, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen), @@ -7327,6 +7339,7 @@ nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRo break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: nm_hash_update_vals (h, + obj->type_coerced, obj->table_coerced, obj->ifindex, obj->network, @@ -7369,6 +7382,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route 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), @@ -7392,6 +7406,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: + NM_CMP_FIELD (a, b, type_coerced); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE), nm_platform_route_table_uncoerce (b->table_coerced, TRUE)); @@ -7454,6 +7469,7 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: nm_hash_update_vals (h, + obj->type_coerced, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), *nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen), obj->plen, @@ -7466,6 +7482,7 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: nm_hash_update_vals (h, + obj->type_coerced, nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), obj->ifindex, *nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen), @@ -7493,6 +7510,7 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: nm_hash_update_vals (h, + obj->type_coerced, obj->table_coerced, obj->ifindex, obj->network, @@ -7537,11 +7555,13 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route 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); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE), nm_platform_route_table_uncoerce (b->table_coerced, TRUE)); diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index aa3551a6..3e6ef84c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -468,6 +468,13 @@ typedef union { * 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 { @@ -1285,6 +1292,39 @@ _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); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index f074ca69..19debfb5 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -328,13 +328,13 @@ test_ip6_route (void) g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, pref_src, 128, in6addr_any, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0)); - accept_signals (route_added, 0, 1); + accept_signals (route_added, 0, 2); _wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 200, ifindex, 1, &pref_src); /* Add route to gateway */ nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, in6addr_any, metric, mss); - accept_signal (route_added); + accept_signals (route_added, 0, 3); /* Add route */ g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 5899b079..0a1e7b47 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1996,11 +1996,10 @@ nm_settings_update_connection (NMSettings *self, */ device = nm_settings_connection_default_wired_get_device (sett_conn); if (device) { + nm_assert (cur_in_memory); - nm_assert (!NM_FLAGS_ANY (nm_settings_connection_get_flags (sett_conn), - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED - | NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)); + nm_assert (NM_FLAGS_HAS (nm_settings_connection_get_flags (sett_conn), + NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)); default_wired_clear_tag (self, device, sett_conn, FALSE); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index d65ae555..1a9df92c 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -800,6 +800,7 @@ typedef struct { union { guint8 uint8; guint32 uint32; + const char *str; struct { guint32 uint32; bool lock:1; @@ -815,6 +816,7 @@ typedef struct { enum { /* route attributes */ + PARSE_LINE_ATTR_ROUTE_TYPE, PARSE_LINE_ATTR_ROUTE_TABLE, PARSE_LINE_ATTR_ROUTE_SRC, PARSE_LINE_ATTR_ROUTE_FROM, @@ -844,6 +846,7 @@ enum { #define PARSE_LINE_TYPE_IFNAME 'i' #define PARSE_LINE_TYPE_FLAG 'f' #define PARSE_LINE_TYPE_ROUTE_SCOPE 'S' +#define PARSE_LINE_TYPE_STRING 's' /** * parse_route_line: @@ -875,6 +878,8 @@ parse_route_line (const char *line, GError **error) { static const ParseLineInfo parse_infos[] = { + [PARSE_LINE_ATTR_ROUTE_TYPE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TYPE, + .type = PARSE_LINE_TYPE_STRING, }, [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, .type = PARSE_LINE_TYPE_UINT32, }, [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, @@ -1010,6 +1015,23 @@ parse_route_line (const char *line, } } + p_info = &parse_infos[PARSE_LINE_ATTR_ROUTE_TYPE]; + p_data = &parse_datas[PARSE_LINE_ATTR_ROUTE_TYPE]; + if ( !p_data->has + && NM_IN_STRSET (w, + "local", + "unicast", + "broadcast" + "multicast", + "throw", + "unreachable", + "prohibit", + "blackhole", + "nat")) { + p_data->has = TRUE; + goto parse_line_type_string; + } + /* "to" is also accepted unqualified... (once) */ p_info = &parse_infos[PARSE_LINE_ATTR_ROUTE_TO]; p_data = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO]; @@ -1160,6 +1182,15 @@ parse_line_type_addr_with_prefix: i_words++; goto next; +parse_line_type_string: + s = words[i_words]; + if (!s) + goto err_word_missing_argument; + + p_data->v.str = s; + i_words++; + goto next; + err_word_missing_argument: g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing argument for \"%s\"", w); @@ -1253,13 +1284,18 @@ next: p_info->key, g_variant_new_boolean (TRUE)); break; + case PARSE_LINE_TYPE_STRING: + nm_ip_route_set_attribute (route, + p_info->key, + g_variant_new_string (p_data->v.str)); + break; default: nm_assert_not_reached (); break; } } - nm_assert (_nm_ip_route_attribute_validate_all (route)); + nm_assert (_nm_ip_route_attribute_validate_all (route, NULL)); NM_SET_OUT (out_route, g_steal_pointer (&route)); return 0; @@ -2479,7 +2515,7 @@ make_tc_setting (shvarFile *ifcfg) NMTCTfilter *tfilter = NULL; gs_free char *value_to_free = NULL; const char *value = NULL; - GError *local = NULL; + gs_free_error GError *local = NULL; value = svGetValueStr (ifcfg, numbered_tag (tag, "FILTER", i), &value_to_free); if (!value) diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 199e8e4e..e6526944 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -2099,7 +2099,15 @@ get_route_attributes_string (NMIPRoute *route, int family) str = g_string_new (""); + attr = nm_ip_route_get_attribute (route, NM_IP_ROUTE_ATTRIBUTE_TYPE); + if ( attr + && nm_ip_route_attribute_validate (NM_IP_ROUTE_ATTRIBUTE_TYPE, attr, family, NULL, NULL)) + g_string_append_printf (str, "%s ", g_variant_get_string (attr, NULL)); + for (i = 0; i < len; i++) { + if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TYPE)) + continue; + attr = nm_ip_route_get_attribute (route, names[i]); if (!nm_ip_route_attribute_validate (names[i], attr, family, NULL, NULL)) diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index 5d02c62e..9c05417e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -13,3 +13,7 @@ NETMASK2=255.255.255.255 GATEWAY2=192.168.1.8 METRIC2=3 OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14 scope link" + +ADDRESS3=1.2.3.4 +NETMASK3=255.255.255.255 +OPTIONS3="local scope host" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy index faa247d8..1fef7e97 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy @@ -6,3 +6,4 @@ 43.53.0.0/16 metric 3 via 7.7.7.7 dev eth2 cwnd 14 mtu lock 9000 initrwnd 20 window lock 10000 initcwnd lock 42 src 1.2.3.4 7.7.7.8/32 via (null) metric 18 +local 1.2.3.4 diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index a5025f3b..40d1bb8c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -1323,7 +1323,7 @@ test_read_wired_static_routes (void) 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), ==, 3); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 4); ip4_route = nm_setting_ip_config_get_route (s_ip4, 0); g_assert (ip4_route); @@ -1367,6 +1367,13 @@ test_read_wired_static_routes (void) nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, TRUE); nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 253); + ip4_route = nm_setting_ip_config_get_route (s_ip4, 3); + g_assert (ip4_route); + g_assert_cmpstr (nm_ip_route_get_dest (ip4_route), ==, "1.2.3.4"); + 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); } @@ -1402,7 +1409,7 @@ test_read_wired_static_routes_legacy (void) 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); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 5); /* Route #1 */ ip4_route = nm_setting_ip_config_get_route (s_ip4, 0); @@ -1443,6 +1450,13 @@ test_read_wired_static_routes_legacy (void) g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, NULL); g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 18); + + /* Route #5 */ + ip4_route = nm_setting_ip_config_get_route (s_ip4, 4); + 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); } diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection index 1e62f4b3..f9ccc003 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection +++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection @@ -36,7 +36,9 @@ routes9=1.1.1.9/19,0.0.0.0,0 route10=1.1.1.10/21,,0 routes10=1.1.1.10/20,,0 routes11=1.1.1.11/21,,21 -routes11_options=cwnd=10,lock-cwnd=true,mtu=1430,src=7.7.7.7 +routes11_options=cwnd=10,lock-cwnd=true,mtu=1430,src=7.7.7.7,type=unicast +routes12=1.2.3.4/32 +routes12_options=type=local address30=1.2.3.30/24 addresses30=1.2.3.30/25 addresses31=1.2.3.31/25 diff --git a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c index 1a9482e5..98820272 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -274,7 +274,7 @@ test_read_valid_wired_connection (void) g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "2.3.4.6"); /* IPv4 routes */ - g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 13); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 14); check_ip_route (s_ip4, 0, "5.6.7.8", 32, NULL, -1); check_ip_route (s_ip4, 1, "1.2.3.0", 24, "2.3.4.8", 99); check_ip_route (s_ip4, 2, "1.1.1.2", 12, NULL, -1); @@ -288,6 +288,7 @@ test_read_valid_wired_connection (void) check_ip_route (s_ip4, 10, "1.1.1.10", 21, NULL, 0); check_ip_route (s_ip4, 11, "1.1.1.10", 20, NULL, 0); check_ip_route (s_ip4, 12, "1.1.1.11", 21, NULL, 21); + check_ip_route (s_ip4, 13, "1.2.3.4", 32, NULL, -1); /* Route attributes */ route = nm_setting_ip_config_get_route (s_ip4, 12); @@ -297,6 +298,12 @@ test_read_valid_wired_connection (void) nmtst_assert_route_attribute_uint32 (route, NM_IP_ROUTE_ATTRIBUTE_MTU, 1430); nmtst_assert_route_attribute_boolean (route, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, TRUE); nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_SRC, "7.7.7.7"); + nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_TYPE, "unicast"); + + route = nm_setting_ip_config_get_route (s_ip4, 13); + g_assert (route); + + nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_TYPE, "local"); s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 6bbeb1eb..3dda0fbf 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -3292,6 +3292,7 @@ dispose (GObject *object) g_clear_object (&priv->supplicant_manager); g_clear_object (&priv->dbus_connection); nm_clear_g_free (&priv->ifname); + nm_clear_g_free (&priv->driver); nm_assert (!priv->net_path); } diff --git a/src/tests/test-core.c b/src/tests/test-core.c index b90a8fac..099786ef 100644 --- a/src/tests/test-core.c +++ b/src/tests/test-core.c @@ -968,10 +968,17 @@ test_wildcard_match (void) do_test_wildcard_match ("b", TRUE, "!!a"); do_test_wildcard_match ("!a", FALSE, "!!a"); - do_test_wildcard_match ("\\", TRUE, "\\\\"); + do_test_wildcard_match ("\\", TRUE, "\\\\\\"); do_test_wildcard_match ("\\\\", FALSE, "\\\\"); do_test_wildcard_match ("", FALSE, "\\\\"); + do_test_wildcard_match ("\\a", TRUE, "\\\\\\a"); + do_test_wildcard_match ("b", TRUE, "&!a"); + do_test_wildcard_match ("a", FALSE, "&!a"); + do_test_wildcard_match ("!a", TRUE, "&\\!a"); + do_test_wildcard_match ("!a", TRUE, "|\\!a"); + do_test_wildcard_match ("!a", TRUE, "\\!a"); + do_test_wildcard_match ("name", FALSE, "name[123]"); do_test_wildcard_match ("name1", TRUE, "name[123]"); do_test_wildcard_match ("name2", TRUE, "name[123]"); @@ -979,6 +986,12 @@ test_wildcard_match (void) do_test_wildcard_match ("name4", FALSE, "name[123]"); do_test_wildcard_match ("[a]", TRUE, "\\[a\\]"); + + do_test_wildcard_match ("aa", FALSE, "!a*"); + do_test_wildcard_match ("aa", FALSE, "&!a*"); + do_test_wildcard_match ("aa", FALSE, "|!a*"); + do_test_wildcard_match ("aa", FALSE, "&!a*", "aa"); + do_test_wildcard_match ("aa", TRUE, "|!a*", "aa"); } static NMConnection * @@ -2118,6 +2131,46 @@ test_nm_utils_dhcp_client_id_systemd_node_specific (gconstpointer test_data) /*****************************************************************************/ static void +_kernel_cmdline_match (gboolean expected_match, + const char *const*proc_cmdline, + const char *const*patterns) +{ + gs_free_error GError *error = NULL; + GError **p_error = nmtst_get_rand_bool () ? &error : NULL; + gboolean match; + + nm_assert (proc_cmdline); + nm_assert (patterns); + + match = nm_utils_kernel_cmdline_match_check (proc_cmdline, patterns, NM_PTRARRAY_LEN (patterns), p_error); + if (expected_match) + nmtst_assert_success (match, error); + else { + g_assert (!p_error || error); + g_assert (!match); + } +} + +static void +test_kernel_cmdline_match_check (void) +{ + _kernel_cmdline_match (TRUE, NM_MAKE_STRV (""), NM_MAKE_STRV ("")); + _kernel_cmdline_match (FALSE, NM_MAKE_STRV (""), NM_MAKE_STRV ("a")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a"), NM_MAKE_STRV ("a")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a=b"), NM_MAKE_STRV ("a")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a=b", "b"), NM_MAKE_STRV ("a", "b")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a=b", "b"), NM_MAKE_STRV ("&a", "&b")); + _kernel_cmdline_match (FALSE, NM_MAKE_STRV ("a=b", "bc"), NM_MAKE_STRV ("&a", "&b")); + _kernel_cmdline_match (FALSE, NM_MAKE_STRV ("a=b", "b"), NM_MAKE_STRV ("&a", "&b", "c")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a=b", "b"), NM_MAKE_STRV ("&a", "&b", "b", "c")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a=b", "b", "c=dd"), NM_MAKE_STRV ("&a", "&b", "c")); + _kernel_cmdline_match (FALSE, NM_MAKE_STRV ("a", "b"), NM_MAKE_STRV ("a", "&c")); + _kernel_cmdline_match (TRUE, NM_MAKE_STRV ("a", "b"), NM_MAKE_STRV ("a", "|\\c")); +} + +/*****************************************************************************/ + +static void test_connectivity_state_cmp (void) { NMConnectivityState a; @@ -2229,6 +2282,7 @@ main (int argc, char **argv) g_test_add_data_func ("/general/nm_utils_dhcp_client_id_systemd_node_specific/1", GINT_TO_POINTER (1), test_nm_utils_dhcp_client_id_systemd_node_specific); g_test_add_func ("/core/general/test_connectivity_state_cmp", test_connectivity_state_cmp); + g_test_add_func ("/core/general/test_kernel_cmdline_match_check", test_kernel_cmdline_match_check); return g_test_run (); } |