shared,core: extend nm_utils_is_specific_hostname() and move to shared

nm_utils_is_specific_hostname() is basically to check whether the
hostname is localhost (and also handle "(null)").

In that sense, it's similar to systemd's is_localhost(). Extend or
variant to

  - be case insensitive (like is_localhost()).

  - accept more variants of localhost/localdomain names as special.
This commit is contained in:
Thomas Haller 2020-07-31 08:52:21 +02:00
parent 00c6823ecc
commit 5da502a1e1
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 116 additions and 14 deletions

View file

@ -5157,3 +5157,81 @@ _nm_utils_format_variant_attributes (GHashTable *attributes,
key_value_separator);
return g_string_free (str, FALSE);
}
/*****************************************************************************/
gboolean
nm_utils_is_localhost (const char *name)
{
static const char *const NAMES[] = {
"localhost",
"localhost4",
"localhost6",
"localhost.localdomain",
"localhost4.localdomain4",
"localhost6.localdomain6",
};
gsize name_len;
int i;
if (!name)
return FALSE;
/* This tries to identify local host and domain names
* described in RFC6761 plus the redhatism of localdomain.
*
* Similar to systemd's is_localhost(). */
name_len = strlen (name);
if (name_len == 0)
return FALSE;
if (name[name_len - 1] == '.') {
/* one trailing dot is fine. Hide it. */
name_len--;
}
for (i = 0; i < (int) G_N_ELEMENTS (NAMES); i++) {
const char *n = NAMES[i];
gsize l = strlen (n);
gsize s;
if (name_len < l)
continue;
s = name_len - l;
if (g_ascii_strncasecmp (&name[s], n, l) != 0)
continue;
/* we accept the name if it is equal to one of the well-known names,
* or if it is some prefix, a '.' and the well-known name. */
if (s == 0)
return TRUE;
if (name[s - 1] == '.')
return TRUE;
}
return FALSE;
}
gboolean
nm_utils_is_specific_hostname (const char *name)
{
if (nm_str_is_empty (name))
return FALSE;
if (nm_streq (name, "(none)")) {
/* This is not a special hostname. Probably an artefact by somebody wrongly
* printing NULL. */
return FALSE;
}
if (nm_utils_is_localhost (name))
return FALSE;
/* FIXME: properly validate the hostname, like systemd's hostname_is_valid() */
return TRUE;
}

View file

@ -2195,4 +2195,10 @@ char *_nm_utils_format_variant_attributes (GHashTable *attributes,
char attr_separator,
char key_value_separator);
/*****************************************************************************/
gboolean nm_utils_is_localhost (const char *name);
gboolean nm_utils_is_specific_hostname (const char *name);
#endif /* __NM_SHARED_UTILS_H__ */

View file

@ -910,6 +910,37 @@ test_in_strset_ascii_case (void)
/*****************************************************************************/
static void
test_is_specific_hostname (void)
{
g_assert (!nm_utils_is_specific_hostname (NULL));
g_assert (!nm_utils_is_specific_hostname (""));
g_assert (!nm_utils_is_specific_hostname ("(none)"));
g_assert (nm_utils_is_specific_hostname ("(NONE)"));
g_assert (!nm_utils_is_specific_hostname ("localhost"));
g_assert (!nm_utils_is_specific_hostname ("lOcalHost"));
g_assert (!nm_utils_is_specific_hostname ("LOCALHOST"));
g_assert (!nm_utils_is_specific_hostname ("LOCALHOST.localdomain"));
g_assert (nm_utils_is_specific_hostname ("xlocalhost"));
g_assert (nm_utils_is_specific_hostname ("lOcalHxost"));
g_assert (nm_utils_is_specific_hostname ("LOCALxHOST"));
g_assert (!nm_utils_is_specific_hostname ("foo.LOCALHOST"));
g_assert (!nm_utils_is_specific_hostname ("foo.LOCALHOsT6."));
g_assert (!nm_utils_is_specific_hostname ("foo.LOCALHOsT6.localdomain6"));
g_assert (!nm_utils_is_specific_hostname (".LOCALHOsT6.localdomain6"));
g_assert (!nm_utils_is_specific_hostname ("LOCALHOsT6.localdomain6"));
g_assert (!nm_utils_is_specific_hostname ("LOCALHOsT6.localdomain6."));
g_assert (nm_utils_is_specific_hostname ("LOCALHOsT6.localdomain."));
g_assert (nm_utils_is_specific_hostname (" "));
}
/*****************************************************************************/
NMTST_DEFINE ();
int main (int argc, char **argv)
@ -933,6 +964,7 @@ int main (int argc, char **argv)
g_test_add_func ("/general/test_nm_str_buf", test_nm_str_buf);
g_test_add_func ("/general/test_nm_utils_parse_next_line", test_nm_utils_parse_next_line);
g_test_add_func ("/general/test_in_strset_ascii_case", test_in_strset_ascii_case);
g_test_add_func ("/general/test_is_specific_hostname", test_is_specific_hostname);
return g_test_run ();
}

View file

@ -2373,20 +2373,6 @@ NM_ASSERT_VALID_PATH_COMPONENT (const char *name)
g_assert_not_reached ();
}
gboolean
nm_utils_is_specific_hostname (const char *name)
{
if (!name)
return FALSE;
if ( strcmp (name, "(none)")
&& strcmp (name, "localhost")
&& strcmp (name, "localhost6")
&& strcmp (name, "localhost.localdomain")
&& strcmp (name, "localhost6.localdomain6"))
return TRUE;
return FALSE;
}
/*****************************************************************************/
typedef struct {