diff options
| author | Michael Biebl <biebl@debian.org> | 2017-01-23 23:34:56 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2017-01-23 23:34:56 +0100 |
| commit | d462f64d6044349b0a4e3581cf2c97bbab7aec97 (patch) | |
| tree | 0743acb1a191ce83b5722d77aeb896c6c0cdd952 /src/nm-core-utils.c | |
| parent | 58f8be580039b0575b197b9573a1c92745d96d30 (diff) | |
New upstream version 1.5.91 upstream/1.5.91
Diffstat (limited to 'src/nm-core-utils.c')
| -rw-r--r-- | src/nm-core-utils.c | 390 |
1 files changed, 207 insertions, 183 deletions
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 219f309b..79f9e117 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -1213,169 +1213,44 @@ nm_utils_read_link_absolute (const char *link_file, GError **error) #define MATCH_TAG_CONFIG_NM_VERSION_MAX "nm-version-max:" #define MATCH_TAG_CONFIG_ENV "env:" -#define _spec_has_prefix(pspec, tag) \ - ({ \ - const char **_spec = (pspec); \ - gboolean _has = FALSE; \ - \ - if (!g_ascii_strncasecmp (*_spec, (""tag), NM_STRLEN (tag))) { \ - *_spec += NM_STRLEN (tag); \ - _has = TRUE; \ - } \ - _has; \ - }) - -static const char * -_match_except (const char *spec_str, gboolean *out_except) -{ - if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, NM_STRLEN (EXCEPT_TAG))) { - spec_str += NM_STRLEN (EXCEPT_TAG); - *out_except = TRUE; - } else - *out_except = FALSE; - return spec_str; -} - -NMMatchSpecMatchType -nm_match_spec_device_type (const GSList *specs, const char *device_type) -{ - const GSList *iter; - NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH; - - if (!device_type || !*device_type) - return NM_MATCH_SPEC_NO_MATCH; - - for (iter = specs; iter; iter = g_slist_next (iter)) { - const char *spec_str = iter->data; - gboolean except; - - if (!spec_str || !*spec_str) - continue; - - spec_str = _match_except (spec_str, &except); - - if (g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)) != 0) - continue; - - spec_str += NM_STRLEN (DEVICE_TYPE_TAG); - if (strcmp (spec_str, device_type) == 0) { - if (except) - return NM_MATCH_SPEC_NEG_MATCH; - match = NM_MATCH_SPEC_MATCH; - } - } - return match; -} - -NMMatchSpecMatchType -nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) -{ - const GSList *iter; - NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH; - gsize hwaddr_len = 0; - guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX]; - - nm_assert (nm_utils_hwaddr_valid (hwaddr, -1)); - - for (iter = specs; iter; iter = g_slist_next (iter)) { - const char *spec_str = iter->data; - gboolean except; - - if (!spec_str || !*spec_str) - continue; - - spec_str = _match_except (spec_str, &except); - - if ( !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG)) - || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG)) - || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG))) - continue; - - if (!g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG))) - spec_str += NM_STRLEN (MAC_TAG); - else if (except) - continue; - - if (G_UNLIKELY (hwaddr_len == 0)) { - if (!_nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, sizeof (hwaddr_bin), &hwaddr_len)) - g_return_val_if_reached (NM_MATCH_SPEC_NO_MATCH); - } - - if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len)) { - if (except) - return NM_MATCH_SPEC_NEG_MATCH; - match = NM_MATCH_SPEC_MATCH; - } - } - return match; -} - -NMMatchSpecMatchType -nm_match_spec_interface_name (const GSList *specs, const char *interface_name) -{ - const GSList *iter; - NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH; - - g_return_val_if_fail (interface_name != NULL, NM_MATCH_SPEC_NO_MATCH); - - for (iter = specs; iter; iter = g_slist_next (iter)) { - const char *spec_str = iter->data; - gboolean use_pattern = FALSE; - gboolean except; - - if (!spec_str || !*spec_str) - continue; - - spec_str = _match_except (spec_str, &except); - - if ( !g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG)) - || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG)) - || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG))) - continue; - - if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))) { - spec_str += NM_STRLEN (INTERFACE_NAME_TAG); - if (spec_str[0] == '=') - spec_str += 1; - else { - if (spec_str[0] == '~') - spec_str += 1; - use_pattern=TRUE; - } - } else if (except) - continue; - - if ( !strcmp (spec_str, interface_name) - || (use_pattern && g_pattern_match_simple (spec_str, interface_name))) { - if (except) - return NM_MATCH_SPEC_NEG_MATCH; - match = NM_MATCH_SPEC_MATCH; - } - } - return match; -} - -#define BUFSIZE 10 +typedef struct { + const char *interface_name; + const char *device_type; + struct { + const char *value; + gboolean is_parsed; + guint len; + guint8 bin[NM_UTILS_HWADDR_LEN_MAX]; + } hwaddr; + struct { + const char *value; + gboolean is_parsed; + guint32 a; + guint32 b; + guint32 c; + } s390_subchannels; +} MatchDeviceData; static gboolean -parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c) +match_device_s390_subchannels_parse (const char *s390_subchannels, guint32 *a, guint32 *b, guint32 *c) { + const int BUFSIZE = 10; long unsigned int tmp; char buf[BUFSIZE + 1]; - const char *p = subchannels; + const char *p = s390_subchannels; int i = 0; char *pa = NULL, *pb = NULL, *pc = NULL; - g_return_val_if_fail (subchannels != NULL, FALSE); - g_return_val_if_fail (a != NULL, FALSE); - g_return_val_if_fail (*a == 0, FALSE); - g_return_val_if_fail (b != NULL, FALSE); - g_return_val_if_fail (*b == 0, FALSE); - g_return_val_if_fail (c != NULL, FALSE); - g_return_val_if_fail (*c == 0, FALSE); + nm_assert (s390_subchannels); + nm_assert (a != NULL); + nm_assert (*a == 0); + nm_assert (b != NULL); + nm_assert (*b == 0); + nm_assert (c != NULL); + nm_assert (*c == 0); /* sanity check */ - if (!g_ascii_isxdigit (subchannels[0])) + if (!g_ascii_isxdigit (s390_subchannels[0])) return FALSE; /* Get the first channel */ @@ -1421,47 +1296,194 @@ parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c) return TRUE; } +static gboolean +match_data_s390_subchannels_eval (const char *spec_str, + MatchDeviceData *match_data) +{ + guint32 a, b, c; + + if (G_UNLIKELY (!match_data->s390_subchannels.is_parsed)) { + match_data->s390_subchannels.is_parsed = TRUE; + + if ( !match_data->s390_subchannels.value + || !match_device_s390_subchannels_parse (match_data->s390_subchannels.value, + &match_data->s390_subchannels.a, + &match_data->s390_subchannels.b, + &match_data->s390_subchannels.c)) { + match_data->s390_subchannels.value = NULL; + return FALSE; + } + } else if (!match_data->s390_subchannels.value) + return FALSE; + + if (!match_device_s390_subchannels_parse (spec_str, &a, &b, &c)) + return FALSE; + return match_data->s390_subchannels.a == a + && match_data->s390_subchannels.b == b + && match_data->s390_subchannels.c == c; +} + +static gboolean +match_device_hwaddr_eval (const char *spec_str, + MatchDeviceData *match_data) +{ + if (G_UNLIKELY (!match_data->hwaddr.is_parsed)) { + match_data->hwaddr.is_parsed = TRUE; + + if (match_data->hwaddr.value) { + gsize l; + + if (!_nm_utils_hwaddr_aton (match_data->hwaddr.value, match_data->hwaddr.bin, sizeof (match_data->hwaddr.bin), &l)) + g_return_val_if_reached (FALSE); + match_data->hwaddr.len = l; + } else + return FALSE; + } else if (!match_data->hwaddr.len) + return FALSE; + + return nm_utils_hwaddr_matches (spec_str, -1, match_data->hwaddr.bin, match_data->hwaddr.len); +} + +#define _MATCH_CHECK(spec_str, tag) \ + ({ \ + gboolean _has = FALSE; \ + \ + if (!g_ascii_strncasecmp (spec_str, (""tag""), NM_STRLEN (tag))) { \ + spec_str += NM_STRLEN (tag); \ + _has = TRUE; \ + } \ + _has; \ + }) + +static const char * +match_except (const char *spec_str, gboolean *out_except) +{ + if (_MATCH_CHECK (spec_str, EXCEPT_TAG)) + *out_except = TRUE; + else + *out_except = FALSE; + return spec_str; +} + +static gboolean +match_device_eval (const char *spec_str, + gboolean allow_fuzzy, + MatchDeviceData *match_data) +{ + if (spec_str[0] == '*' && spec_str[1] == '\0') + return TRUE; + + if (_MATCH_CHECK (spec_str, DEVICE_TYPE_TAG)) { + return match_data->device_type + && nm_streq (spec_str, match_data->device_type); + } + + if (_MATCH_CHECK (spec_str, MAC_TAG)) + return match_device_hwaddr_eval (spec_str, match_data); + + if (_MATCH_CHECK (spec_str, INTERFACE_NAME_TAG)) { + gboolean use_pattern = FALSE; + + if (spec_str[0] == '=') + spec_str += 1; + else { + if (spec_str[0] == '~') + spec_str += 1; + use_pattern = TRUE; + } + + if (match_data->interface_name) { + if (nm_streq (spec_str, match_data->interface_name)) + return TRUE; + if (use_pattern && g_pattern_match_simple (spec_str, match_data->interface_name)) + return TRUE; + } + return FALSE; + } + + if (_MATCH_CHECK (spec_str, SUBCHAN_TAG)) + return match_data_s390_subchannels_eval (spec_str, match_data); + + if (allow_fuzzy) { + if (match_device_hwaddr_eval (spec_str, match_data)) + return TRUE; + if ( match_data->interface_name + && nm_streq (spec_str, match_data->interface_name)) + return TRUE; + } + + return FALSE; +} + NMMatchSpecMatchType -nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels) +nm_match_spec_device (const GSList *specs, + const char *interface_name, + const char *device_type, + const char *hwaddr, + const char *s390_subchannels) { const GSList *iter; - guint32 a = 0, b = 0, c = 0; - guint32 spec_a = 0, spec_b = 0, spec_c = 0; - NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH; + NMMatchSpecMatchType match; + const char *spec_str; + gboolean except; + MatchDeviceData match_data = { + .interface_name = interface_name, + .device_type = nm_str_not_empty (device_type), + .hwaddr = { + .value = hwaddr, + }, + .s390_subchannels = { + .value = s390_subchannels, + }, + }; - g_return_val_if_fail (subchannels != NULL, NM_MATCH_SPEC_NO_MATCH); + nm_assert (!hwaddr || nm_utils_hwaddr_valid (hwaddr, -1)); if (!specs) return NM_MATCH_SPEC_NO_MATCH; - if (!parse_subchannels (subchannels, &a, &b, &c)) - return NM_MATCH_SPEC_NO_MATCH; + match = NM_MATCH_SPEC_NO_MATCH; - for (iter = specs; iter; iter = g_slist_next (iter)) { - const char *spec_str = iter->data; - gboolean except; + /* pre-search for "*" */ + for (iter = specs; iter; iter = iter->next) { + spec_str = iter->data; + + if (spec_str && spec_str[0] == '*' && spec_str[1] == '\0') { + match = NM_MATCH_SPEC_MATCH; + break; + } + } + + for (iter = specs; iter; iter = iter->next) { + spec_str = iter->data; if (!spec_str || !*spec_str) continue; - spec_str = _match_except (spec_str, &except); + spec_str = match_except (spec_str, &except); - if (!g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))) { - spec_str += NM_STRLEN (SUBCHAN_TAG); - if (parse_subchannels (spec_str, &spec_a, &spec_b, &spec_c)) { - if (a == spec_a && b == spec_b && c == spec_c) { - if (except) - return NM_MATCH_SPEC_NEG_MATCH; - match = NM_MATCH_SPEC_MATCH; - } - } + if ( !except + && match == NM_MATCH_SPEC_MATCH) { + /* we have no "except-match" but already match. No need to evaluate + * the match, we cannot match stronger. */ + continue; } + + if (!match_device_eval (spec_str, + !except, + &match_data)) + continue; + + if (except) + return NM_MATCH_SPEC_NEG_MATCH; + match = NM_MATCH_SPEC_MATCH; } + return match; } static gboolean -_match_config_nm_version (const char *str, const char *tag, guint cur_nm_version) +match_config_eval (const char *str, const char *tag, guint cur_nm_version) { gs_free char *s_ver = NULL; gs_strfreev char **s_ver_tokens = NULL; @@ -1524,7 +1546,7 @@ _match_config_nm_version (const char *str, const char *tag, guint cur_nm_version } NMMatchSpecMatchType -nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const char *env) +nm_match_spec_config (const GSList *specs, guint cur_nm_version, const char *env) { const GSList *iter; NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH; @@ -1540,15 +1562,15 @@ nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const cha if (!spec_str || !*spec_str) continue; - spec_str = _match_except (spec_str, &except); + spec_str = match_except (spec_str, &except); - if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION)) - v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version); - else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN)) - v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version); - else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX)) - v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version); - else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_ENV)) + if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_NM_VERSION)) + v_match = match_config_eval (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version); + else if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN)) + v_match = match_config_eval (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version); + else if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX)) + v_match = match_config_eval (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version); + else if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_ENV)) v_match = env && env[0] && !strcmp (spec_str, env); else continue; @@ -1562,6 +1584,8 @@ nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const cha return match; } +#undef _MATCH_CHECK + /** * nm_match_spec_split: * @value: the string of device specs |