1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Copyright 2004 - 2014 Red Hat, Inc.
19 * Copyright 2005 - 2008 Novell, Inc.
22 #include "nm-default.h"
24 #include "nm-core-utils.h"
32 #include <sys/types.h>
36 #include <linux/if_infiniband.h>
37 #include <net/ethernet.h>
40 #include "nm-core-internal.h"
41 #include "nm-setting-connection.h"
42 #include "nm-setting-ip4-config.h"
43 #include "nm-setting-ip6-config.h"
44 #include "nm-setting-wireless.h"
45 #include "nm-setting-wireless-security.h"
48 * Some toolchains (E.G. uClibc 0.9.33 and earlier) don't export
49 * CLOCK_BOOTTIME even though the kernel supports it, so provide a
52 #ifndef CLOCK_BOOTTIME
53 #define CLOCK_BOOTTIME 7
56 G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int));
57 int _nm_utils_testing = 0;
60 nm_utils_get_testing_initialized ()
62 NMUtilsTestFlags flags;
64 flags = (NMUtilsTestFlags) _nm_utils_testing;
65 if (flags == NM_UTILS_TEST_NONE)
66 flags = (NMUtilsTestFlags) g_atomic_int_get (&_nm_utils_testing);
67 return flags != NM_UTILS_TEST_NONE;
71 nm_utils_get_testing ()
73 NMUtilsTestFlags flags;
75 flags = (NMUtilsTestFlags) _nm_utils_testing;
76 if (flags != NM_UTILS_TEST_NONE) {
77 /* Flags already initialized. Return them. */
78 return flags & NM_UTILS_TEST_ALL;
81 /* Accessing nm_utils_get_testing() causes us to set the flags to initialized.
82 * Detecting running tests also based on g_test_initialized(). */
83 flags = _NM_UTILS_TEST_INITIALIZED;
84 if (g_test_initialized ())
85 flags |= _NM_UTILS_TEST_GENERAL;
87 if (g_atomic_int_compare_and_exchange (&_nm_utils_testing, 0, (int) flags)) {
88 /* Done. We set it. */
89 return flags & NM_UTILS_TEST_ALL;
91 /* It changed in the meantime (??). Re-read the value. */
92 return ((NMUtilsTestFlags) _nm_utils_testing) & NM_UTILS_TEST_ALL;
96 _nm_utils_set_testing (NMUtilsTestFlags flags)
98 g_assert (!NM_FLAGS_ANY (flags, ~NM_UTILS_TEST_ALL));
100 /* mask out everything except ALL, and always set GENERAL. */
101 flags = (flags & NM_UTILS_TEST_ALL) | (_NM_UTILS_TEST_GENERAL | _NM_UTILS_TEST_INITIALIZED);
103 if (!g_atomic_int_compare_and_exchange (&_nm_utils_testing, 0, (int) flags)) {
104 /* We only allow setting _nm_utils_set_testing() once, before fetching the
105 * value with nm_utils_get_testing(). */
106 g_return_if_reached ();
110 /*****************************************************************************/
112 G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error)
115 nm_utils_error_set_cancelled (GError **error,
116 gboolean is_disposing,
117 const char *instance_name)
120 g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING,
121 "Disposing %s instance",
122 instance_name && *instance_name ? instance_name : "source");
124 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
125 "Request cancelled");
130 nm_utils_error_is_cancelled (GError *error,
131 gboolean consider_is_disposing)
134 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
136 if ( consider_is_disposing
137 && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING))
143 /*****************************************************************************/
145 static GSList *_singletons = NULL;
146 static gboolean _singletons_shutdown = FALSE;
149 _nm_singleton_instance_weak_cb (gpointer data,
150 GObject *where_the_object_was)
152 _singletons = g_slist_remove (_singletons, where_the_object_was);
155 static void __attribute__((destructor))
156 _nm_singleton_instance_destroy (void)
158 _singletons_shutdown = TRUE;
160 while (_singletons) {
161 GObject *instance = _singletons->data;
163 _singletons = g_slist_delete_link (_singletons, _singletons);
165 g_object_weak_unref (instance, _nm_singleton_instance_weak_cb, NULL);
167 if (instance->ref_count > 1)
168 nm_log_dbg (LOGD_CORE, "disown %s singleton (%p)", G_OBJECT_TYPE_NAME (instance), instance);
170 g_object_unref (instance);
175 _nm_singleton_instance_register_destruction (GObject *instance)
177 g_return_if_fail (G_IS_OBJECT (instance));
179 /* Don't allow registration after shutdown. We only destroy the singletons
181 g_return_if_fail (!_singletons_shutdown);
183 g_object_weak_ref (instance, _nm_singleton_instance_weak_cb, NULL);
185 _singletons = g_slist_prepend (_singletons, instance);
188 /*****************************************************************************/
191 nm_utils_ascii_str_to_bool (const char *str,
198 return default_value;
200 while (str[0] && g_ascii_isspace (str[0]))
204 return default_value;
207 if (g_ascii_isspace (str[len - 1])) {
213 if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp (str, "on") || !g_ascii_strcasecmp (str, "1"))
214 default_value = TRUE;
215 else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp (str, "off") || !g_ascii_strcasecmp (str, "0"))
216 default_value = FALSE;
219 return default_value;
222 /*****************************************************************************/
225 * nm_ethernet_address_is_valid:
226 * @addr: pointer to a binary or ASCII Ethernet address
227 * @len: length of @addr, or -1 if @addr is ASCII
229 * Compares an Ethernet address against known invalid addresses.
231 * Returns: %TRUE if @addr is a valid Ethernet address, %FALSE if it is not.
234 nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
236 guint8 invalid_addr[4][ETH_ALEN] = {
237 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
238 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
239 {0x44, 0x44, 0x44, 0x44, 0x44, 0x44},
240 {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}, /* prism54 dummy MAC */
242 guint8 addr_bin[ETH_ALEN];
246 g_return_val_if_fail (len == -1 || len == ETH_ALEN, FALSE);
251 if (!nm_utils_hwaddr_aton (addr, addr_bin, ETH_ALEN))
254 } else if (len != ETH_ALEN)
255 g_return_val_if_reached (FALSE);
257 /* Check for multicast address */
258 if ((((guint8 *) addr)[0]) & 0x01)
261 for (i = 0; i < G_N_ELEMENTS (invalid_addr); i++) {
262 if (nm_utils_hwaddr_matches (addr, ETH_ALEN, invalid_addr[i], ETH_ALEN))
270 /* nm_utils_ip4_address_clear_host_address:
271 * @addr: source ip6 address
272 * @plen: prefix length of network
274 * returns: the input address, with the host address set to 0.
277 nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen)
279 return addr & nm_utils_ip4_prefix_to_netmask (plen);
282 /* nm_utils_ip6_address_clear_host_address:
283 * @dst: destination output buffer, will contain the network part of the @src address
284 * @src: source ip6 address
285 * @plen: prefix length of network
287 * Note: this function is self assignment safe, to update @src inplace, set both
288 * @dst and @src to the same destination.
290 const struct in6_addr *
291 nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen)
293 g_return_val_if_fail (plen <= 128, NULL);
294 g_return_val_if_fail (src, NULL);
295 g_return_val_if_fail (dst, NULL);
298 guint nbytes = plen / 8;
299 guint nbits = plen % 8;
301 if (nbytes && dst != src)
302 memcpy (dst, src, nbytes);
304 dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
308 memset (&dst->s6_addr[nbytes], 0, 16 - nbytes);
309 } else if (src != dst)
316 nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
319 guint index_to_delete;
321 guint mm_src, mm_dst, mm_len;
325 g_return_if_fail (array);
328 g_return_if_fail (indexes_to_delete);
330 elt_size = g_array_get_element_size (array);
333 index_to_delete = indexes_to_delete[0];
334 if (index_to_delete >= array->len)
335 g_return_if_reached ();
337 res_length = array->len - 1;
339 mm_dst = index_to_delete;
340 mm_src = index_to_delete;
343 for (i_src = index_to_delete; i_src < array->len; i_src++) {
344 if (i_src < index_to_delete)
347 /* we require indexes_to_delete to contain non-repeated, ascending
348 * indexes. Otherwise we would need to presort the indexes. */
352 if (i_itd + 1 >= len) {
353 index_to_delete = G_MAXUINT;
357 dd = indexes_to_delete[++i_itd];
358 if (dd > index_to_delete) {
359 if (dd >= array->len)
360 g_warn_if_reached ();
362 g_assert (res_length > 0);
365 index_to_delete = dd;
368 g_warn_if_reached ();
372 memmove (&array->data[mm_dst * elt_size],
373 &array->data[mm_src * elt_size],
376 mm_src += mm_len + 1;
383 memmove (&array->data[mm_dst * elt_size],
384 &array->data[mm_src * elt_size],
387 g_array_set_size (array, res_length);
391 nm_spawn_process (const char *args, GError **error)
393 GError *local = NULL;
398 g_return_val_if_fail (args != NULL, -1);
399 g_return_val_if_fail (!error || !*error, -1);
401 if (g_shell_parse_argv (args, &num_args, &argv, &local)) {
402 g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &local);
407 nm_log_warn (LOGD_CORE, "could not spawn process '%s': %s", args, local->message);
408 g_propagate_error (error, local);
415 _trunk_first_line (char *str)
419 s = strchr (str, '\n');
426 nm_utils_modprobe (GError **error, gboolean suppress_error_logging, const char *arg1, ...)
428 gs_unref_ptrarray GPtrArray *argv = NULL;
430 gs_free char *_log_str = NULL;
431 #define ARGV_TO_STR(argv) (_log_str ? _log_str : (_log_str = g_strjoinv (" ", (char **) argv->pdata)))
432 GError *local = NULL;
434 NMLogLevel llevel = suppress_error_logging ? LOGL_DEBUG : LOGL_ERR;
435 gs_free char *std_out = NULL, *std_err = NULL;
437 g_return_val_if_fail (!error || !*error, -1);
438 g_return_val_if_fail (arg1, -1);
440 /* construct the argument list */
441 argv = g_ptr_array_sized_new (4);
442 g_ptr_array_add (argv, "/sbin/modprobe");
443 g_ptr_array_add (argv, (char *) arg1);
446 while ((arg1 = va_arg (ap, const char *)))
447 g_ptr_array_add (argv, (char *) arg1);
450 g_ptr_array_add (argv, NULL);
452 nm_log_dbg (LOGD_CORE, "modprobe: '%s'", ARGV_TO_STR (argv));
453 if (!g_spawn_sync (NULL, (char **) argv->pdata, NULL, 0, NULL, NULL, &std_out, &std_err, &exit_status, &local)) {
454 nm_log (llevel, LOGD_CORE, "modprobe: '%s' failed: %s", ARGV_TO_STR (argv), local->message);
455 g_propagate_error (error, local);
457 } else if (exit_status != 0) {
458 nm_log (llevel, LOGD_CORE, "modprobe: '%s' exited with error %d%s%s%s%s%s%s", ARGV_TO_STR (argv), exit_status,
459 std_out&&*std_out ? " (" : "", std_out&&*std_out ? _trunk_first_line (std_out) : "", std_out&&*std_out ? ")" : "",
460 std_err&&*std_err ? " (" : "", std_err&&*std_err ? _trunk_first_line (std_err) : "", std_err&&*std_err ? ")" : "");
467 * nm_utils_get_start_time_for_pid:
468 * @pid: the process identifier
469 * @out_state: return the state character, like R, S, Z. See `man 5 proc`.
470 * @out_ppid: parent process id
472 * Originally copied from polkit source (src/polkit/polkitunixprocess.c)
475 * Returns: the timestamp when the process started (by parsing /proc/$PID/stat).
476 * If an error occurs (e.g. the process does not exist), 0 is returned.
478 * The returned start time counts since boot, in the unit HZ (with HZ usually being (1/100) seconds)
481 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid)
485 gs_free gchar *contents = NULL;
487 gs_strfreev gchar **tokens = NULL;
497 g_return_val_if_fail (pid > 0, 0);
499 nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid);
501 if (!g_file_get_contents (filename, &contents, &length, NULL))
504 /* start time is the token at index 19 after the '(process name)' entry - since only this
505 * field can contain the ')' character, search backwards for this to avoid malicious
506 * processes trying to fool us
508 p = strrchr (contents, ')');
511 p += 2; /* skip ') ' */
512 if (p - contents >= (int) length)
517 tokens = g_strsplit (p, " ", 0);
519 num_tokens = g_strv_length (tokens);
525 ppid = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 1, G_MAXINT, 0);
528 start_time = strtoull (tokens[19], &endp, 10);
529 if (*endp != '\0' || errno != 0)
541 /******************************************************************************************/
545 NMLogDomain log_domain;
548 gint64 wait_start_us;
549 guint source_timeout_kill_id;
556 NMUtilsKillChildAsyncCb callback;
559 char log_name[1]; /* variable-length object, must be last element!! */
560 } KillChildAsyncData;
562 #define LOG_NAME_FMT "kill child process '%s' (%ld)"
563 #define LOG_NAME_PROCESS_FMT "kill process '%s' (%ld)"
564 #define LOG_NAME_ARGS log_name,(long)pid
566 static KillChildAsyncData *
567 _kc_async_data_alloc (pid_t pid, NMLogDomain log_domain, const char *log_name, NMUtilsKillChildAsyncCb callback, void *user_data)
569 KillChildAsyncData *data;
572 /* append the name at the end of our KillChildAsyncData. */
573 log_name_len = strlen (LOG_NAME_FMT) + 20 + strlen (log_name);
574 data = g_malloc (sizeof (KillChildAsyncData) - 1 + log_name_len);
575 g_snprintf (data->log_name, log_name_len, LOG_NAME_FMT, LOG_NAME_ARGS);
578 data->user_data = user_data;
579 data->callback = callback;
580 data->log_domain = log_domain;
585 #define KC_EXIT_TO_STRING_BUF_SIZE 128
587 _kc_exit_to_string (char *buf, int exit)
588 #define _kc_exit_to_string(buf, exit) ( G_STATIC_ASSERT_EXPR(sizeof (buf) == KC_EXIT_TO_STRING_BUF_SIZE && sizeof ((buf)[0]) == 1), _kc_exit_to_string (buf, exit) )
590 if (WIFEXITED (exit))
591 g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "normally with status %d", WEXITSTATUS (exit));
592 else if (WIFSIGNALED (exit))
593 g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "by signal %d", WTERMSIG (exit));
595 g_snprintf (buf, KC_EXIT_TO_STRING_BUF_SIZE, "with unexpected status %d", exit);
600 _kc_signal_to_string (int sig)
603 case 0: return "no signal (0)";
604 case SIGKILL: return "SIGKILL (" G_STRINGIFY (SIGKILL) ")";
605 case SIGTERM: return "SIGTERM (" G_STRINGIFY (SIGTERM) ")";
607 return "Unexpected signal";
611 #define KC_WAITED_TO_STRING 100
613 _kc_waited_to_string (char *buf, gint64 wait_start_us)
614 #define _kc_waited_to_string(buf, wait_start_us) ( G_STATIC_ASSERT_EXPR(sizeof (buf) == KC_WAITED_TO_STRING && sizeof ((buf)[0]) == 1), _kc_waited_to_string (buf, wait_start_us) )
616 g_snprintf (buf, KC_WAITED_TO_STRING, " (%ld usec elapsed)", (long) (nm_utils_get_monotonic_timestamp_us () - wait_start_us));
621 _kc_cb_watch_child (GPid pid, gint status, gpointer user_data)
623 KillChildAsyncData *data = user_data;
624 char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE], buf_wait[KC_WAITED_TO_STRING];
626 if (data->async.source_timeout_kill_id)
627 g_source_remove (data->async.source_timeout_kill_id);
629 nm_log_dbg (data->log_domain, "%s: terminated %s%s",
630 data->log_name, _kc_exit_to_string (buf_exit, status),
631 _kc_waited_to_string (buf_wait, data->async.wait_start_us));
634 data->callback (pid, TRUE, status, data->user_data);
640 _kc_cb_timeout_grace_period (void *user_data)
642 KillChildAsyncData *data = user_data;
645 data->async.source_timeout_kill_id = 0;
647 if ((ret = kill (data->pid, SIGKILL)) != 0) {
649 /* ESRCH means, process does not exist or is already a zombie. */
650 if (errsv != ESRCH) {
651 nm_log_err (LOGD_CORE | data->log_domain, "%s: kill(SIGKILL) returned unexpected return value %d: (%s, %d)",
652 data->log_name, ret, strerror (errsv), errsv);
655 nm_log_dbg (data->log_domain, "%s: process not terminated after %ld usec. Sending SIGKILL signal",
656 data->log_name, (long) (nm_utils_get_monotonic_timestamp_us () - data->async.wait_start_us));
659 return G_SOURCE_REMOVE;
663 _kc_invoke_callback_idle (gpointer user_data)
665 KillChildAsyncData *data = user_data;
667 if (data->sync.success) {
668 char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
670 nm_log_dbg (data->log_domain, "%s: invoke callback: terminated %s",
671 data->log_name, _kc_exit_to_string (buf_exit, data->sync.child_status));
673 nm_log_dbg (data->log_domain, "%s: invoke callback: killing child failed", data->log_name);
675 data->callback (data->pid, data->sync.success, data->sync.child_status, data->user_data);
678 return G_SOURCE_REMOVE;
682 _kc_invoke_callback (pid_t pid, NMLogDomain log_domain, const char *log_name, NMUtilsKillChildAsyncCb callback, void *user_data, gboolean success, int child_status)
684 KillChildAsyncData *data;
689 data = _kc_async_data_alloc (pid, log_domain, log_name, callback, user_data);
690 data->sync.success = success;
691 data->sync.child_status = child_status;
693 g_idle_add (_kc_invoke_callback_idle, data);
696 /* nm_utils_kill_child_async:
697 * @pid: the process id of the process to kill
698 * @sig: signal to send initially. Set to 0 to send not signal.
699 * @log_domain: the logging domain used for logging (LOGD_NONE to suppress logging)
700 * @log_name: for logging, the name of the processes to kill
701 * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
702 * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter is ignored.
703 * @callback: (allow-none): callback after the child terminated. This function will always
704 * be invoked asynchronously.
705 * @user_data: passed on to callback
707 * Uses g_child_watch_add(), so note the glib comment: if you obtain pid from g_spawn_async() or
708 * g_spawn_async_with_pipes() you will need to pass %G_SPAWN_DO_NOT_REAP_CHILD as flag to the spawn
709 * function for the child watching to work.
710 * Also note, that you must g_source_remove() any other child watchers for @pid because glib
711 * supports only one watcher per child.
714 nm_utils_kill_child_async (pid_t pid, int sig, NMLogDomain log_domain,
715 const char *log_name, guint32 wait_before_kill_msec,
716 NMUtilsKillChildAsyncCb callback, void *user_data)
718 int status = 0, errsv;
720 KillChildAsyncData *data;
721 char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
723 g_return_if_fail (pid > 0);
724 g_return_if_fail (log_name != NULL);
726 /* let's see if the child already terminated... */
727 ret = waitpid (pid, &status, WNOHANG);
729 nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
730 LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
731 _kc_invoke_callback (pid, log_domain, log_name, callback, user_data, TRUE, status);
733 } else if (ret != 0) {
735 /* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
736 if (errsv != ECHILD) {
737 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error while waitpid: %s (%d)",
738 LOG_NAME_ARGS, strerror (errsv), errsv);
739 _kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
744 /* send the first signal. */
745 if (kill (pid, sig) != 0) {
747 /* ESRCH means, process does not exist or is already a zombie. */
748 if (errsv != ESRCH) {
749 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error sending %s: %s (%d)",
750 LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
751 _kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
755 /* let's try again with waitpid, probably there was a race... */
756 ret = waitpid (pid, &status, 0);
758 nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
759 LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
760 _kc_invoke_callback (pid, log_domain, log_name, callback, user_data, TRUE, status);
763 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed due to unexpected return value %ld by waitpid (%s, %d) after sending %s",
764 LOG_NAME_ARGS, (long) ret, strerror (errsv), errsv, _kc_signal_to_string (sig));
765 _kc_invoke_callback (pid, log_domain, log_name, callback, user_data, FALSE, -1);
770 data = _kc_async_data_alloc (pid, log_domain, log_name, callback, user_data);
771 data->async.wait_start_us = nm_utils_get_monotonic_timestamp_us ();
773 if (sig != SIGKILL && wait_before_kill_msec > 0) {
774 data->async.source_timeout_kill_id = g_timeout_add (wait_before_kill_msec, _kc_cb_timeout_grace_period, data);
775 nm_log_dbg (log_domain, "%s: wait for process to terminate after sending %s (send SIGKILL in %ld milliseconds)...",
776 data->log_name, _kc_signal_to_string (sig), (long) wait_before_kill_msec);
778 data->async.source_timeout_kill_id = 0;
779 nm_log_dbg (log_domain, "%s: wait for process to terminate after sending %s...",
780 data->log_name, _kc_signal_to_string (sig));
783 g_child_watch_add (pid, _kc_cb_watch_child, data);
787 _sleep_duration_convert_ms_to_us (guint32 sleep_duration_msec)
789 if (sleep_duration_msec > 0) {
790 guint64 x = (gint64) sleep_duration_msec * (guint64) 1000L;
792 return x < G_MAXULONG ? (gulong) x : G_MAXULONG;
794 return G_USEC_PER_SEC / 20;
797 /* nm_utils_kill_child_sync:
798 * @pid: process id to kill
799 * @sig: signal to sent initially. If 0, no signal is sent. If %SIGKILL, the
800 * second %SIGKILL signal is not sent after @wait_before_kill_msec milliseconds.
801 * @log_domain: log debug information for this domain. Errors and warnings are logged both
802 * as %LOGD_CORE and @log_domain.
803 * @log_name: name of the process to kill for logging.
804 * @child_status: (out) (allow-none): return the exit status of the child, if no error occured.
805 * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
806 * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has not effect.
807 * @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
808 * Set to zero, to use the default (meaning 20 wakeups per seconds).
810 * Kill a child process synchronously and wait. The function first checks if the child already terminated
811 * and if it did, return the exit status. Otherwise send one @sig signal. @sig will always be
812 * sent unless the child already exited. If the child does not exit within @wait_before_kill_msec milliseconds,
813 * the function will send %SIGKILL and waits for the child indefinitly. If @wait_before_kill_msec is zero, no
814 * %SIGKILL signal will be sent.
816 * In case of error, errno is preserved to contain the last reason of failure.
819 nm_utils_kill_child_sync (pid_t pid, int sig, NMLogDomain log_domain, const char *log_name,
820 int *child_status, guint32 wait_before_kill_msec,
821 guint32 sleep_duration_msec)
823 int status = 0, errsv = 0;
825 gboolean success = FALSE;
826 gboolean was_waiting = FALSE, send_kill = FALSE;
827 char buf_exit[KC_EXIT_TO_STRING_BUF_SIZE];
828 char buf_wait[KC_WAITED_TO_STRING];
829 gint64 wait_start_us;
831 g_return_val_if_fail (pid > 0, FALSE);
832 g_return_val_if_fail (log_name != NULL, FALSE);
834 /* check if the child process already terminated... */
835 ret = waitpid (pid, &status, WNOHANG);
837 nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
838 LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
841 } else if (ret != 0) {
843 /* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
844 if (errsv != ECHILD) {
845 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": unexpected error while waitpid: %s (%d)",
846 LOG_NAME_ARGS, strerror (errsv), errsv);
851 /* send first signal @sig */
852 if (kill (pid, sig) != 0) {
854 /* ESRCH means, process does not exist or is already a zombie. */
855 if (errsv != ESRCH) {
856 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed to send %s: %s (%d)",
857 LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
859 /* let's try again with waitpid, probably there was a race... */
860 ret = waitpid (pid, &status, 0);
862 nm_log_dbg (log_domain, LOG_NAME_FMT ": process %ld already terminated %s",
863 LOG_NAME_ARGS, (long) ret, _kc_exit_to_string (buf_exit, status));
867 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed due to unexpected return value %ld by waitpid (%s, %d) after sending %s",
868 LOG_NAME_ARGS, (long) ret, strerror (errsv), errsv, _kc_signal_to_string (sig));
874 wait_start_us = nm_utils_get_monotonic_timestamp_us ();
876 /* wait for the process to terminated... */
877 if (sig != SIGKILL) {
878 gint64 wait_until, now;
879 gulong sleep_time, sleep_duration_usec;
882 sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
883 wait_until = wait_before_kill_msec <= 0 ? 0 : wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
886 ret = waitpid (pid, &status, WNOHANG);
888 nm_log_dbg (log_domain, LOG_NAME_FMT ": after sending %s, process %ld exited %s%s",
889 LOG_NAME_ARGS, _kc_signal_to_string (sig), (long) ret, _kc_exit_to_string (buf_exit, status),
890 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
896 /* ECHILD means, the process is not a child/does not exist or it has SIGCHILD blocked. */
897 if (errsv != ECHILD) {
898 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": after sending %s, waitpid failed with %s (%d)%s",
899 LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv,
900 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
908 now = nm_utils_get_monotonic_timestamp_us ();
909 if (now >= wait_until)
913 nm_log_dbg (log_domain, LOG_NAME_FMT ": waiting up to %ld milliseconds for process to terminate normally after sending %s...",
914 LOG_NAME_ARGS, (long) MAX (wait_before_kill_msec, 0), _kc_signal_to_string (sig));
918 sleep_time = MIN (wait_until - now, sleep_duration_usec);
919 if (loop_count < 20) {
920 /* At the beginning we expect the process to die fast.
921 * Limit the sleep time, the limit doubles with every iteration. */
922 sleep_time = MIN (sleep_time, (((guint64) 1) << loop_count) * G_USEC_PER_SEC / 2000);
925 g_usleep (sleep_time);
928 /* send SIGKILL, if called with @wait_before_kill_msec > 0 */
930 nm_log_dbg (log_domain, LOG_NAME_FMT ": sending SIGKILL...", LOG_NAME_ARGS);
933 if (kill (pid, SIGKILL) != 0) {
935 /* ESRCH means, process does not exist or is already a zombie. */
936 if (errsv != ESRCH) {
937 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": failed to send SIGKILL (after sending %s), %s (%d)",
938 LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
946 nm_log_dbg (log_domain, LOG_NAME_FMT ": waiting for process to terminate after sending %s%s...",
947 LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "");
950 /* block until the child terminates. */
951 while ((ret = waitpid (pid, &status, 0)) <= 0) {
954 if (errsv != EINTR) {
955 nm_log_err (LOGD_CORE | log_domain, LOG_NAME_FMT ": after sending %s%s, waitpid failed with %s (%d)%s",
956 LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "", strerror (errsv), errsv,
957 _kc_waited_to_string (buf_wait, wait_start_us));
962 nm_log_dbg (log_domain, LOG_NAME_FMT ": after sending %s%s, process %ld exited %s%s",
963 LOG_NAME_ARGS, _kc_signal_to_string (sig), send_kill ? " and SIGKILL" : "", (long) ret,
964 _kc_exit_to_string (buf_exit, status), _kc_waited_to_string (buf_wait, wait_start_us));
968 *child_status = success ? status : -1;
969 errno = success ? 0 : errsv;
973 /* nm_utils_kill_process_sync:
974 * @pid: process id to kill
975 * @start_time: the start time of the process to kill (as obtained by nm_utils_get_start_time_for_pid()).
976 * This is an optional argument, to avoid (somewhat) killing the wrong process as @pid
977 * might get recycled. You can pass 0, to not provide this parameter.
978 * @sig: signal to sent initially. If 0, no signal is sent. If %SIGKILL, the
979 * second %SIGKILL signal is not sent after @wait_before_kill_msec milliseconds.
980 * @log_domain: log debug information for this domain. Errors and warnings are logged both
981 * as %LOGD_CORE and @log_domain.
982 * @log_name: name of the process to kill for logging.
983 * @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
984 * to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has no effect.
985 * If @max_wait_msec is set but less then @wait_before_kill_msec, the final %SIGKILL will also
987 * @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
988 * Set to zero, to use the default (meaning 20 wakeups per seconds).
989 * @max_wait_msec: if 0, waits indefinitely until the process is gone (or a zombie). Otherwise, this
990 * is the maxium wait time until returning. If @max_wait_msec is non-zero but smaller then @wait_before_kill_msec,
991 * we will not send a final %SIGKILL.
993 * Kill a non-child process synchronously and wait. This function will not return before the
994 * process with PID @pid is gone, the process is a zombie, or @max_wait_msec expires.
997 nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain log_domain,
998 const char *log_name, guint32 wait_before_kill_msec,
999 guint32 sleep_duration_msec, guint32 max_wait_msec)
1002 guint64 start_time0;
1003 gint64 wait_until_sigkill, now, wait_start_us, max_wait_until;
1004 gulong sleep_time, sleep_duration_usec;
1006 gboolean was_waiting = FALSE;
1007 char buf_wait[KC_WAITED_TO_STRING];
1010 g_return_if_fail (pid > 0);
1011 g_return_if_fail (log_name != NULL);
1012 g_return_if_fail (wait_before_kill_msec > 0);
1014 start_time0 = nm_utils_get_start_time_for_pid (pid, &p_state, NULL);
1015 if (start_time0 == 0) {
1016 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": cannot kill process %ld because it seems already gone",
1017 LOG_NAME_ARGS, (long int) pid);
1020 if (start_time != 0 && start_time != start_time0) {
1021 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": don't kill process %ld because the start_time is unexpectedly %lu instead of %ld",
1022 LOG_NAME_ARGS, (long int) pid, (long unsigned) start_time0, (long unsigned) start_time);
1030 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": cannot kill process %ld because it is already a zombie (%c)",
1031 LOG_NAME_ARGS, (long int) pid, p_state);
1037 if (kill (pid, sig) != 0) {
1039 /* ESRCH means, process does not exist or is already a zombie. */
1040 if (errsv == ESRCH) {
1041 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": failed to send %s because process seems gone",
1042 LOG_NAME_ARGS, _kc_signal_to_string (sig));
1044 nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to send %s: %s (%d)",
1045 LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv);
1050 /* wait for the process to terminated... */
1052 wait_start_us = nm_utils_get_monotonic_timestamp_us ();
1054 sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
1056 wait_until_sigkill = wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
1058 wait_until_sigkill = 0;
1059 if (max_wait_msec > 0) {
1060 max_wait_until = wait_start_us + (((gint64) max_wait_msec) * 1000L);
1061 if (wait_until_sigkill > 0 && wait_until_sigkill > max_wait_msec)
1062 wait_until_sigkill = 0;
1067 start_time = nm_utils_get_start_time_for_pid (pid, &p_state, NULL);
1069 if (start_time != start_time0) {
1070 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone after sending signal %s%s",
1071 LOG_NAME_ARGS, _kc_signal_to_string (sig),
1072 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
1079 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is a zombie (%c) after sending signal %s%s",
1080 LOG_NAME_ARGS, p_state, _kc_signal_to_string (sig),
1081 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
1087 if (kill (pid, 0) != 0) {
1089 /* ESRCH means, process does not exist or is already a zombie. */
1090 if (errsv == ESRCH) {
1091 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone or a zombie after sending signal %s%s",
1092 LOG_NAME_ARGS, _kc_signal_to_string (sig),
1093 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
1095 nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to kill(%ld, 0): %s (%d)%s",
1096 LOG_NAME_ARGS, (long int) pid, strerror (errsv), errsv,
1097 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
1102 sleep_time = sleep_duration_usec;
1103 now = nm_utils_get_monotonic_timestamp_us ();
1105 if ( max_wait_until != 0
1106 && now >= max_wait_until) {
1107 if (wait_until_sigkill != 0) {
1108 /* wait_before_kill_msec is not larger then max_wait_until but we did not yet send
1109 * SIGKILL. Although we already reached our timeout, we don't want to skip sending
1110 * the signal. Even if we don't wait for the process to disappear. */
1111 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
1112 kill (pid, SIGKILL);
1114 nm_log_warn (log_domain, LOG_NAME_PROCESS_FMT ": timeout %u msec waiting for process to disappear (after sending %s)%s",
1115 LOG_NAME_ARGS, (unsigned) max_wait_until, _kc_signal_to_string (sig),
1116 was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
1120 if (wait_until_sigkill != 0) {
1121 if (now >= wait_until_sigkill) {
1122 /* Still not dead. SIGKILL now... */
1123 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
1124 if (kill (pid, SIGKILL) != 0) {
1126 /* ESRCH means, process does not exist or is already a zombie. */
1127 if (errsv != ESRCH) {
1128 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": process is gone or a zombie%s",
1129 LOG_NAME_ARGS, _kc_waited_to_string (buf_wait, wait_start_us));
1131 nm_log_warn (LOGD_CORE | log_domain, LOG_NAME_PROCESS_FMT ": failed to send SIGKILL (after sending %s), %s (%d)%s",
1132 LOG_NAME_ARGS, _kc_signal_to_string (sig), strerror (errsv), errsv,
1133 _kc_waited_to_string (buf_wait, wait_start_us));
1138 wait_until_sigkill = 0;
1139 loop_count = 0; /* reset the loop_count. Now we really expect the process to die quickly. */
1141 sleep_time = MIN (wait_until_sigkill - now, sleep_duration_usec);
1145 if (wait_until_sigkill != 0) {
1146 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear before sending KILL signal after sending %s...",
1147 LOG_NAME_ARGS, (long) wait_before_kill_msec, _kc_signal_to_string (sig));
1148 } else if (max_wait_until != 0) {
1149 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear after sending %s...",
1150 LOG_NAME_ARGS, (long) max_wait_msec, _kc_signal_to_string (sig));
1152 nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting for process to disappear after sending %s...",
1153 LOG_NAME_ARGS, _kc_signal_to_string (sig));
1158 if (loop_count < 20) {
1159 /* At the beginning we expect the process to die fast.
1160 * Limit the sleep time, the limit doubles with every iteration. */
1161 sleep_time = MIN (sleep_time, (((guint64) 1) << loop_count) * G_USEC_PER_SEC / 2000);
1164 g_usleep (sleep_time);
1168 #undef LOG_NAME_PROCESS_FMT
1169 #undef LOG_NAME_ARGS
1171 const char *const NM_PATHS_DEFAULT[] = {
1184 nm_utils_find_helper(const char *progname, const char *try_first, GError **error)
1186 return nm_utils_file_search_in_paths (progname, try_first, NM_PATHS_DEFAULT, G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, error);
1189 /******************************************************************************************/
1191 #define MAC_TAG "mac:"
1192 #define INTERFACE_NAME_TAG "interface-name:"
1193 #define DEVICE_TYPE_TAG "type:"
1194 #define SUBCHAN_TAG "s390-subchannels:"
1195 #define EXCEPT_TAG "except:"
1196 #define MATCH_TAG_CONFIG_NM_VERSION "nm-version:"
1197 #define MATCH_TAG_CONFIG_NM_VERSION_MIN "nm-version-min:"
1198 #define MATCH_TAG_CONFIG_NM_VERSION_MAX "nm-version-max:"
1199 #define MATCH_TAG_CONFIG_ENV "env:"
1201 #define _spec_has_prefix(pspec, tag) \
1203 const char **_spec = (pspec); \
1204 gboolean _has = FALSE; \
1206 if (!g_ascii_strncasecmp (*_spec, (""tag), NM_STRLEN (tag))) { \
1207 *_spec += NM_STRLEN (tag); \
1214 _match_except (const char *spec_str, gboolean *out_except)
1216 if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, NM_STRLEN (EXCEPT_TAG))) {
1217 spec_str += NM_STRLEN (EXCEPT_TAG);
1220 *out_except = FALSE;
1224 NMMatchSpecMatchType
1225 nm_match_spec_device_type (const GSList *specs, const char *device_type)
1228 NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
1230 if (!device_type || !*device_type)
1231 return NM_MATCH_SPEC_NO_MATCH;
1233 for (iter = specs; iter; iter = g_slist_next (iter)) {
1234 const char *spec_str = iter->data;
1237 if (!spec_str || !*spec_str)
1240 spec_str = _match_except (spec_str, &except);
1242 if (g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)) != 0)
1245 spec_str += NM_STRLEN (DEVICE_TYPE_TAG);
1246 if (strcmp (spec_str, device_type) == 0) {
1248 return NM_MATCH_SPEC_NEG_MATCH;
1249 match = NM_MATCH_SPEC_MATCH;
1255 NMMatchSpecMatchType
1256 nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
1259 NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
1261 g_return_val_if_fail (hwaddr != NULL, NM_MATCH_SPEC_NO_MATCH);
1263 for (iter = specs; iter; iter = g_slist_next (iter)) {
1264 const char *spec_str = iter->data;
1267 if (!spec_str || !*spec_str)
1270 spec_str = _match_except (spec_str, &except);
1272 if ( !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))
1273 || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))
1274 || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)))
1277 if (!g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG)))
1278 spec_str += NM_STRLEN (MAC_TAG);
1282 if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1)) {
1284 return NM_MATCH_SPEC_NEG_MATCH;
1285 match = NM_MATCH_SPEC_MATCH;
1291 NMMatchSpecMatchType
1292 nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
1295 NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
1297 g_return_val_if_fail (interface_name != NULL, NM_MATCH_SPEC_NO_MATCH);
1299 for (iter = specs; iter; iter = g_slist_next (iter)) {
1300 const char *spec_str = iter->data;
1301 gboolean use_pattern = FALSE;
1304 if (!spec_str || !*spec_str)
1307 spec_str = _match_except (spec_str, &except);
1309 if ( !g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG))
1310 || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))
1311 || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)))
1314 if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))) {
1315 spec_str += NM_STRLEN (INTERFACE_NAME_TAG);
1316 if (spec_str[0] == '=')
1319 if (spec_str[0] == '~')
1326 if ( !strcmp (spec_str, interface_name)
1327 || (use_pattern && g_pattern_match_simple (spec_str, interface_name))) {
1329 return NM_MATCH_SPEC_NEG_MATCH;
1330 match = NM_MATCH_SPEC_MATCH;
1339 parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
1341 long unsigned int tmp;
1342 char buf[BUFSIZE + 1];
1343 const char *p = subchannels;
1345 char *pa = NULL, *pb = NULL, *pc = NULL;
1347 g_return_val_if_fail (subchannels != NULL, FALSE);
1348 g_return_val_if_fail (a != NULL, FALSE);
1349 g_return_val_if_fail (*a == 0, FALSE);
1350 g_return_val_if_fail (b != NULL, FALSE);
1351 g_return_val_if_fail (*b == 0, FALSE);
1352 g_return_val_if_fail (c != NULL, FALSE);
1353 g_return_val_if_fail (*c == 0, FALSE);
1356 if (!g_ascii_isxdigit (subchannels[0]))
1359 /* Get the first channel */
1360 while (*p && (*p != ',')) {
1361 if (!g_ascii_isxdigit (*p) && (*p != '.'))
1362 return FALSE; /* Invalid chars */
1364 return FALSE; /* Too long to be a subchannel */
1369 /* and grab each of its elements, there should be 3 */
1371 pb = strchr (buf, '.');
1373 pc = strchr (pb + 1, '.');
1374 if (!pa || !pb || !pc)
1377 /* Split the string */
1382 tmp = strtoul (pa, NULL, 16);
1388 tmp = strtoul (pb, NULL, 16);
1394 tmp = strtoul (pc, NULL, 16);
1402 NMMatchSpecMatchType
1403 nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
1406 guint32 a = 0, b = 0, c = 0;
1407 guint32 spec_a = 0, spec_b = 0, spec_c = 0;
1408 NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
1410 g_return_val_if_fail (subchannels != NULL, NM_MATCH_SPEC_NO_MATCH);
1413 return NM_MATCH_SPEC_NO_MATCH;
1415 if (!parse_subchannels (subchannels, &a, &b, &c))
1416 return NM_MATCH_SPEC_NO_MATCH;
1418 for (iter = specs; iter; iter = g_slist_next (iter)) {
1419 const char *spec_str = iter->data;
1422 if (!spec_str || !*spec_str)
1425 spec_str = _match_except (spec_str, &except);
1427 if (!g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))) {
1428 spec_str += NM_STRLEN (SUBCHAN_TAG);
1429 if (parse_subchannels (spec_str, &spec_a, &spec_b, &spec_c)) {
1430 if (a == spec_a && b == spec_b && c == spec_c) {
1432 return NM_MATCH_SPEC_NEG_MATCH;
1433 match = NM_MATCH_SPEC_MATCH;
1442 _match_config_nm_version (const char *str, const char *tag, guint cur_nm_version)
1444 gs_free char *s_ver = NULL;
1445 gs_strfreev char **s_ver_tokens = NULL;
1446 gint v_maj = -1, v_min = -1, v_mic = -1;
1447 guint c_maj = -1, c_min = -1, c_mic = -1;
1450 s_ver = g_strdup (str);
1453 /* Let's be strict with the accepted format here. No funny stuff!! */
1455 if (s_ver[strspn (s_ver, ".0123456789")] != '\0')
1458 s_ver_tokens = g_strsplit (s_ver, ".", -1);
1459 n_tokens = g_strv_length (s_ver_tokens);
1460 if (n_tokens == 0 || n_tokens > 3)
1463 v_maj = _nm_utils_ascii_str_to_int64 (s_ver_tokens[0], 10, 0, 0xFFFF, -1);
1466 if (n_tokens >= 2) {
1467 v_min = _nm_utils_ascii_str_to_int64 (s_ver_tokens[1], 10, 0, 0xFF, -1);
1471 if (n_tokens >= 3) {
1472 v_mic = _nm_utils_ascii_str_to_int64 (s_ver_tokens[2], 10, 0, 0xFF, -1);
1477 nm_decode_version (cur_nm_version, &c_maj, &c_min, &c_mic);
1479 #define CHECK_AND_RETURN_FALSE(cur, val, tag, is_last_digit) \
1481 if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MIN)) { \
1484 } else if (!strcmp (tag, MATCH_TAG_CONFIG_NM_VERSION_MAX)) { \
1491 if (!(is_last_digit)) { \
1497 CHECK_AND_RETURN_FALSE (c_mic, v_mic, tag, TRUE);
1499 CHECK_AND_RETURN_FALSE (c_min, v_min, tag, v_mic < 0);
1500 CHECK_AND_RETURN_FALSE (c_maj, v_maj, tag, v_min < 0);
1504 NMMatchSpecMatchType
1505 nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const char *env)
1508 NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
1511 return NM_MATCH_SPEC_NO_MATCH;
1513 for (iter = specs; iter; iter = g_slist_next (iter)) {
1514 const char *spec_str = iter->data;
1518 if (!spec_str || !*spec_str)
1521 spec_str = _match_except (spec_str, &except);
1523 if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION))
1524 v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version);
1525 else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN))
1526 v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version);
1527 else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX))
1528 v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version);
1529 else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_ENV))
1530 v_match = env && env[0] && !strcmp (spec_str, env);
1536 return NM_MATCH_SPEC_NEG_MATCH;
1537 match = NM_MATCH_SPEC_MATCH;
1544 * nm_match_spec_split:
1545 * @value: the string of device specs
1547 * Splits the specs from the string and returns them as individual
1548 * entires in a #GSList.
1550 * It does not validate any specs, it basically just does a special
1551 * strsplit with ',' or ';' as separators and supporting '\\' as
1554 * Leading and trailing spaces of each entry are removed. But the user
1555 * can preserve them by specifying "\\s has 2 leading" or "has 2 trailing \\s".
1557 * Specs can have a qualifier like "interface-name:". We still don't strip
1558 * any whitespace after the colon, so "interface-name: X" matches an interface
1561 * Returns: (transfer full): the list of device specs.
1564 nm_match_spec_split (const char *value)
1566 char *string_value, *p, *q0, *q;
1567 GSList *pieces = NULL;
1570 if (!value || !*value)
1573 /* Copied from glibs g_key_file_parse_value_as_string() function
1576 string_value = g_new (gchar, strlen (value) + 1);
1578 p = (gchar *) value;
1580 /* skip over leading whitespace */
1581 while (g_ascii_isspace (*p))
1584 q0 = q = string_value;
1609 if (NM_IN_SET (*p, ',', ';'))
1625 if (g_ascii_isspace (*p)) {
1628 } else if (NM_IN_SET (*p, ',', ';')) {
1629 if (q0 < q - trailing_ws)
1630 pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
1634 while (g_ascii_isspace (*p))
1643 if (q0 < q - trailing_ws)
1644 pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
1645 g_free (string_value);
1646 return g_slist_reverse (pieces);
1650 * nm_match_spec_join:
1651 * @specs: the device specs to join
1653 * This is based on g_key_file_parse_string_as_value(), analog to
1654 * nm_match_spec_split() which is based on g_key_file_parse_value_as_string().
1656 * Returns: (transfer full): a joined list of device specs that can be
1657 * split again with nm_match_spec_split(). Note that
1658 * nm_match_spec_split (nm_match_spec_join (specs)) yields the original
1659 * result (which is not true the other way around because there are multiple
1660 * ways to encode the same joined specs string).
1663 nm_match_spec_join (GSList *specs)
1668 str = g_string_new ("");
1670 for (; specs; specs = specs->next) {
1677 g_string_append_c (str, ',');
1679 /* escape leading whitespace */
1682 g_string_append (str, "\\s");
1686 g_string_append (str, "\\t");
1694 g_string_append (str, "\\n");
1697 g_string_append (str, "\\r");
1700 g_string_append (str, "\\\\");
1703 g_string_append (str, "\\,");
1706 g_string_append (str, "\\;");
1709 g_string_append_c (str, *p);
1714 /* escape trailing whitespaces */
1715 switch (str->str[str->len - 1]) {
1717 g_string_overwrite (str, str->len - 1, "\\s");
1720 g_string_overwrite (str, str->len - 1, "\\t");
1725 return g_string_free (str, FALSE);
1728 /*****************************************************************************/
1730 char _nm_utils_to_string_buffer[];
1733 nm_utils_to_string_buffer_init (char **buf, gsize *len)
1736 *buf = _nm_utils_to_string_buffer;
1737 *len = sizeof (_nm_utils_to_string_buffer);
1742 nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len)
1744 nm_utils_to_string_buffer_init (buf, len);
1746 g_strlcpy (*buf, "(null)", *len);
1753 nm_utils_strbuf_append_c (char **buf, gsize *len, char c)
1773 nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str)
1781 if (!str || !*str) {
1790 if (!str || !*str) {
1794 src_len = g_strlcpy (*buf, str, *len);
1795 if (src_len >= *len) {
1796 *buf = &(*buf)[*len];
1799 *buf = &(*buf)[src_len];
1807 nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
1816 va_start (args, format);
1817 retval = g_vsnprintf (p, *len, format, args);
1820 if (retval >= *len) {
1830 nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
1839 #if NM_MORE_ASSERTS > 10
1841 nm_assert (n_descs > 0);
1842 for (i = 0; i < n_descs; i++) {
1845 nm_assert (descs[i].flag && nm_utils_is_power_of_two (descs[i].flag));
1846 nm_assert (descs[i].name && descs[i].name[0]);
1847 for (j = 0; j < i; j++)
1848 nm_assert (descs[j].flag != descs[i].flag);
1852 nm_utils_to_string_buffer_init (&buf, &len);
1863 for (i = 0; flags && i < n_descs; i++) {
1864 if (NM_FLAGS_HAS (flags, descs[i].flag)) {
1865 flags &= ~descs[i].flag;
1868 nm_utils_strbuf_append_c (&p, &len, ',');
1869 nm_utils_strbuf_append_str (&p, &len, descs[i].name);
1874 nm_utils_strbuf_append_c (&p, &len, ',');
1875 nm_utils_strbuf_append (&p, &len, "0x%x", flags);
1880 /*****************************************************************************/
1883 nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id)
1889 g_return_val_if_fail (parent_iface && *parent_iface, NULL);
1893 else if (vlan_id < 100)
1895 else if (vlan_id < 1000)
1898 g_return_val_if_fail (vlan_id < 4095, NULL);
1902 ifname = g_new (char, IFNAMSIZ);
1904 parent_len = strlen (parent_iface);
1905 parent_len = MIN (parent_len, IFNAMSIZ - 1 - id_len);
1906 memcpy (ifname, parent_iface, parent_len);
1907 g_snprintf (&ifname[parent_len], IFNAMSIZ - parent_len, ".%u", vlan_id);
1913 * nm_utils_read_resolv_conf_nameservers():
1914 * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
1916 * Reads all nameservers out of @rc_contents or /etc/resolv.conf and returns
1919 * Returns: a #GPtrArray of 'char *' elements of each nameserver line from
1920 * @contents or resolv.conf
1923 nm_utils_read_resolv_conf_nameservers (const char *rc_contents)
1925 GPtrArray *nameservers = NULL;
1926 char *contents = NULL;
1927 char **lines, **iter;
1931 contents = g_strdup (rc_contents);
1933 if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
1937 nameservers = g_ptr_array_new_full (3, g_free);
1939 lines = g_strsplit_set (contents, "\r\n", -1);
1940 for (iter = lines; *iter; iter++) {
1941 if (!g_str_has_prefix (*iter, "nameserver"))
1943 p = *iter + strlen ("nameserver");
1944 if (!g_ascii_isspace (*p++))
1946 /* Skip intermediate whitespace */
1947 while (g_ascii_isspace (*p))
1951 g_ptr_array_add (nameservers, g_strdup (p));
1960 * nm_utils_read_resolv_conf_dns_options():
1961 * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
1963 * Reads all dns options out of @rc_contents or /etc/resolv.conf and returns
1966 * Returns: a #GPtrArray of 'char *' elements of each option
1969 nm_utils_read_resolv_conf_dns_options (const char *rc_contents)
1971 GPtrArray *options = NULL;
1972 char *contents = NULL;
1973 char **lines, **line_iter;
1974 char **tokens, **token_iter;
1978 contents = g_strdup (rc_contents);
1980 if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
1984 options = g_ptr_array_new_full (3, g_free);
1986 lines = g_strsplit_set (contents, "\r\n", -1);
1987 for (line_iter = lines; *line_iter; line_iter++) {
1988 if (!g_str_has_prefix (*line_iter, "options"))
1990 p = *line_iter + strlen ("options");
1991 if (!g_ascii_isspace (*p++))
1994 tokens = g_strsplit (p, " ", 0);
1995 for (token_iter = tokens; token_iter && *token_iter; token_iter++) {
1996 g_strstrip (*token_iter);
1997 if (!*token_iter[0])
1999 g_ptr_array_add (options, g_strdup (*token_iter));
2001 g_strfreev (tokens);
2010 nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b)
2012 NMSettingConnection *a_s_con, *b_s_con;
2013 gboolean a_ac, b_ac;
2016 a_s_con = nm_connection_get_setting_connection (*a);
2017 b_s_con = nm_connection_get_setting_connection (*b);
2019 a_ac = !!nm_setting_connection_get_autoconnect (a_s_con);
2020 b_ac = !!nm_setting_connection_get_autoconnect (b_s_con);
2022 return ((int) b_ac) - ((int) a_ac);
2026 a_ap = nm_setting_connection_get_autoconnect_priority (a_s_con);
2027 b_ap = nm_setting_connection_get_autoconnect_priority (b_s_con);
2029 return (a_ap > b_ap) ? -1 : 1;
2034 /**************************************************************************/
2036 static gint64 monotonic_timestamp_offset_sec;
2037 static int monotonic_timestamp_clock_mode = 0;
2040 monotonic_timestamp_get (struct timespec *tp)
2045 switch (monotonic_timestamp_clock_mode) {
2047 /* the clock is not yet initialized (first run) */
2048 err = clock_gettime (CLOCK_BOOTTIME, tp);
2049 if (err == -1 && errno == EINVAL) {
2051 err = clock_gettime (CLOCK_MONOTONIC, tp);
2056 /* default, return CLOCK_BOOTTIME */
2057 err = clock_gettime (CLOCK_BOOTTIME, tp);
2060 /* fallback, return CLOCK_MONOTONIC. Kernels prior to 2.6.39
2061 * don't support CLOCK_BOOTTIME. */
2062 err = clock_gettime (CLOCK_MONOTONIC, tp);
2066 g_assert (err == 0); (void)err;
2067 g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND);
2069 if (G_LIKELY (clock_mode == 0))
2072 /* Calculate an offset for the time stamp.
2074 * We always want positive values, because then we can initialize
2075 * a timestamp with 0 and be sure, that it will be less then any
2076 * value nm_utils_get_monotonic_timestamp_*() might return.
2077 * For this to be true also for nm_utils_get_monotonic_timestamp_s() at
2078 * early boot, we have to shift the timestamp to start counting at
2079 * least from 1 second onward.
2081 * Another advantage of shifting is, that this way we make use of the whole 31 bit
2082 * range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_s()
2083 * wraps (~68 years).
2085 monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1;
2086 monotonic_timestamp_clock_mode = clock_mode;
2088 if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) {
2089 time_t now = time (NULL);
2093 strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm));
2094 nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with "
2095 "an offset of %lld.0 seconds to %s (local time is %s)",
2096 tp->tv_nsec, (long long) -monotonic_timestamp_offset_sec,
2097 clock_mode == 1 ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC", s);
2102 * nm_utils_get_monotonic_timestamp_ns:
2104 * Returns: a monotonically increasing time stamp in nanoseconds,
2105 * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
2107 * The returned value will start counting at an undefined point
2108 * in the past and will always be positive.
2110 * All the nm_utils_get_monotonic_timestamp_*s functions return the same
2111 * timestamp but in different scales (nsec, usec, msec, sec).
2114 nm_utils_get_monotonic_timestamp_ns (void)
2116 struct timespec tp = { 0 };
2118 monotonic_timestamp_get (&tp);
2120 /* Although the result will always be positive, we return a signed
2121 * integer, which makes it easier to calculate time differences (when
2122 * you want to subtract signed values).
2124 return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * NM_UTILS_NS_PER_SECOND +
2129 * nm_utils_get_monotonic_timestamp_us:
2131 * Returns: a monotonically increasing time stamp in microseconds,
2132 * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
2134 * The returned value will start counting at an undefined point
2135 * in the past and will always be positive.
2137 * All the nm_utils_get_monotonic_timestamp_*s functions return the same
2138 * timestamp but in different scales (nsec, usec, msec, sec).
2141 nm_utils_get_monotonic_timestamp_us (void)
2143 struct timespec tp = { 0 };
2145 monotonic_timestamp_get (&tp);
2147 /* Although the result will always be positive, we return a signed
2148 * integer, which makes it easier to calculate time differences (when
2149 * you want to subtract signed values).
2151 return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) G_USEC_PER_SEC) +
2152 (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/G_USEC_PER_SEC));
2156 * nm_utils_get_monotonic_timestamp_ms:
2158 * Returns: a monotonically increasing time stamp in milliseconds,
2159 * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
2161 * The returned value will start counting at an undefined point
2162 * in the past and will always be positive.
2164 * All the nm_utils_get_monotonic_timestamp_*s functions return the same
2165 * timestamp but in different scales (nsec, usec, msec, sec).
2168 nm_utils_get_monotonic_timestamp_ms (void)
2170 struct timespec tp = { 0 };
2172 monotonic_timestamp_get (&tp);
2174 /* Although the result will always be positive, we return a signed
2175 * integer, which makes it easier to calculate time differences (when
2176 * you want to subtract signed values).
2178 return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) 1000) +
2179 (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
2183 * nm_utils_get_monotonic_timestamp_s:
2185 * Returns: nm_utils_get_monotonic_timestamp_ms() in seconds (throwing
2186 * away sub second parts). The returned value will always be positive.
2188 * This value wraps after roughly 68 years which should be fine for any
2189 * practical purpose.
2191 * All the nm_utils_get_monotonic_timestamp_*s functions return the same
2192 * timestamp but in different scales (nsec, usec, msec, sec).
2195 nm_utils_get_monotonic_timestamp_s (void)
2197 struct timespec tp = { 0 };
2199 monotonic_timestamp_get (&tp);
2200 return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec);
2207 NMSetting *diff_base_setting;
2208 GHashTable *setting_diff;
2209 } LogConnectionSettingData;
2213 const char *item_name;
2214 NMSettingDiffResult diff_result;
2215 } LogConnectionSettingItem;
2218 _log_connection_sort_hashes_fcn (gconstpointer a, gconstpointer b)
2220 const LogConnectionSettingData *v1 = a;
2221 const LogConnectionSettingData *v2 = b;
2225 s1 = v1->setting ? v1->setting : v1->diff_base_setting;
2226 s2 = v2->setting ? v2->setting : v2->diff_base_setting;
2228 g_assert (s1 && s2);
2230 p1 = _nm_setting_get_setting_priority (s1);
2231 p2 = _nm_setting_get_setting_priority (s2);
2234 return p1 > p2 ? 1 : -1;
2236 return strcmp (v1->name, v2->name);
2240 _log_connection_sort_hashes (NMConnection *connection, NMConnection *diff_base, GHashTable *connection_diff)
2242 GHashTableIter iter;
2243 GArray *sorted_hashes;
2244 LogConnectionSettingData setting_data;
2246 sorted_hashes = g_array_sized_new (TRUE, FALSE, sizeof (LogConnectionSettingData), g_hash_table_size (connection_diff));
2248 g_hash_table_iter_init (&iter, connection_diff);
2249 while (g_hash_table_iter_next (&iter, (gpointer) &setting_data.name, (gpointer) &setting_data.setting_diff)) {
2250 setting_data.setting = nm_connection_get_setting_by_name (connection, setting_data.name);
2251 setting_data.diff_base_setting = diff_base ? nm_connection_get_setting_by_name (diff_base, setting_data.name) : NULL;
2252 g_assert (setting_data.setting || setting_data.diff_base_setting);
2253 g_array_append_val (sorted_hashes, setting_data);
2256 g_array_sort (sorted_hashes, _log_connection_sort_hashes_fcn);
2257 return sorted_hashes;
2261 _log_connection_sort_names_fcn (gconstpointer a, gconstpointer b)
2263 const LogConnectionSettingItem *v1 = a;
2264 const LogConnectionSettingItem *v2 = b;
2266 /* we want to first show the items, that disappeared, then the one that changed and
2267 * then the ones that were added. */
2269 if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) != (v2->diff_result & NM_SETTING_DIFF_RESULT_IN_A))
2270 return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) ? -1 : 1;
2271 if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) != (v2->diff_result & NM_SETTING_DIFF_RESULT_IN_B))
2272 return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) ? 1 : -1;
2273 return strcmp (v1->item_name, v2->item_name);
2277 _log_connection_get_property (NMSetting *setting, const char *name)
2279 GValue val = G_VALUE_INIT;
2282 g_return_val_if_fail (setting, NULL);
2284 if ( !NM_IS_SETTING_VPN (setting)
2285 && nm_setting_get_secret_flags (setting, name, NULL, NULL))
2286 return g_strdup ("****");
2288 if (!_nm_setting_get_property (setting, name, &val))
2289 g_return_val_if_reached (FALSE);
2291 if (G_VALUE_HOLDS_STRING (&val)) {
2294 val_s = g_value_get_string (&val);
2296 /* for NULL, we want to return the unquoted string "NULL". */
2297 s = g_strdup ("NULL");
2299 char *escaped = g_strescape (val_s, "'");
2301 s = g_strdup_printf ("'%s'", escaped);
2305 s = g_strdup_value_contents (&val);
2307 s = g_strdup ("NULL");
2309 char *escaped = g_strescape (s, "'");
2315 g_value_unset(&val);
2320 _log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sorted_names)
2322 GHashTableIter iter;
2323 LogConnectionSettingItem item;
2326 g_array_set_size (sorted_names, 0);
2328 g_hash_table_iter_init (&iter, setting_data->setting_diff);
2329 while (g_hash_table_iter_next (&iter, (gpointer) &item.item_name, &p)) {
2330 item.diff_result = GPOINTER_TO_UINT (p);
2331 g_array_append_val (sorted_names, item);
2334 g_array_sort (sorted_names, _log_connection_sort_names_fcn);
2338 nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix)
2340 GHashTable *connection_diff = NULL;
2341 GArray *sorted_hashes;
2342 GArray *sorted_names = NULL;
2344 gboolean connection_diff_are_same;
2345 gboolean print_header = TRUE;
2346 gboolean print_setting_header;
2349 g_return_if_fail (NM_IS_CONNECTION (connection));
2350 g_return_if_fail (!diff_base || (NM_IS_CONNECTION (diff_base) && diff_base != connection));
2352 /* For VPN setting types, this is broken, because we cannot (generically) print the content of data/secrets. Bummer... */
2354 if (!nm_logging_enabled (level, domain))
2362 connection_diff_are_same = nm_connection_diff (connection, diff_base, NM_SETTING_COMPARE_FLAG_EXACT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT, &connection_diff);
2363 if (connection_diff_are_same) {
2365 nm_log (level, domain, "%sconnection '%s' (%p/%s and %p/%s): no difference", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base));
2367 nm_log (level, domain, "%sconnection '%s' (%p/%s): no properties set", prefix, name, connection, G_OBJECT_TYPE_NAME (connection));
2368 g_assert (!connection_diff);
2372 /* FIXME: it doesn't nicely show the content of NMSettingVpn, becuase nm_connection_diff() does not
2373 * expand the hash values. */
2375 sorted_hashes = _log_connection_sort_hashes (connection, diff_base, connection_diff);
2376 if (sorted_hashes->len <= 0)
2379 sorted_names = g_array_new (FALSE, FALSE, sizeof (LogConnectionSettingItem));
2380 str1 = g_string_new (NULL);
2382 for (i = 0; i < sorted_hashes->len; i++) {
2383 LogConnectionSettingData *setting_data = &g_array_index (sorted_hashes, LogConnectionSettingData, i);
2385 _log_connection_sort_names (setting_data, sorted_names);
2386 print_setting_header = TRUE;
2387 for (j = 0; j < sorted_names->len; j++) {
2388 char *str_conn, *str_diff;
2389 LogConnectionSettingItem *item = &g_array_index (sorted_names, LogConnectionSettingItem, j);
2391 str_conn = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_A)
2392 ? _log_connection_get_property (setting_data->setting, item->item_name)
2394 str_diff = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_B)
2395 ? _log_connection_get_property (setting_data->diff_base_setting, item->item_name)
2399 GError *err_verify = NULL;
2400 const char *path = nm_connection_get_path (connection);
2403 nm_log (level, domain, "%sconnection '%s' (%p/%s < %p/%s)%s%s%s:", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base),
2404 NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
2406 nm_log (level, domain, "%sconnection '%s' (%p/%s):%s%s%s", prefix, name, connection, G_OBJECT_TYPE_NAME (connection),
2407 NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
2409 print_header = FALSE;
2411 if (!nm_connection_verify (connection, &err_verify)) {
2412 nm_log (level, domain, "%sconnection %p does not verify: %s", prefix, connection, err_verify->message);
2413 g_clear_error (&err_verify);
2416 #define _NM_LOG_ALIGN "-25"
2417 if (print_setting_header) {
2419 if (setting_data->setting && setting_data->diff_base_setting)
2420 g_string_printf (str1, "%p < %p", setting_data->setting, setting_data->diff_base_setting);
2421 else if (setting_data->diff_base_setting)
2422 g_string_printf (str1, "*missing* < %p", setting_data->diff_base_setting);
2424 g_string_printf (str1, "%p < *missing*", setting_data->setting);
2425 nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %s ]", prefix, setting_data->name, str1->str);
2427 nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %p ]", prefix, setting_data->name, setting_data->setting);
2428 print_setting_header = FALSE;
2430 g_string_printf (str1, "%s.%s", setting_data->name, item->item_name);
2431 switch (item->diff_result & (NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B)) {
2432 case NM_SETTING_DIFF_RESULT_IN_B:
2433 nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s < %s", prefix, str1->str, str_diff ? str_diff : "NULL");
2435 case NM_SETTING_DIFF_RESULT_IN_A:
2436 nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s", prefix, str1->str, str_conn ? str_conn : "NULL");
2439 nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s < %s", prefix, str1->str, str_conn ? str_conn : "NULL", str_diff ? str_diff : "NULL");
2441 #undef _NM_LOG_ALIGN
2448 g_array_free (sorted_names, TRUE);
2449 g_string_free (str1, TRUE);
2451 g_hash_table_destroy (connection_diff);
2452 g_array_free (sorted_hashes, TRUE);
2456 * nm_utils_monotonic_timestamp_as_boottime:
2457 * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME.
2458 * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if
2459 * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano
2460 * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc.
2462 * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime().
2463 * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick.
2464 * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds.
2465 * If @timestamp is a non-positive, it returns -1. Note that a (valid) monotonic-timestamp
2466 * is always positive.
2468 * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC.
2471 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_per_tick)
2475 /* only support ns-per-tick being a multiple of 10. */
2476 g_return_val_if_fail (timestamp_ns_per_tick == 1
2477 || (timestamp_ns_per_tick > 0 &&
2478 timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND &&
2479 timestamp_ns_per_tick % 10 == 0),
2482 /* Check that the timestamp is in a valid range. */
2483 g_return_val_if_fail (timestamp >= 0, -1);
2485 /* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful
2486 * value (because he has no idea what these timestamps would be). That would be a bug. */
2487 g_return_val_if_fail (monotonic_timestamp_clock_mode != 0, -1);
2489 /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */
2490 offset = monotonic_timestamp_offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick);
2492 /* check for overflow. */
2493 g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64);
2495 return timestamp - offset;
2499 #define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/"
2500 #define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/"
2501 G_STATIC_ASSERT (sizeof (IPV4_PROPERTY_DIR) == sizeof (IPV6_PROPERTY_DIR));
2504 _get_property_path (const char *ifname,
2505 const char *property,
2508 static char path[sizeof (IPV6_PROPERTY_DIR) + IFNAMSIZ + 32];
2511 ifname = NM_ASSERT_VALID_PATH_COMPONENT (ifname);
2512 property = NM_ASSERT_VALID_PATH_COMPONENT (property);
2514 len = g_snprintf (path,
2517 ipv6 ? IPV6_PROPERTY_DIR : IPV4_PROPERTY_DIR,
2520 g_assert (len < sizeof (path) - 1);
2526 * nm_utils_ip6_property_path:
2527 * @ifname: an interface name
2528 * @property: a property name
2530 * Returns the path to IPv6 property @property on @ifname. Note that
2531 * this uses a static buffer.
2534 nm_utils_ip6_property_path (const char *ifname, const char *property)
2536 return _get_property_path (ifname, property, TRUE);
2540 * nm_utils_ip4_property_path:
2541 * @ifname: an interface name
2542 * @property: a property name
2544 * Returns the path to IPv4 property @property on @ifname. Note that
2545 * this uses a static buffer.
2548 nm_utils_ip4_property_path (const char *ifname, const char *property)
2550 return _get_property_path (ifname, property, FALSE);
2554 nm_utils_is_valid_path_component (const char *name)
2558 if (name == NULL || name[0] == '\0')
2561 if (name[0] == '.') {
2562 if (name[1] == '\0')
2564 if (name[1] == '.' && name[2] == '\0')
2571 } while (*(++n) != '\0');
2577 NM_ASSERT_VALID_PATH_COMPONENT (const char *name)
2579 if (G_LIKELY (nm_utils_is_valid_path_component (name)))
2582 nm_log_err (LOGD_CORE, "Failed asserting path component: %s%s%s",
2583 NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)"));
2584 g_error ("FATAL: Failed asserting path component: %s%s%s",
2585 NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)"));
2586 g_assert_not_reached ();
2590 nm_utils_is_specific_hostname (const char *name)
2594 if ( strcmp (name, "(none)")
2595 && strcmp (name, "localhost")
2596 && strcmp (name, "localhost6")
2597 && strcmp (name, "localhost.localdomain")
2598 && strcmp (name, "localhost6.localdomain6"))
2603 /******************************************************************/
2605 /* Returns the "u" (universal/local) bit value for a Modified EUI-64 */
2607 get_gre_eui64_u_bit (guint32 addr)
2609 static const struct {
2613 { 0xff000000 }, { 0x7f000000 }, /* IPv4 loopback */
2614 { 0xf0000000 }, { 0xe0000000 }, /* IPv4 multicast */
2615 { 0xffffff00 }, { 0xe0000000 }, /* IPv4 local multicast */
2616 { 0xffffffff }, { INADDR_BROADCAST }, /* limited broadcast */
2617 { 0xff000000 }, { 0x00000000 }, /* zero net */
2618 { 0xff000000 }, { 0x0a000000 }, /* private 10 (RFC3330) */
2619 { 0xfff00000 }, { 0xac100000 }, /* private 172 */
2620 { 0xffff0000 }, { 0xc0a80000 }, /* private 192 */
2621 { 0xffff0000 }, { 0xa9fe0000 }, /* IPv4 link-local */
2622 { 0xffffff00 }, { 0xc0586300 }, /* anycast 6-to-4 */
2623 { 0xffffff00 }, { 0xc0000200 }, /* test 192 */
2624 { 0xfffe0000 }, { 0xc6120000 }, /* test 198 */
2628 for (i = 0; i < G_N_ELEMENTS (items); i++) {
2629 if ((addr & htonl (items[i].mask)) == htonl (items[i].result))
2630 return 0x00; /* "local" scope */
2632 return 0x02; /* "universal" scope */
2636 * nm_utils_get_ipv6_interface_identifier:
2637 * @link_type: the hardware link type
2638 * @hwaddr: the hardware address of the interface
2639 * @hwaddr_len: the length (in bytes) of @hwaddr
2640 * @dev_id: the device identifier, if any
2641 * @out_iid: on success, filled with the interface identifier; on failure
2644 * Constructs an interface identifier in "Modified EUI-64" format which is
2645 * suitable for constructing IPv6 addresses. Note that the identifier is
2646 * not obscured in any way (eg, RFC3041).
2648 * Returns: %TRUE if the interface identifier could be constructed, %FALSE if
2649 * if could not be constructed.
2652 nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
2653 const guint8 *hwaddr,
2656 NMUtilsIPv6IfaceId *out_iid)
2660 g_return_val_if_fail (hwaddr != NULL, FALSE);
2661 g_return_val_if_fail (hwaddr_len > 0, FALSE);
2662 g_return_val_if_fail (out_iid != NULL, FALSE);
2666 switch (link_type) {
2667 case NM_LINK_TYPE_INFINIBAND:
2668 /* Use the port GUID per http://tools.ietf.org/html/rfc4391#section-8,
2669 * making sure to set the 'u' bit to 1. The GUID is the lower 64 bits
2670 * of the IPoIB interface's hardware address.
2672 g_return_val_if_fail (hwaddr_len == INFINIBAND_ALEN, FALSE);
2673 memcpy (out_iid->id_u8, hwaddr + INFINIBAND_ALEN - 8, 8);
2674 out_iid->id_u8[0] |= 0x02;
2676 case NM_LINK_TYPE_GRE:
2677 case NM_LINK_TYPE_GRETAP:
2678 /* Hardware address is the network-endian IPv4 address */
2679 g_return_val_if_fail (hwaddr_len == 4, FALSE);
2680 addr = * (guint32 *) hwaddr;
2681 out_iid->id_u8[0] = get_gre_eui64_u_bit (addr);
2682 out_iid->id_u8[1] = 0x00;
2683 out_iid->id_u8[2] = 0x5E;
2684 out_iid->id_u8[3] = 0xFE;
2685 memcpy (out_iid->id_u8 + 4, &addr, 4);
2688 if (hwaddr_len == ETH_ALEN) {
2689 /* Translate 48-bit MAC address to a 64-bit Modified EUI-64. See
2690 * http://tools.ietf.org/html/rfc4291#appendix-A and the Linux
2691 * kernel's net/ipv6/addrconf.c::ipv6_generate_eui64() function.
2693 out_iid->id_u8[0] = hwaddr[0];
2694 out_iid->id_u8[1] = hwaddr[1];
2695 out_iid->id_u8[2] = hwaddr[2];
2697 out_iid->id_u8[3] = (dev_id >> 8) & 0xff;
2698 out_iid->id_u8[4] = dev_id & 0xff;
2700 out_iid->id_u8[0] ^= 0x02;
2701 out_iid->id_u8[3] = 0xff;
2702 out_iid->id_u8[4] = 0xfe;
2704 out_iid->id_u8[5] = hwaddr[3];
2705 out_iid->id_u8[6] = hwaddr[4];
2706 out_iid->id_u8[7] = hwaddr[5];
2714 nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
2715 const NMUtilsIPv6IfaceId iid)
2717 memcpy (addr->s6_addr + 8, &iid.id_u8, 8);
2721 nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
2722 const struct in6_addr *addr)
2724 memcpy (iid, addr->s6_addr + 8, 8);
2728 _set_stable_privacy (struct in6_addr *addr,
2739 gsize len = sizeof (digest);
2741 g_return_val_if_fail (key_len, FALSE);
2743 /* Documentation suggests that this can fail.
2744 * Maybe in case of a missing algorithm in crypto library? */
2745 sum = g_checksum_new (G_CHECKSUM_SHA256);
2747 g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
2748 "Can't create a SHA256 hash");
2752 key_len = MIN (key_len, G_MAXUINT32);
2754 g_checksum_update (sum, addr->s6_addr, 8);
2755 g_checksum_update (sum, (const guchar *) ifname, strlen (ifname) + 1);
2758 g_checksum_update (sum, (const guchar *) uuid, strlen (uuid) + 1);
2759 tmp[0] = htonl (dad_counter);
2760 tmp[1] = htonl (key_len);
2761 g_checksum_update (sum, (const guchar *) tmp, sizeof (tmp));
2762 g_checksum_update (sum, (const guchar *) secret_key, key_len);
2764 g_checksum_get_digest (sum, digest, &len);
2765 g_checksum_free (sum);
2767 g_return_val_if_fail (len == 32, FALSE);
2769 memcpy (addr->s6_addr + 8, &digest[0], 8);
2774 #define RFC7217_IDGEN_RETRIES 3
2776 * nm_utils_ipv6_addr_set_stable_privacy:
2778 * Extend the address prefix with an interface identifier using the
2779 * RFC 7217 Stable Privacy mechanism.
2781 * Returns: %TRUE on success, %FALSE if the address could not be generated.
2784 nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
2790 gchar *secret_key = NULL;
2792 gboolean success = FALSE;
2794 if (dad_counter >= RFC7217_IDGEN_RETRIES) {
2795 g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
2796 "Too many DAD collisions");
2800 /* Let's try to load a saved secret key first. */
2801 if (g_file_get_contents (NMSTATEDIR "/secret_key", &secret_key, &key_len, NULL)) {
2803 g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
2804 "Key is too short to be usable");
2808 int urandom = open ("/dev/urandom", O_RDONLY);
2811 if (urandom == -1) {
2812 g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
2813 "Can't open /dev/urandom: %s", strerror (errno));
2817 /* RFC7217 mandates the key SHOULD be at least 128 bits.
2818 * Let's use twice as much. */
2820 secret_key = g_malloc (key_len);
2822 key_mask = umask (0077);
2823 if (read (urandom, secret_key, key_len) == key_len) {
2824 if (!g_file_set_contents (NMSTATEDIR "/secret_key", secret_key, key_len, error)) {
2825 g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key");
2829 g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
2830 "Could not obtain a secret");
2838 success = _set_stable_privacy (addr, ifname, uuid, dad_counter,
2839 secret_key, key_len, error);
2842 g_free (secret_key);
2850 * This can be passed as a child setup function to the g_spawn*() family
2851 * of functions, to ensure that the child is in its own process group
2852 * (and thus, in some situations, will not be killed when NetworkManager
2856 nm_utils_setpgid (gpointer unused G_GNUC_UNUSED)
2865 * nm_utils_g_value_set_strv:
2866 * @value: a #GValue, initialized to store a #G_TYPE_STRV
2867 * @strings: a #GPtrArray of strings
2869 * Converts @strings to a #GStrv and stores it in @value.
2872 nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings)
2877 strv = g_new (char *, strings->len + 1);
2878 for (i = 0; i < strings->len; i++)
2879 strv[i] = g_strdup (strings->pdata[i]);
2882 g_value_take_boxed (value, strv);
2885 /*****************************************************************************/
2888 debug_key_matches (const gchar *key,
2892 /* may not call GLib functions: see note in g_parse_debug_string() */
2893 for (; length; length--, key++, token++) {
2894 char k = (*key == '_') ? '-' : g_ascii_tolower (*key );
2895 char t = (*token == '_') ? '-' : g_ascii_tolower (*token);
2901 return *key == '\0';
2905 * nm_utils_parse_debug_string:
2906 * @string: the string to parse
2907 * @keys: the debug keys
2908 * @nkeys: number of entires in @keys
2910 * Similar to g_parse_debug_string(), but does not special
2911 * case "help" or "all".
2913 * Returns: the flags
2916 nm_utils_parse_debug_string (const char *string,
2917 const GDebugKey *keys,
2928 q = strpbrk (string, ":;, \t");
2930 q = string + strlen (string);
2932 for (i = 0; i < nkeys; i++) {
2933 if (debug_key_matches (keys[i].key, string, q - string))
2934 result |= keys[i].value;
2945 /*****************************************************************************/
2948 nm_utils_ifname_cpy (char *dst, const char *name)
2950 g_return_if_fail (dst);
2951 g_return_if_fail (name && name[0]);
2953 nm_assert (nm_utils_iface_valid_name (name));
2955 if (g_strlcpy (dst, name, IFNAMSIZ) >= IFNAMSIZ)
2956 g_return_if_reached ();
2959 /*****************************************************************************/
2961 #define IPV4LL_NETWORK (htonl (0xA9FE0000L))
2962 #define IPV4LL_NETMASK (htonl (0xFFFF0000L))
2965 nm_utils_ip4_address_is_link_local (in_addr_t addr)
2967 return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK;
2970 /*****************************************************************************/
2973 * Takes a pair @timestamp and @duration, and returns the remaining duration based
2974 * on the new timestamp @now.
2977 nm_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp,
2983 nm_assert (now >= 0);
2985 if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
2986 return NM_PLATFORM_LIFETIME_PERMANENT;
2988 if (timestamp == 0) {
2989 /* if the @timestamp is zero, assume it was just left unset and that the relative
2990 * @duration starts counting from @now. This is convenient to construct an address
2991 * and print it in nm_platform_ip4_address_to_string().
2993 * In general it does not make sense to set the @duration without anchoring at
2994 * @timestamp because you don't know the absolute expiration time when looking
2995 * at the address at a later moment. */
2999 /* For timestamp > now, just accept it and calculate the expected(?) result. */
3000 t = (gint64) timestamp + (gint64) duration - (gint64) now;
3004 if (t >= NM_PLATFORM_LIFETIME_PERMANENT)
3005 return NM_PLATFORM_LIFETIME_PERMANENT - 1;
3010 nm_utils_lifetime_get (guint32 timestamp,
3014 guint32 *out_lifetime,
3015 guint32 *out_preferred)
3017 guint32 t_lifetime, t_preferred;
3019 nm_assert (now >= 0);
3021 if (lifetime == 0) {
3022 *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
3023 *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT;
3025 /* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses
3026 * (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT).
3027 * In that case we also expect that the other fields (timestamp and preferred) are left unset. */
3028 g_return_val_if_fail (timestamp == 0 && preferred == 0, TRUE);
3031 now = nm_utils_get_monotonic_timestamp_s ();
3032 t_lifetime = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now);
3038 t_preferred = nm_utils_lifetime_rebase_relative_time_on_now (timestamp, preferred, now);
3040 *out_lifetime = t_lifetime;
3041 *out_preferred = MIN (t_preferred, t_lifetime);
3043 /* Assert that non-permanent addresses have a (positive) @timestamp. nm_utils_lifetime_rebase_relative_time_on_now()
3044 * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always
3045 * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew.
3047 g_return_val_if_fail ( timestamp != 0
3048 || ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT
3049 && preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE);
3050 g_return_val_if_fail (t_preferred <= t_lifetime, TRUE);