static void nm_audit_log (NMAuditManager *self, GPtrArray *fields, const char *file, guint line, const char *func, gboolean success) { #if HAVE_LIBAUDIT NMAuditManagerPrivate *priv; #endif char *msg; g_return_if_fail (NM_IS_AUDIT_MANAGER (self)); #if HAVE_LIBAUDIT priv = NM_AUDIT_MANAGER_GET_PRIVATE (self); if (priv->auditd_fd >= 0) { msg = build_message (fields, BACKEND_AUDITD); audit_log_user_message (priv->auditd_fd, AUDIT_USYS_CONFIG, msg, NULL, NULL, NULL, success); g_free (msg); } #endif if (nm_logging_enabled (AUDIT_LOG_LEVEL, LOGD_AUDIT)) { msg = build_message (fields, BACKEND_LOG); _NMLOG (AUDIT_LOG_LEVEL, LOGD_AUDIT, "%s", msg); g_free (msg); } }
gboolean nm_audit_manager_audit_enabled (NMAuditManager *self) { #if HAVE_LIBAUDIT NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self); if (priv->auditd_fd >= 0) return TRUE; #endif return nm_logging_enabled (AUDIT_LOG_LEVEL, LOGD_AUDIT); }
static gboolean properties_changed (gpointer data) { GObject *object = G_OBJECT (data); NMPropertiesChangedInfo *info = g_object_get_qdata (object, nm_properties_changed_signal_quark ()); g_assert (info); if (nm_logging_enabled (LOGL_DEBUG, LOGD_DBUS_PROPS)) { GString *buf = g_string_new (NULL); g_hash_table_foreach (info->hash, add_to_string, buf); nm_log_dbg (LOGD_DBUS_PROPS, "%s -> %s", G_OBJECT_TYPE_NAME (object), buf->str); g_string_free (buf, TRUE); } g_signal_emit (object, info->signal_id, 0, info->hash); g_hash_table_remove_all (info->hash); return FALSE; }
/** * nm_utils_match_connection: * @connections: a (optionally pre-sorted) list of connections from which to * find a matching connection to @original based on "inferrable" properties * @original: the #NMConnection to find a match for from @connections * @device_has_carrier: pass %TRUE if the device that generated @original has * a carrier, %FALSE if not * @match_filter_func: a function to check whether each connection from @connections * should be considered for matching. This function should return %TRUE if the * connection should be considered, %FALSE if the connection should be ignored * @match_compat_data: data pointer passed to @match_filter_func * * Checks each connection from @connections until a matching connection is found * considering only setting properties marked with %NM_SETTING_PARAM_INFERRABLE * and checking a few other characteristics like IPv6 method. If the caller * desires some priority order of the connections, @connections should be * sorted before calling this function. * * Returns: the best #NMConnection matching @original, or %NULL if no connection * matches well enough. */ NMConnection * nm_utils_match_connection (GSList *connections, NMConnection *original, gboolean device_has_carrier, gint64 default_v4_metric, gint64 default_v6_metric, NMUtilsMatchFilterFunc match_filter_func, gpointer match_filter_data) { NMConnection *best_match = NULL; GSList *iter; for (iter = connections; iter; iter = iter->next) { NMConnection *candidate = NM_CONNECTION (iter->data); GHashTable *diffs = NULL; if (match_filter_func) { if (!match_filter_func (candidate, match_filter_data)) continue; } if (!nm_connection_diff (original, candidate, NM_SETTING_COMPARE_FLAG_INFERRABLE, &diffs)) { if (!best_match) { best_match = check_possible_match (original, candidate, diffs, device_has_carrier, default_v4_metric, default_v6_metric); } if (!best_match && nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) { GString *diff_string; GHashTableIter s_iter, p_iter; gpointer setting_name, setting; gpointer property_name, value; diff_string = g_string_new (NULL); g_hash_table_iter_init (&s_iter, diffs); while (g_hash_table_iter_next (&s_iter, &setting_name, &setting)) { g_hash_table_iter_init (&p_iter, setting); while (g_hash_table_iter_next (&p_iter, &property_name, &value)) { if (diff_string->len) g_string_append (diff_string, ", "); g_string_append_printf (diff_string, "%s.%s", (char *) setting_name, (char *) property_name); } } nm_log_dbg (LOGD_CORE, "Connection '%s' differs from candidate '%s' in %s", nm_connection_get_id (original), nm_connection_get_id (candidate), diff_string->str); g_string_free (diff_string, TRUE); } g_hash_table_unref (diffs); continue; } /* Exact match */ return candidate; } /* Best match (if any) */ return best_match; }
static gboolean _dispatcher_call (DispatcherAction action, gboolean blocking, NMSettingsConnection *settings_connection, NMConnection *applied_connection, NMDevice *device, NMConnectivityState connectivity_state, const char *vpn_iface, NMProxyConfig *vpn_proxy_config, NMIP4Config *vpn_ip4_config, NMIP6Config *vpn_ip6_config, DispatcherFunc callback, gpointer user_data, guint *out_call_id) { GVariant *connection_dict; GVariantBuilder connection_props; GVariantBuilder device_props; GVariantBuilder device_proxy_props; GVariantBuilder device_ip4_props; GVariantBuilder device_ip6_props; GVariant *device_dhcp4_props = NULL; GVariant *device_dhcp6_props = NULL; GVariantBuilder vpn_proxy_props; GVariantBuilder vpn_ip4_props; GVariantBuilder vpn_ip6_props; DispatchInfo *info = NULL; gboolean success = FALSE; GError *error = NULL; static guint request_counter = 0; guint reqid = ++request_counter; if (!dispatcher_proxy) return FALSE; /* Wrapping protection */ if (G_UNLIKELY (!reqid)) reqid = ++request_counter; g_assert (!blocking || (!callback && !user_data)); _ensure_requests (); /* All actions except 'hostname' and 'connectivity-change' require a device */ if ( action == DISPATCHER_ACTION_HOSTNAME || action == DISPATCHER_ACTION_CONNECTIVITY_CHANGE) { _LOGD ("(%u) dispatching action '%s'%s", reqid, action_to_string (action), blocking ? " (blocking)" : (callback ? " (with callback)" : "")); } else { g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); _LOGD ("(%u) (%s) dispatching action '%s'%s", reqid, vpn_iface ? vpn_iface : nm_device_get_iface (device), action_to_string (action), blocking ? " (blocking)" : (callback ? " (with callback)" : "")); } if (!_get_monitor_by_action(action)->has_scripts) { if (blocking == FALSE && (out_call_id || callback)) { info = g_malloc0 (sizeof (*info)); info->action = action; info->request_id = reqid; info->callback = callback; info->user_data = user_data; info->idle_id = g_idle_add (dispatcher_idle_cb, info); _LOGD ("(%u) simulate request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); } else _LOGD ("(%u) ignoring request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); success = TRUE; goto done; } if (applied_connection) connection_dict = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); else connection_dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); g_variant_builder_init (&connection_props, G_VARIANT_TYPE_VARDICT); if (settings_connection) { const char *connection_path; const char *filename; connection_path = nm_connection_get_path (NM_CONNECTION (settings_connection)); if (connection_path) { g_variant_builder_add (&connection_props, "{sv}", NMD_CONNECTION_PROPS_PATH, g_variant_new_object_path (connection_path)); } filename = nm_settings_connection_get_filename (settings_connection); if (filename) { g_variant_builder_add (&connection_props, "{sv}", NMD_CONNECTION_PROPS_FILENAME, g_variant_new_string (filename)); } if (nm_settings_connection_get_nm_generated_assumed (settings_connection)) { g_variant_builder_add (&connection_props, "{sv}", NMD_CONNECTION_PROPS_EXTERNAL, g_variant_new_boolean (TRUE)); } } g_variant_builder_init (&device_props, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&device_proxy_props, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&device_ip4_props, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&device_ip6_props, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&vpn_proxy_props, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&vpn_ip4_props, G_VARIANT_TYPE_VARDICT); g_variant_builder_init (&vpn_ip6_props, G_VARIANT_TYPE_VARDICT); /* hostname and connectivity-change actions don't send device data */ if ( action != DISPATCHER_ACTION_HOSTNAME && action != DISPATCHER_ACTION_CONNECTIVITY_CHANGE) { fill_device_props (device, &device_props, &device_proxy_props, &device_ip4_props, &device_ip6_props, &device_dhcp4_props, &device_dhcp6_props); if (vpn_ip4_config || vpn_ip6_config) { fill_vpn_props (vpn_proxy_config, vpn_ip4_config, vpn_ip6_config, &vpn_proxy_props, &vpn_ip4_props, &vpn_ip6_props); } } if (!device_dhcp4_props) device_dhcp4_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)); if (!device_dhcp6_props) device_dhcp6_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)); /* Send the action to the dispatcher */ if (blocking) { GVariant *ret; GVariantIter *results; ret = _nm_dbus_proxy_call_sync (dispatcher_proxy, "Action", g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)", action_to_string (action), connection_dict, &connection_props, &device_props, &device_proxy_props, &device_ip4_props, &device_ip6_props, device_dhcp4_props, device_dhcp6_props, nm_connectivity_state_to_string (connectivity_state), vpn_iface ? vpn_iface : "", &vpn_proxy_props, &vpn_ip4_props, &vpn_ip6_props, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)), G_VARIANT_TYPE ("(a(sus))"), G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT, NULL, &error); if (ret) { g_variant_get (ret, "(a(sus))", &results); dispatcher_results_process (reqid, action, results); g_variant_iter_free (results); g_variant_unref (ret); success = TRUE; } else { g_dbus_error_strip_remote_error (error); _LOGW ("(%u) failed: %s", reqid, error->message); g_clear_error (&error); success = FALSE; } } else { info = g_malloc0 (sizeof (*info)); info->action = action; info->request_id = reqid; info->callback = callback; info->user_data = user_data; g_dbus_proxy_call (dispatcher_proxy, "Action", g_variant_new ("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)", action_to_string (action), connection_dict, &connection_props, &device_props, &device_proxy_props, &device_ip4_props, &device_ip6_props, device_dhcp4_props, device_dhcp6_props, nm_connectivity_state_to_string (connectivity_state), vpn_iface ? vpn_iface : "", &vpn_proxy_props, &vpn_ip4_props, &vpn_ip6_props, nm_logging_enabled (LOGL_DEBUG, LOGD_DISPATCH)), G_DBUS_CALL_FLAGS_NONE, CALL_TIMEOUT, NULL, dispatcher_done_cb, info); success = TRUE; } g_variant_unref (device_dhcp4_props); g_variant_unref (device_dhcp6_props); done: if (success && info) { /* Track the request in case of cancelation */ g_hash_table_insert (requests, GUINT_TO_POINTER (info->request_id), info); if (out_call_id) *out_call_id = info->request_id; } else if (out_call_id) *out_call_id = 0; return success; }
static NMCmdLine * create_pppd_cmd_line (NMPPPManager *self, NMSettingPpp *setting, NMSettingPppoe *pppoe, NMSettingAdsl *adsl, const char *ppp_name, GError **err) { NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); const char *pppd_binary = NULL; NMCmdLine *cmd; gboolean ppp_debug; g_return_val_if_fail (setting != NULL, NULL); pppd_binary = nm_utils_find_helper ("pppd", NULL, err); if (!pppd_binary) return NULL; /* Create pppd command line */ cmd = nm_cmd_line_new (); nm_cmd_line_add_string (cmd, pppd_binary); nm_cmd_line_add_string (cmd, "nodetach"); nm_cmd_line_add_string (cmd, "lock"); /* NM handles setting the default route */ nm_cmd_line_add_string (cmd, "nodefaultroute"); /* Allow IPv6 to be configured by IPV6CP */ nm_cmd_line_add_string (cmd, "ipv6"); nm_cmd_line_add_string (cmd, ","); ppp_debug = !!getenv ("NM_PPP_DEBUG"); if (nm_logging_enabled (LOGL_DEBUG, LOGD_PPP)) ppp_debug = TRUE; if (ppp_debug) nm_cmd_line_add_string (cmd, "debug"); if (ppp_name) { nm_cmd_line_add_string (cmd, "user"); nm_cmd_line_add_string (cmd, ppp_name); } if (pppoe) { char *dev_str; const char *pppoe_service; nm_cmd_line_add_string (cmd, "plugin"); nm_cmd_line_add_string (cmd, "rp-pppoe.so"); dev_str = g_strdup_printf ("nic-%s", priv->parent_iface); nm_cmd_line_add_string (cmd, dev_str); g_free (dev_str); pppoe_service = nm_setting_pppoe_get_service (pppoe); if (pppoe_service) { nm_cmd_line_add_string (cmd, "rp_pppoe_service"); nm_cmd_line_add_string (cmd, pppoe_service); } } else if (adsl) { const gchar *protocol = nm_setting_adsl_get_protocol (adsl); if (!strcmp (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) { guint32 vpi = nm_setting_adsl_get_vpi (adsl); guint32 vci = nm_setting_adsl_get_vci (adsl); const char *encaps = nm_setting_adsl_get_encapsulation (adsl); gchar *vpivci; nm_cmd_line_add_string (cmd, "plugin"); nm_cmd_line_add_string (cmd, "pppoatm.so"); vpivci = g_strdup_printf("%d.%d", vpi, vci); nm_cmd_line_add_string (cmd, vpivci); g_free (vpivci); if (g_strcmp0 (encaps, NM_SETTING_ADSL_ENCAPSULATION_LLC) == 0) nm_cmd_line_add_string (cmd, "llc-encaps"); else /*if (g_strcmp0 (encaps, NM_SETTING_ADSL_ENCAPSULATION_VCMUX) == 0)*/ nm_cmd_line_add_string (cmd, "vc-encaps"); } else if (!strcmp (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { nm_cmd_line_add_string (cmd, "plugin"); nm_cmd_line_add_string (cmd, "rp-pppoe.so"); nm_cmd_line_add_string (cmd, priv->parent_iface); } nm_cmd_line_add_string (cmd, "noipdefault"); } else { nm_cmd_line_add_string (cmd, priv->parent_iface); /* Don't send some random address as the local address */ nm_cmd_line_add_string (cmd, "noipdefault"); } if (nm_setting_ppp_get_baud (setting)) nm_cmd_line_add_int (cmd, nm_setting_ppp_get_baud (setting)); /* noauth by default, because we certainly don't have any information * with which to verify anything the peer gives us if we ask it to * authenticate itself, which is what 'auth' really means. */ nm_cmd_line_add_string (cmd, "noauth"); if (nm_setting_ppp_get_refuse_eap (setting)) nm_cmd_line_add_string (cmd, "refuse-eap"); if (nm_setting_ppp_get_refuse_pap (setting)) nm_cmd_line_add_string (cmd, "refuse-pap"); if (nm_setting_ppp_get_refuse_chap (setting)) nm_cmd_line_add_string (cmd, "refuse-chap"); if (nm_setting_ppp_get_refuse_mschap (setting)) nm_cmd_line_add_string (cmd, "refuse-mschap"); if (nm_setting_ppp_get_refuse_mschapv2 (setting)) nm_cmd_line_add_string (cmd, "refuse-mschap-v2"); if (nm_setting_ppp_get_nobsdcomp (setting)) nm_cmd_line_add_string (cmd, "nobsdcomp"); if (nm_setting_ppp_get_no_vj_comp (setting)) nm_cmd_line_add_string (cmd, "novj"); if (nm_setting_ppp_get_nodeflate (setting)) nm_cmd_line_add_string (cmd, "nodeflate"); if (nm_setting_ppp_get_require_mppe (setting)) nm_cmd_line_add_string (cmd, "require-mppe"); if (nm_setting_ppp_get_require_mppe_128 (setting)) nm_cmd_line_add_string (cmd, "require-mppe-128"); if (nm_setting_ppp_get_mppe_stateful (setting)) nm_cmd_line_add_string (cmd, "mppe-stateful"); if (nm_setting_ppp_get_crtscts (setting)) nm_cmd_line_add_string (cmd, "crtscts"); /* Always ask for DNS, we don't have to use them if the connection * overrides the returned servers. */ nm_cmd_line_add_string (cmd, "usepeerdns"); if (nm_setting_ppp_get_mru (setting)) { nm_cmd_line_add_string (cmd, "mru"); nm_cmd_line_add_int (cmd, nm_setting_ppp_get_mru (setting)); } if (nm_setting_ppp_get_mtu (setting)) { nm_cmd_line_add_string (cmd, "mtu"); nm_cmd_line_add_int (cmd, nm_setting_ppp_get_mtu (setting)); } nm_cmd_line_add_string (cmd, "lcp-echo-failure"); nm_cmd_line_add_int (cmd, nm_setting_ppp_get_lcp_echo_failure (setting)); nm_cmd_line_add_string (cmd, "lcp-echo-interval"); nm_cmd_line_add_int (cmd, nm_setting_ppp_get_lcp_echo_interval (setting)); /* Avoid pppd to exit if no traffic going through */ nm_cmd_line_add_string (cmd, "idle"); nm_cmd_line_add_int (cmd, 0); nm_cmd_line_add_string (cmd, "ipparam"); nm_cmd_line_add_string (cmd, nm_exported_object_get_path (NM_EXPORTED_OBJECT (self))); nm_cmd_line_add_string (cmd, "plugin"); nm_cmd_line_add_string (cmd, NM_PPPD_PLUGIN); return cmd; }
static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); const char *iface = nm_device_get_ip_iface (device); gs_unref_ptrarray GPtrArray *argv = NULL; gs_free_error GError *error = NULL; gs_free char *tmp_str = NULL; const char *teamd_binary; const char *config; teamd_binary = nm_utils_find_helper ("teamd", NULL, NULL); if (!teamd_binary) { _LOGW (LOGD_TEAM, "Activation: (team) failed to start teamd: teamd binary not found"); return FALSE; } if (priv->teamd_process_watch || priv->teamd_pid > 0 || priv->tdc) { g_warn_if_reached (); if (!priv->teamd_pid) teamd_kill (self, teamd_binary, NULL); teamd_cleanup (device, TRUE); } /* Start teamd now */ argv = g_ptr_array_new (); g_ptr_array_add (argv, (gpointer) teamd_binary); g_ptr_array_add (argv, (gpointer) "-o"); g_ptr_array_add (argv, (gpointer) "-n"); g_ptr_array_add (argv, (gpointer) "-U"); g_ptr_array_add (argv, (gpointer) "-D"); g_ptr_array_add (argv, (gpointer) "-N"); g_ptr_array_add (argv, (gpointer) "-t"); g_ptr_array_add (argv, (gpointer) iface); config = nm_setting_team_get_config(s_team); if (config) { g_ptr_array_add (argv, (gpointer) "-c"); g_ptr_array_add (argv, (gpointer) config); } if (nm_logging_enabled (LOGL_DEBUG, LOGD_TEAM)) g_ptr_array_add (argv, (gpointer) "-gg"); g_ptr_array_add (argv, NULL); _LOGD (LOGD_TEAM, "running: %s", (tmp_str = g_strjoinv (" ", (gchar **) argv->pdata))); if (!g_spawn_async ("/", (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, nm_utils_setpgid, NULL, &priv->teamd_pid, &error)) { _LOGW (LOGD_TEAM, "Activation: (team) failed to start teamd: %s", error->message); teamd_cleanup (device, TRUE); return FALSE; } /* Start a timeout for teamd to appear at D-Bus */ if (!priv->teamd_timeout) priv->teamd_timeout = g_timeout_add_seconds (5, teamd_timeout_cb, device); /* Monitor the child process so we know when it dies */ priv->teamd_process_watch = g_child_watch_add (priv->teamd_pid, teamd_process_watch_cb, device); _LOGI (LOGD_TEAM, "Activation: (team) started teamd [pid %u]...", (guint) priv->teamd_pid); return TRUE; }
static gboolean teamd_start (NMDevice *dev, NMSettingTeam *s_team, NMDeviceTeamPrivate *priv) { const char *iface = nm_device_get_ip_iface (dev); char *tmp_str; const char *config; const char **teamd_binary = NULL; static const char *teamd_paths[] = { "/usr/bin/teamd", "/usr/local/bin/teamd", NULL }; GPtrArray *argv; GError *error = NULL; gboolean ret; int status; if (priv->teamd_dbus_watch || priv->teamd_process_watch || priv->teamd_pid > 0 || #if WITH_TEAMDCTL priv->tdc || #endif priv->teamd_timeout) { /* FIXME g_assert that this never hits. For now, be more reluctant, and try to recover. */ g_warn_if_reached (); teamd_cleanup (dev, FALSE); } teamd_binary = teamd_paths; while (*teamd_binary != NULL) { if (g_file_test (*teamd_binary, G_FILE_TEST_EXISTS)) break; teamd_binary++; } if (!*teamd_binary) { nm_log_warn (LOGD_TEAM, "Activation (%s) failed to start teamd: teamd binary not found", iface); return FALSE; } /* Kill teamd for same named device first if it is there */ argv = g_ptr_array_new (); g_ptr_array_add (argv, (gpointer) *teamd_binary); g_ptr_array_add (argv, (gpointer) "-k"); g_ptr_array_add (argv, (gpointer) "-t"); g_ptr_array_add (argv, (gpointer) iface); g_ptr_array_add (argv, NULL); tmp_str = g_strjoinv (" ", (gchar **) argv->pdata); nm_log_dbg (LOGD_TEAM, "running: %s", tmp_str); g_free (tmp_str); ret = g_spawn_sync ("/", (char **) argv->pdata, NULL, 0, nm_unblock_posix_signals, NULL, NULL, NULL, &status, &error); g_ptr_array_free (argv, TRUE); /* Start teamd now */ argv = g_ptr_array_new (); g_ptr_array_add (argv, (gpointer) *teamd_binary); g_ptr_array_add (argv, (gpointer) "-o"); g_ptr_array_add (argv, (gpointer) "-n"); g_ptr_array_add (argv, (gpointer) "-U"); g_ptr_array_add (argv, (gpointer) "-D"); g_ptr_array_add (argv, (gpointer) "-t"); g_ptr_array_add (argv, (gpointer) iface); config = nm_setting_team_get_config(s_team); if (config) { g_ptr_array_add (argv, (gpointer) "-c"); g_ptr_array_add (argv, (gpointer) config); } if (nm_logging_enabled (LOGL_DEBUG, LOGD_TEAM)) g_ptr_array_add (argv, (gpointer) "-gg"); g_ptr_array_add (argv, NULL); tmp_str = g_strjoinv (" ", (gchar **) argv->pdata); nm_log_dbg (LOGD_TEAM, "running: %s", tmp_str); g_free (tmp_str); /* Start a timeout for teamd to appear at D-Bus */ priv->teamd_timeout = g_timeout_add_seconds (5, teamd_timeout_cb, dev); /* Register D-Bus name watcher */ tmp_str = g_strdup_printf ("org.libteam.teamd.%s", iface); priv->teamd_dbus_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, tmp_str, G_BUS_NAME_WATCHER_FLAGS_NONE, teamd_dbus_appeared, teamd_dbus_vanished, dev, NULL); g_free (tmp_str); ret = g_spawn_async ("/", (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, &teamd_child_setup, NULL, &priv->teamd_pid, &error); g_ptr_array_free (argv, TRUE); if (!ret) { nm_log_warn (LOGD_TEAM, "Activation (%s) failed to start teamd: %s", iface, error->message); g_clear_error (&error); teamd_cleanup (dev, FALSE); return FALSE; } /* Monitor the child process so we know when it dies */ priv->teamd_process_watch = g_child_watch_add (priv->teamd_pid, teamd_process_watch_cb, dev); nm_log_info (LOGD_TEAM, "Activation (%s) started teamd...", iface); return TRUE; }