core: add nm_utils_connection_match_spec_list()
Add function nm_utils_connection_match_spec_list() to check whether a connection matches a spec list. Also document the supported syntax in the man page.
This commit is contained in:
@@ -1685,6 +1685,55 @@ interface-name:vboxnet*,except:interface-name:vboxnet2
|
||||
</programlisting>
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="connection-spec">
|
||||
<title>Connection List Format</title>
|
||||
<para>
|
||||
Connections can be specified using the following format:
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>*</term>
|
||||
<listitem><para>Matches every connection.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>uuid:UUID</term>
|
||||
<listitem><para>Match the connection by UUID, for example
|
||||
<literal>"uuid:83037490-1d17-4986-a397-01f1db3a7fc2"</literal></para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>id=ID</term>
|
||||
<listitem><para>Match the connection by name.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>origin:ORIGIN</term>
|
||||
<listitem><para>Match the connection by origin, stored in the
|
||||
<literal>org.freedesktop.NetworkManager.origin</literal> tag of the user setting. For example, use
|
||||
<literal>"except:origin:nm-initrd-generator"</literal> to forbid activation of connections created by the
|
||||
initrd generator.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>except:SPEC</term>
|
||||
<listitem><para>Negative match of a connection. A negative match has higher priority then the positive
|
||||
matches above.</para>
|
||||
<para>If there is a list consisting only of negative matches, the behavior is the same as if there is also
|
||||
match-all. That means, if none of all the negative matches is satisfied, the overall result is still a
|
||||
positive match.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>SPEC[,;]SPEC</term>
|
||||
<listitem><para>Multiple specs can be concatenated with commas or semicolons. The order does not matter as
|
||||
matches are either inclusive or negative (<literal>except:</literal>), with negative matches having higher
|
||||
priority.</para>
|
||||
<para>Backslash is supported to escape the separators ';' and ',', and to express special characters such as
|
||||
newline ('\n'), tabulator ('\t'), whitespace ('\s') and backslash ('\\'). Whitespace is not a separator but
|
||||
will be trimmed between two specs (unless escaped as '\s').</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@@ -1484,6 +1484,112 @@ nm_match_spec_device(const GSList *specs,
|
||||
return _match_result(has_except, has_not_except, has_match, has_match_except);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *uuid;
|
||||
const char *id;
|
||||
const char *origin;
|
||||
} MatchConnectionData;
|
||||
|
||||
static gboolean
|
||||
match_connection_eval(const char *spec_str, const MatchConnectionData *match_data)
|
||||
{
|
||||
if (spec_str[0] == '*' && spec_str[1] == '\0')
|
||||
return TRUE;
|
||||
|
||||
if (_MATCH_CHECK(spec_str, "id:"))
|
||||
return nm_streq0(spec_str, match_data->id);
|
||||
|
||||
if (_MATCH_CHECK(spec_str, "uuid:"))
|
||||
return nm_streq0(spec_str, match_data->uuid);
|
||||
|
||||
if (_MATCH_CHECK(spec_str, "origin:"))
|
||||
return nm_streq0(spec_str, match_data->origin);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static NMMatchSpecMatchType
|
||||
match_spec_connection(const GSList *specs, const char *id, const char *uuid, const char *origin)
|
||||
{
|
||||
const GSList * iter;
|
||||
gboolean has_match = FALSE;
|
||||
gboolean has_match_except = FALSE;
|
||||
gboolean has_except = FALSE;
|
||||
gboolean has_not_except = FALSE;
|
||||
const char * spec_str;
|
||||
const MatchConnectionData match_data = {
|
||||
.id = nm_str_not_empty(id),
|
||||
.uuid = nm_str_not_empty(uuid),
|
||||
.origin = nm_str_not_empty(origin),
|
||||
};
|
||||
|
||||
if (!specs)
|
||||
return NM_MATCH_SPEC_NO_MATCH;
|
||||
|
||||
for (iter = specs; iter; iter = iter->next) {
|
||||
gboolean except;
|
||||
|
||||
spec_str = iter->data;
|
||||
|
||||
if (!spec_str || !*spec_str)
|
||||
continue;
|
||||
|
||||
spec_str = match_except(spec_str, &except);
|
||||
|
||||
if (except)
|
||||
has_except = TRUE;
|
||||
else
|
||||
has_not_except = TRUE;
|
||||
|
||||
if ((except && has_match_except) || (!except && has_match)) {
|
||||
/* evaluating the match does not give new information. Skip it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!match_connection_eval(spec_str, &match_data))
|
||||
continue;
|
||||
|
||||
if (except)
|
||||
has_match_except = TRUE;
|
||||
else
|
||||
has_match = TRUE;
|
||||
}
|
||||
|
||||
return _match_result(has_except, has_not_except, has_match, has_match_except);
|
||||
}
|
||||
|
||||
int
|
||||
nm_utils_connection_match_spec_list(NMConnection *connection,
|
||||
const GSList *specs,
|
||||
int no_match_value)
|
||||
{
|
||||
NMMatchSpecMatchType m;
|
||||
NMSettingUser * s_user;
|
||||
const char * origin = NULL;
|
||||
|
||||
if (!specs)
|
||||
return no_match_value;
|
||||
|
||||
s_user = _nm_connection_get_setting(connection, NM_TYPE_SETTING_USER);
|
||||
if (s_user)
|
||||
origin = nm_setting_user_get_data(s_user, NM_USER_TAG_ORIGIN);
|
||||
|
||||
m = match_spec_connection(specs,
|
||||
nm_connection_get_id(connection),
|
||||
nm_connection_get_uuid(connection),
|
||||
origin);
|
||||
switch (m) {
|
||||
case NM_MATCH_SPEC_MATCH:
|
||||
return TRUE;
|
||||
case NM_MATCH_SPEC_NEG_MATCH:
|
||||
return FALSE;
|
||||
case NM_MATCH_SPEC_NO_MATCH:
|
||||
return no_match_value;
|
||||
}
|
||||
nm_assert_not_reached();
|
||||
return no_match_value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
match_config_eval(const char *str, const char *tag, guint cur_nm_version)
|
||||
{
|
||||
|
@@ -211,6 +211,10 @@ gboolean nm_utils_kernel_cmdline_match_check(const char *const *proc_cmdline,
|
||||
guint num_patterns,
|
||||
GError ** error);
|
||||
|
||||
int nm_utils_connection_match_spec_list(NMConnection *connection,
|
||||
const GSList *specs,
|
||||
int no_match_value);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_utils_connection_has_default_route(NMConnection *connection,
|
||||
|
Reference in New Issue
Block a user