diff options
| author | Michael Biebl <biebl@debian.org> | 2018-05-11 22:08:45 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-05-11 22:08:45 +0200 |
| commit | ee9c73a923909e23a649407be77e25235d769e25 (patch) | |
| tree | e21c923621fa278e737da693df9eb60ea31a6067 /src/nm-core-utils.c | |
| parent | f60117b41d5433be1b4a96d82cd11d0c3dce9b63 (diff) | |
New upstream version 1.10.8 upstream/1.10.8
Diffstat (limited to 'src/nm-core-utils.c')
| -rw-r--r-- | src/nm-core-utils.c | 278 |
1 files changed, 218 insertions, 60 deletions
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index b97be0b8..f6b33a14 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -452,6 +452,83 @@ nm_utils_modprobe (GError **error, gboolean suppress_error_logging, const char * return exit_status; } +/** + * nm_utils_get_start_time_for_pid: + * @pid: the process identifier + * @out_state: return the state character, like R, S, Z. See `man 5 proc`. + * @out_ppid: parent process id + * + * Originally copied from polkit source (src/polkit/polkitunixprocess.c) + * and adjusted. + * + * Returns: the timestamp when the process started (by parsing /proc/$PID/stat). + * If an error occurs (e.g. the process does not exist), 0 is returned. + * + * The returned start time counts since boot, in the unit HZ (with HZ usually being (1/100) seconds) + **/ +guint64 +nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid) +{ + guint64 start_time; + char filename[256]; + gs_free gchar *contents = NULL; + size_t length; + gs_strfreev gchar **tokens = NULL; + guint num_tokens; + gchar *p; + char state = ' '; + gint64 ppid = 0; + + start_time = 0; + contents = NULL; + + g_return_val_if_fail (pid > 0, 0); + + nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid); + + if (!g_file_get_contents (filename, &contents, &length, NULL)) + goto fail; + + /* start time is the token at index 19 after the '(process name)' entry - since only this + * field can contain the ')' character, search backwards for this to avoid malicious + * processes trying to fool us + */ + p = strrchr (contents, ')'); + if (p == NULL) + goto fail; + p += 2; /* skip ') ' */ + if (p - contents >= (int) length) + goto fail; + + state = p[0]; + + tokens = g_strsplit (p, " ", 0); + + num_tokens = g_strv_length (tokens); + + if (num_tokens < 20) + goto fail; + + if (out_ppid) { + ppid = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 1, G_MAXINT, 0); + if (ppid == 0) + goto fail; + } + + start_time = _nm_utils_ascii_str_to_int64 (tokens[19], 10, 1, G_MAXINT64, 0); + if (start_time == 0) + goto fail; + + NM_SET_OUT (out_state, state); + NM_SET_OUT (out_ppid, ppid); + return start_time; + +fail: + NM_SET_OUT (out_state, ' '); + NM_SET_OUT (out_ppid, 0); + return 0; +} + /*****************************************************************************/ typedef struct { @@ -1169,8 +1246,8 @@ typedef struct { static gboolean match_device_s390_subchannels_parse (const char *s390_subchannels, guint32 *out_a, guint32 *out_b, guint32 *out_c) { - char buf[30 + 1]; - const int BUFSIZE = G_N_ELEMENTS (buf) - 1; + const int BUFSIZE = 30; + char buf[BUFSIZE + 1]; guint i = 0; char *pa = NULL, *pb = NULL, *pc = NULL; gint64 a, b, c; @@ -1800,6 +1877,110 @@ nm_utils_new_infiniband_name (char *name, const char *parent_name, int p_key) /*****************************************************************************/ +gboolean +nm_utils_resolve_conf_parse (int addr_family, + const char *rc_contents, + GArray *nameservers, + GPtrArray *dns_options) +{ + guint i; + gboolean changed = FALSE; + gs_free const char **lines = NULL; + gsize l; + + g_return_val_if_fail (rc_contents, FALSE); + g_return_val_if_fail (nameservers, FALSE); + g_return_val_if_fail ( ( addr_family == AF_INET + && g_array_get_element_size (nameservers) == sizeof (in_addr_t)) + || ( addr_family == AF_INET6 + && g_array_get_element_size (nameservers) == sizeof (struct in6_addr)), FALSE); + + lines = nm_utils_strsplit_set (rc_contents, "\r\n"); + if (!lines) + return FALSE; + +/* like glibc's MATCH() macro in resolv/res_init.c. */ +#define RC_MATCH(line, option, out_arg) \ + ({ \ + const char *const _line = (line); \ + gboolean _match = FALSE; \ + \ + if ( (strncmp (_line, option, NM_STRLEN (option)) == 0) \ + && (NM_IN_SET (_line[NM_STRLEN (option)], ' ', '\t'))) { \ + _match = TRUE;\ + (out_arg) = &_line[NM_STRLEN (option) + 1]; \ + } \ + _match; \ + }) + + for (l = 0; lines[l]; l++) { + const char *const line = lines[l]; + const char *s = NULL; + + if (RC_MATCH (line, "nameserver", s)) { + gs_free char *s_cpy = NULL; + NMIPAddr ns; + + s = nm_strstrip_avoid_copy (s, &s_cpy); + if (inet_pton (addr_family, s, &ns) != 1) + continue; + + if (addr_family == AF_INET) { + if (!ns.addr4) + continue; + for (i = 0; i < nameservers->len; i++) { + if (g_array_index (nameservers, guint32, i) == ns.addr4) + break; + } + } else { + if (IN6_IS_ADDR_UNSPECIFIED (&ns.addr6)) + continue; + for (i = 0; i < nameservers->len; i++) { + struct in6_addr *t = &g_array_index (nameservers, struct in6_addr, i); + + if (IN6_ARE_ADDR_EQUAL (t, &ns.addr6)) + break; + } + } + + if (i == nameservers->len) { + g_array_append_val (nameservers, ns); + changed = TRUE; + } + continue; + } + + if (RC_MATCH (line, "options", s)) { + if (!dns_options) + continue; + + s = nm_str_skip_leading_spaces (s); + if (s[0]) { + gs_free const char **tokens = NULL; + gsize i_tokens; + + tokens = nm_utils_strsplit_set (s, " \t"); + for (i_tokens = 0; tokens && tokens[i_tokens]; i_tokens++) { + gs_free char *t = g_strstrip (g_strdup (tokens[i_tokens])); + + if ( _nm_utils_dns_option_validate (t, NULL, NULL, + addr_family == AF_INET6, + _nm_utils_dns_option_descs) + && _nm_utils_dns_option_find_idx (dns_options, t) < 0) { + g_ptr_array_add (dns_options, g_steal_pointer (&t)); + changed = TRUE; + } + } + } + continue; + } + } + + return changed; +} + +/*****************************************************************************/ + /** * nm_utils_cmp_connection_by_autoconnect_priority: * @a: @@ -2157,13 +2338,7 @@ _log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sort } void -nm_utils_log_connection_diff (NMConnection *connection, - NMConnection *diff_base, - guint32 level, - guint64 domain, - const char *name, - const char *prefix, - const char *dbus_path) +nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix) { GHashTable *connection_diff = NULL; GArray *sorted_hashes; @@ -2239,6 +2414,7 @@ nm_utils_log_connection_diff (NMConnection *connection, if (print_header) { GError *err_verify = NULL; + const char *path = nm_connection_get_path (connection); const char *t1, *t2; t1 = nm_connection_get_connection_type (connection); @@ -2248,12 +2424,12 @@ nm_utils_log_connection_diff (NMConnection *connection, prefix, name, connection, G_OBJECT_TYPE_NAME (connection), NM_PRINT_FMT_QUOTE_STRING (t1), diff_base, G_OBJECT_TYPE_NAME (diff_base), NM_PRINT_FMT_QUOTE_STRING (t2), - NM_PRINT_FMT_QUOTED (dbus_path, " [", dbus_path, "]", "")); + NM_PRINT_FMT_QUOTED (path, " [", path, "]", "")); } else { nm_log (level, domain, NULL, NULL, "%sconnection '%s' (%p/%s/%s%s%s):%s%s%s", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), NM_PRINT_FMT_QUOTE_STRING (t1), - NM_PRINT_FMT_QUOTED (dbus_path, " [", dbus_path, "]", "")); + NM_PRINT_FMT_QUOTED (path, " [", path, "]", "")); } print_header = FALSE; @@ -2571,7 +2747,7 @@ _get_contents_error (GError **error, int errsv, const char *format, ...) /** * nm_utils_fd_get_contents: * @fd: open file descriptor to read. The fd will not be closed, - * but don't rely on its state afterwards. + * but don't rely on it's state afterwards. * @close_fd: if %TRUE, @fd will be closed by the function. * Passing %TRUE here might safe a syscall for dup(). * @max_length: allocate at most @max_length bytes. If the @@ -3573,8 +3749,7 @@ nm_utils_setpgid (gpointer unused G_GNUC_UNUSED) /** * nm_utils_g_value_set_strv: * @value: a #GValue, initialized to store a #G_TYPE_STRV - * @strings: a #GPtrArray of strings. %NULL values are not - * allowed. + * @strings: a #GPtrArray of strings * * Converts @strings to a #GStrv and stores it in @value. */ @@ -3582,13 +3757,11 @@ void nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings) { char **strv; - guint i; + int i; strv = g_new (char *, strings->len + 1); - for (i = 0; i < strings->len; i++) { - nm_assert (strings->pdata[i]); + for (i = 0; i < strings->len; i++) strv[i] = g_strdup (strings->pdata[i]); - } strv[i] = NULL; g_value_take_boxed (value, strv); @@ -3718,11 +3891,12 @@ nm_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp, return t; } -guint32 +gboolean nm_utils_lifetime_get (guint32 timestamp, guint32 lifetime, guint32 preferred, gint32 now, + guint32 *out_lifetime, guint32 *out_preferred) { guint32 t_lifetime, t_preferred; @@ -3730,39 +3904,38 @@ nm_utils_lifetime_get (guint32 timestamp, nm_assert (now >= 0); if (timestamp == 0 && lifetime == 0) { - /* We treat lifetime==0 && timestamp==0 addresses as permanent addresses to allow easy + /* We treat lifetime==0 && timestamp == 0 addresses as permanent addresses to allow easy * creation of such addresses (without requiring to set the lifetime fields to * NM_PLATFORM_LIFETIME_PERMANENT). The real lifetime==0 addresses (E.g. DHCP6 telling us * to drop an address will have timestamp set. */ - NM_SET_OUT (out_preferred, NM_PLATFORM_LIFETIME_PERMANENT); - g_return_val_if_fail (preferred == 0, NM_PLATFORM_LIFETIME_PERMANENT); - return NM_PLATFORM_LIFETIME_PERMANENT; - } + *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT; + g_return_val_if_fail (preferred == 0, TRUE); + } else { + if (now <= 0) + now = nm_utils_get_monotonic_timestamp_s (); + t_lifetime = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now); + if (!t_lifetime) { + *out_lifetime = 0; + *out_preferred = 0; + return FALSE; + } + t_preferred = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, preferred, now); - if (now <= 0) - now = nm_utils_get_monotonic_timestamp_s (); + *out_lifetime = t_lifetime; + *out_preferred = MIN (t_preferred, t_lifetime); - t_lifetime = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now); - if (!t_lifetime) { - NM_SET_OUT (out_preferred, 0); - return 0; + /* Assert that non-permanent addresses have a (positive) @timestamp. nm_utils_lifetime_rebase_relative_time_on_now() + * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always + * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. + */ + g_return_val_if_fail ( timestamp != 0 + || ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT + && preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE); + g_return_val_if_fail (t_preferred <= t_lifetime, TRUE); } - - t_preferred = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, preferred, now); - - NM_SET_OUT (out_preferred, MIN (t_preferred, t_lifetime)); - - /* Assert that non-permanent addresses have a (positive) @timestamp. nm_utils_lifetime_rebase_relative_time_on_now() - * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always - * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew. - */ - g_return_val_if_fail ( timestamp != 0 - || ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT - && preferred == NM_PLATFORM_LIFETIME_PERMANENT), t_lifetime); - g_return_val_if_fail (t_preferred <= t_lifetime, t_lifetime); - - return t_lifetime; + return TRUE; } const char * @@ -4156,21 +4329,6 @@ nm_utils_format_con_diff_for_audit (GHashTable *diff) return g_string_free (str, FALSE); } -const char * -nm_utils_parse_dns_domain (const char *domain, gboolean *is_routing) -{ - g_return_val_if_fail (domain, NULL); - g_return_val_if_fail (domain[0], NULL); - - if (domain[0] == '~') { - domain++; - NM_SET_OUT (is_routing, TRUE); - } else - NM_SET_OUT (is_routing, FALSE); - - return domain; -} - /*****************************************************************************/ NM_UTILS_ENUM2STR_DEFINE (nm_icmpv6_router_pref_to_string, NMIcmpv6RouterPref, |