mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-29 19:40:12 +01:00
platform: implement sysctl access via relative path to sysctl_open_netdir()
This commit is contained in:
parent
d8cefd57fb
commit
c85418746c
3 changed files with 98 additions and 38 deletions
|
|
@ -2510,32 +2510,32 @@ ASSERT_NETNS_CURRENT (NMPlatform *platform)
|
|||
} G_STMT_END
|
||||
|
||||
static void
|
||||
_log_dbg_sysctl_set_impl (NMPlatform *platform, const char *path, const char *value)
|
||||
_log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value)
|
||||
{
|
||||
GError *error = NULL;
|
||||
char *contents, *contents_escaped;
|
||||
char *value_escaped = g_strescape (value, NULL);
|
||||
|
||||
if (!g_file_get_contents (path, &contents, NULL, &error)) {
|
||||
_LOGD ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", path, value_escaped, error->message);
|
||||
if (nm_utils_file_get_contents (dirfd, path, 1*1024*1024, &contents, NULL, &error) < 0) {
|
||||
_LOGD ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", pathid, value_escaped, error->message);
|
||||
g_clear_error (&error);
|
||||
} else {
|
||||
g_strstrip (contents);
|
||||
contents_escaped = g_strescape (contents, NULL);
|
||||
if (strcmp (contents, value) == 0)
|
||||
_LOGD ("sysctl: setting '%s' to '%s' (current value is identical)", path, value_escaped);
|
||||
_LOGD ("sysctl: setting '%s' to '%s' (current value is identical)", pathid, value_escaped);
|
||||
else
|
||||
_LOGD ("sysctl: setting '%s' to '%s' (current value is '%s')", path, value_escaped, contents_escaped);
|
||||
_LOGD ("sysctl: setting '%s' to '%s' (current value is '%s')", pathid, value_escaped, contents_escaped);
|
||||
g_free (contents);
|
||||
g_free (contents_escaped);
|
||||
}
|
||||
g_free (value_escaped);
|
||||
}
|
||||
|
||||
#define _log_dbg_sysctl_set(platform, path, value) \
|
||||
#define _log_dbg_sysctl_set(platform, pathid, dirfd, path, value) \
|
||||
G_STMT_START { \
|
||||
if (_LOGD_ENABLED ()) { \
|
||||
_log_dbg_sysctl_set_impl (platform, path, value); \
|
||||
_log_dbg_sysctl_set_impl (platform, pathid, dirfd, path, value); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
|
|
@ -2555,26 +2555,44 @@ sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
|
|||
|
||||
ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
|
||||
|
||||
if (!nm_platform_netns_push (platform, &netns)) {
|
||||
errno = ENETDOWN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fd = open (path, O_WRONLY | O_TRUNC);
|
||||
if (fd == -1) {
|
||||
errsv = errno;
|
||||
if (errsv == ENOENT) {
|
||||
_LOGD ("sysctl: failed to open '%s': (%d) %s",
|
||||
path, errsv, strerror (errsv));
|
||||
} else {
|
||||
_LOGE ("sysctl: failed to open '%s': (%d) %s",
|
||||
path, errsv, strerror (errsv));
|
||||
if (dirfd < 0) {
|
||||
if (!nm_platform_netns_push (platform, &netns)) {
|
||||
errno = ENETDOWN;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pathid = path;
|
||||
|
||||
fd = open (path, O_WRONLY | O_TRUNC | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
errsv = errno;
|
||||
if (errsv == ENOENT) {
|
||||
_LOGD ("sysctl: failed to open '%s': (%d) %s",
|
||||
pathid, errsv, strerror (errsv));
|
||||
} else {
|
||||
_LOGE ("sysctl: failed to open '%s': (%d) %s",
|
||||
pathid, errsv, strerror (errsv));
|
||||
}
|
||||
errno = errsv;
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
fd = openat (dirfd, path, O_WRONLY | O_TRUNC | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
errsv = errno;
|
||||
if (errsv == ENOENT) {
|
||||
_LOGD ("sysctl: failed to openat '%s': (%d) %s",
|
||||
pathid, errsv, strerror (errsv));
|
||||
} else {
|
||||
_LOGE ("sysctl: failed to openat '%s': (%d) %s",
|
||||
pathid, errsv, strerror (errsv));
|
||||
}
|
||||
errno = errsv;
|
||||
return FALSE;
|
||||
}
|
||||
errno = errsv;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_log_dbg_sysctl_set (platform, path, value);
|
||||
_log_dbg_sysctl_set (platform, pathid, dirfd, path, value);
|
||||
|
||||
/* Most sysfs and sysctl options don't care about a trailing LF, while some
|
||||
* (like infiniband) do. So always add the LF. Also, neither sysfs nor
|
||||
|
|
@ -2647,7 +2665,7 @@ _nm_logging_clear_platform_logging_cache_impl (void)
|
|||
}
|
||||
|
||||
static void
|
||||
_log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *contents)
|
||||
_log_dbg_sysctl_get_impl (NMPlatform *platform, const char *pathid, const char *contents)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
const char *prev_value = NULL;
|
||||
|
|
@ -2657,24 +2675,24 @@ _log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *co
|
|||
sysctl_clear_cache_list = g_slist_prepend (sysctl_clear_cache_list, platform);
|
||||
priv->sysctl_get_prev_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
} else
|
||||
prev_value = g_hash_table_lookup (priv->sysctl_get_prev_values, path);
|
||||
prev_value = g_hash_table_lookup (priv->sysctl_get_prev_values, pathid);
|
||||
|
||||
if (prev_value) {
|
||||
if (strcmp (prev_value, contents) != 0) {
|
||||
char *contents_escaped = g_strescape (contents, NULL);
|
||||
char *prev_value_escaped = g_strescape (prev_value, NULL);
|
||||
|
||||
_LOGD ("sysctl: reading '%s': '%s' (changed from '%s' on last read)", path, contents_escaped, prev_value_escaped);
|
||||
_LOGD ("sysctl: reading '%s': '%s' (changed from '%s' on last read)", pathid, contents_escaped, prev_value_escaped);
|
||||
g_free (contents_escaped);
|
||||
g_free (prev_value_escaped);
|
||||
g_hash_table_insert (priv->sysctl_get_prev_values, g_strdup (path), g_strdup (contents));
|
||||
g_hash_table_insert (priv->sysctl_get_prev_values, g_strdup (pathid), g_strdup (contents));
|
||||
}
|
||||
} else {
|
||||
char *contents_escaped = g_strescape (contents, NULL);
|
||||
|
||||
_LOGD ("sysctl: reading '%s': '%s'", path, contents_escaped);
|
||||
_LOGD ("sysctl: reading '%s': '%s'", pathid, contents_escaped);
|
||||
g_free (contents_escaped);
|
||||
g_hash_table_insert (priv->sysctl_get_prev_values, g_strdup (path), g_strdup (contents));
|
||||
g_hash_table_insert (priv->sysctl_get_prev_values, g_strdup (pathid), g_strdup (contents));
|
||||
}
|
||||
|
||||
if ( !priv->sysctl_get_warned
|
||||
|
|
@ -2684,10 +2702,10 @@ _log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *co
|
|||
}
|
||||
}
|
||||
|
||||
#define _log_dbg_sysctl_get(platform, path, contents) \
|
||||
#define _log_dbg_sysctl_get(platform, pathid, contents) \
|
||||
G_STMT_START { \
|
||||
if (_LOGD_ENABLED ()) \
|
||||
_log_dbg_sysctl_get_impl (platform, path, contents); \
|
||||
_log_dbg_sysctl_get_impl (platform, pathid, contents); \
|
||||
} G_STMT_END
|
||||
|
||||
static char *
|
||||
|
|
@ -2699,24 +2717,27 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
|
|||
|
||||
ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
|
||||
|
||||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return NULL;
|
||||
if (dirfd < 0) {
|
||||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return NULL;
|
||||
pathid = path;
|
||||
}
|
||||
|
||||
if (!g_file_get_contents (path, &contents, NULL, &error)) {
|
||||
if (nm_utils_file_get_contents (dirfd, path, 1*1024*1024, &contents, NULL, &error) < 0) {
|
||||
/* We assume FAILED means EOPNOTSUP */
|
||||
if ( g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)
|
||||
|| g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NODEV)
|
||||
|| g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_FAILED))
|
||||
_LOGD ("error reading %s: %s", path, error->message);
|
||||
_LOGD ("error reading %s: %s", pathid, error->message);
|
||||
else
|
||||
_LOGE ("error reading %s: %s", path, error->message);
|
||||
_LOGE ("error reading %s: %s", pathid, error->message);
|
||||
g_clear_error (&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_strstrip (contents);
|
||||
|
||||
_log_dbg_sysctl_get (platform, path, contents);
|
||||
_log_dbg_sysctl_get (platform, pathid, contents);
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,34 @@ nm_platform_process_events (NMPlatform *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_platform_sysctl_open_netdir:
|
||||
* @self: platform instance
|
||||
* @ifindex: the ifindex for which to open /sys/class/net/%s
|
||||
* @out_ifname: optional output argument of the found ifname.
|
||||
*
|
||||
* Wraps nmp_utils_sysctl_open_netdir() by first changing into the right
|
||||
* network-namespace.
|
||||
*
|
||||
* Returns: on success, the open file descriptor to the /sys/class/net/%s
|
||||
* directory.
|
||||
*/
|
||||
int
|
||||
nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname)
|
||||
{
|
||||
const char*ifname_guess;
|
||||
_CHECK_SELF_NETNS (self, klass, netns, -1);
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, -1);
|
||||
|
||||
/* we don't have an @ifname_guess argument to make the API nicer.
|
||||
* But still do a cache-lookup first. Chances are good that we have
|
||||
* the right ifname cached and save if_indextoname() */
|
||||
ifname_guess = nm_platform_link_get_name (self, ifindex);
|
||||
|
||||
return nmp_utils_sysctl_open_netdir (ifindex, ifname_guess, out_ifname);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_sysctl_set:
|
||||
* @self: platform instance
|
||||
|
|
|
|||
|
|
@ -720,6 +720,17 @@ const char *_nm_platform_error_to_string (NMPlatformError error);
|
|||
#define NMP_SYSCTL_PATHID_ABSOLUTE(path) \
|
||||
((const char *) NULL), -1, (path)
|
||||
|
||||
#define NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname, path) \
|
||||
nm_sprintf_bufa (NM_STRLEN ("net:/sys/class/net//\0") + IFNAMSIZ + strlen (path), \
|
||||
"net:/sys/class/net/%s/%s", (ifname), (path)), \
|
||||
(dirfd), (path)
|
||||
|
||||
#define NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, path) \
|
||||
nm_sprintf_bufa (NM_STRLEN ("net:/sys/class/net//"path"/\0") + IFNAMSIZ, \
|
||||
"net:/sys/class/net/%s/%s", (ifname), path), \
|
||||
(dirfd), (""path"")
|
||||
|
||||
int nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname);
|
||||
gboolean nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value);
|
||||
char *nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const char *path);
|
||||
gint32 nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, const char *path, gint32 fallback);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue