1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3 * libnm_glib -- Access network status & information from glib applications
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
19 *
20 * Copyright (C) 2007 - 2008 Novell, Inc.
21 * Copyright (C) 2007 - 2013 Red Hat, Inc.
22 */
23
24 #include <dbus/dbus-glib.h>
25 #include <string.h>
26 #include <nm-utils.h>
27
28 #include "nm-client.h"
29 #include "nm-device-ethernet.h"
30 #include "nm-device-wifi.h"
31 #include "nm-device-private.h"
32 #include "nm-types-private.h"
33 #include "nm-object-private.h"
34 #include "nm-active-connection.h"
35 #include "nm-vpn-connection.h"
36 #include "nm-object-cache.h"
37 #include "nm-dbus-glib-types.h"
38 #include "nm-glib-compat.h"
39
40 void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
41
42 static void nm_client_initable_iface_init (GInitableIface *iface);
43 static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface);
44 static GInitableIface *nm_client_parent_initable_iface;
45 static GAsyncInitableIface *nm_client_parent_async_initable_iface;
46
47 G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT,
48 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init);
49 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init);
50 )
51
52 #define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
53
54 typedef struct {
55 DBusGProxy *client_proxy;
56 DBusGProxy *bus_proxy;
57 gboolean manager_running;
58 char *version;
59 NMState state;
60 gboolean startup;
61 GPtrArray *devices;
62 GPtrArray *active_connections;
63 NMConnectivityState connectivity;
64 NMActiveConnection *primary_connection;
65 NMActiveConnection *activating_connection;
66
67 DBusGProxyCall *perm_call;
68 GHashTable *permissions;
69
70 /* Activations waiting for their NMActiveConnection
71 * to appear and then their callback to be called.
72 */
73 GSList *pending_activations;
74
75 gboolean networking_enabled;
76 gboolean wireless_enabled;
77 gboolean wireless_hw_enabled;
78
79 gboolean wwan_enabled;
80 gboolean wwan_hw_enabled;
81
82 gboolean wimax_enabled;
83 gboolean wimax_hw_enabled;
84 } NMClientPrivate;
85
86 enum {
87 PROP_0,
88 PROP_VERSION,
89 PROP_STATE,
90 PROP_STARTUP,
91 PROP_MANAGER_RUNNING,
92 PROP_NETWORKING_ENABLED,
93 PROP_WIRELESS_ENABLED,
94 PROP_WIRELESS_HARDWARE_ENABLED,
95 PROP_WWAN_ENABLED,
96 PROP_WWAN_HARDWARE_ENABLED,
97 PROP_WIMAX_ENABLED,
98 PROP_WIMAX_HARDWARE_ENABLED,
99 PROP_ACTIVE_CONNECTIONS,
100 PROP_CONNECTIVITY,
101 PROP_PRIMARY_CONNECTION,
102 PROP_ACTIVATING_CONNECTION,
103
104 LAST_PROP
105 };
106
107 enum {
108 DEVICE_ADDED,
109 DEVICE_REMOVED,
110 PERMISSION_CHANGED,
111
112 LAST_SIGNAL
113 };
114
115 static guint signals[LAST_SIGNAL] = { 0 };
116
117 static void proxy_name_owner_changed (DBusGProxy *proxy,
118 const char *name,
119 const char *old_owner,
120 const char *new_owner,
121 gpointer user_data);
122
123 static void client_device_added (NMObject *client, NMObject *device);
124 static void client_device_removed (NMObject *client, NMObject *device);
125
126 /**********************************************************************/
127
128 /**
129 * nm_client_error_quark:
130 *
131 * Registers an error quark for #NMClient if necessary.
132 *
133 * Returns: the error quark used for #NMClient errors.
134 *
135 * Since: 0.9.10
136 **/
137 GQuark
138 nm_client_error_quark (void)
139 {
140 static GQuark quark;
141
142 if (G_UNLIKELY (!quark))
143 quark = g_quark_from_static_string ("nm-client-error-quark");
144 return quark;
145 }
146
147 /**********************************************************************/
148
149 static void
150 nm_client_init (NMClient *client)
151 {
152 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
153
154 priv->state = NM_STATE_UNKNOWN;
155
156 priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
157 }
158
159 static void
160 poke_wireless_devices_with_rf_status (NMClient *client)
161 {
162 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
163 int i;
164
165 for (i = 0; priv->devices && (i < priv->devices->len); i++) {
166 NMDevice *device = g_ptr_array_index (priv->devices, i);
167
168 if (NM_IS_DEVICE_WIFI (device))
169 _nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled);
170 }
171 }
172
173 static void
174 wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
175 {
176 poke_wireless_devices_with_rf_status (NM_CLIENT (object));
177 }
178
179 static void
180 register_properties (NMClient *client)
181 {
182 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
183 const NMPropertiesInfo property_info[] = {
184 { NM_CLIENT_VERSION, &priv->version },
185 { NM_CLIENT_STATE, &priv->state },
186 { NM_CLIENT_STARTUP, &priv->startup },
187 { NM_CLIENT_NETWORKING_ENABLED, &priv->networking_enabled },
188 { NM_CLIENT_WIRELESS_ENABLED, &priv->wireless_enabled },
189 { NM_CLIENT_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled },
190 { NM_CLIENT_WWAN_ENABLED, &priv->wwan_enabled },
191 { NM_CLIENT_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled },
192 { NM_CLIENT_WIMAX_ENABLED, &priv->wimax_enabled },
193 { NM_CLIENT_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled },
194 { NM_CLIENT_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION },
195 { NM_CLIENT_CONNECTIVITY, &priv->connectivity },
196 { NM_CLIENT_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
197 { NM_CLIENT_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
198 { NULL },
199 };
200
201 _nm_object_register_properties (NM_OBJECT (client),
202 priv->client_proxy,
203 property_info);
204
205 _nm_object_register_pseudo_property (NM_OBJECT (client),
206 priv->client_proxy,
207 "Devices",
208 &priv->devices,
209 NM_TYPE_DEVICE,
210 client_device_added,
211 client_device_removed);
212 }
213
214 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network"
215 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi"
216 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan"
217 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX "org.freedesktop.NetworkManager.enable-disable-wimax"
218 #define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake"
219 #define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control"
220 #define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED "org.freedesktop.NetworkManager.wifi.share.protected"
221 #define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open"
222 #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM "org.freedesktop.NetworkManager.settings.modify.system"
223 #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
224 #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
225
226 static NMClientPermission
227 nm_permission_to_client (const char *nm)
228 {
229 if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK))
230 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK;
231 else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI))
232 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI;
233 else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN))
234 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN;
235 else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX))
236 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX;
237 else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE))
238 return NM_CLIENT_PERMISSION_SLEEP_WAKE;
239 else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL))
240 return NM_CLIENT_PERMISSION_NETWORK_CONTROL;
241 else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED))
242 return NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED;
243 else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN))
244 return NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN;
245 else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM))
246 return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM;
247 else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN))
248 return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN;
249 else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME))
250 return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
251
252 return NM_CLIENT_PERMISSION_NONE;
253 }
254
255 static NMClientPermissionResult
256 nm_permission_result_to_client (const char *nm)
257 {
258 if (!strcmp (nm, "yes"))
259 return NM_CLIENT_PERMISSION_RESULT_YES;
260 else if (!strcmp (nm, "no"))
261 return NM_CLIENT_PERMISSION_RESULT_NO;
262 else if (!strcmp (nm, "auth"))
263 return NM_CLIENT_PERMISSION_RESULT_AUTH;
264 return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
265 }
266
267 static void
268 update_permissions (NMClient *self, GHashTable *permissions)
269 {
270 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
271 GHashTableIter iter;
272 gpointer key, value;
273 NMClientPermission perm;
274 NMClientPermissionResult perm_result;
275 GList *keys, *keys_iter;
276
277 /* get list of old permissions for change notification */
278 keys = g_hash_table_get_keys (priv->permissions);
279 g_hash_table_remove_all (priv->permissions);
280
281 if (permissions) {
282 /* Process new permissions */
283 g_hash_table_iter_init (&iter, permissions);
284 while (g_hash_table_iter_next (&iter, &key, &value)) {
285 perm = nm_permission_to_client ((const char *) key);
286 perm_result = nm_permission_result_to_client ((const char *) value);
287 if (perm) {
288 g_hash_table_insert (priv->permissions,
289 GUINT_TO_POINTER (perm),
290 GUINT_TO_POINTER (perm_result));
291
292 /* Remove this permission from the list of previous permissions
293 * we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for
294 * in the change signal since it is still a known permission.
295 */
296 keys = g_list_remove (keys, GUINT_TO_POINTER (perm));
297 }
298 }
299 }
300
301 /* Signal changes in all updated permissions */
302 g_hash_table_iter_init (&iter, priv->permissions);
303 while (g_hash_table_iter_next (&iter, &key, &value)) {
304 g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
305 GPOINTER_TO_UINT (key),
306 GPOINTER_TO_UINT (value));
307 }
308
309 /* And signal changes in all permissions that used to be valid but for
310 * some reason weren't received in the last request (if any).
311 */
312 for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) {
313 g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
314 GPOINTER_TO_UINT (keys_iter->data),
315 NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
316 }
317 g_list_free (keys);
318 }
319
320 static gboolean
321 get_permissions_sync (NMClient *self, GError **error)
322 {
323 gboolean success;
324 GHashTable *permissions = NULL;
325
326 success = dbus_g_proxy_call_with_timeout (NM_CLIENT_GET_PRIVATE (self)->client_proxy,
327 "GetPermissions", 3000, error,
328 G_TYPE_INVALID,
329 DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID);
330 update_permissions (self, success ? permissions : NULL);
331 if (permissions)
332 g_hash_table_destroy (permissions);
333
334 return success;
335 }
336
337 static void
338 get_permissions_reply (DBusGProxy *proxy,
339 DBusGProxyCall *call,
340 gpointer user_data)
341 {
342 NMClient *self = NM_CLIENT (user_data);
343 GHashTable *permissions;
344 GError *error = NULL;
345
346 dbus_g_proxy_end_call (proxy, call, &error,
347 DBUS_TYPE_G_MAP_OF_STRING, &permissions,
348 G_TYPE_INVALID);
349 NM_CLIENT_GET_PRIVATE (self)->perm_call = NULL;
350 update_permissions (NM_CLIENT (user_data), error ? NULL : permissions);
351 g_clear_error (&error);
352 }
353
354 static void
355 client_recheck_permissions (DBusGProxy *proxy, gpointer user_data)
356 {
357 NMClient *self = NM_CLIENT (user_data);
358 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
359
360 if (!priv->perm_call) {
361 priv->perm_call = dbus_g_proxy_begin_call (NM_CLIENT_GET_PRIVATE (self)->client_proxy, "GetPermissions",
362 get_permissions_reply, self, NULL,
363 G_TYPE_INVALID);
364 }
365 }
366
367 /**
368 * nm_client_get_devices:
369 * @client: a #NMClient
370 *
371 * Gets all the known network devices. Use nm_device_get_type() or the
372 * NM_IS_DEVICE_XXXX() functions to determine what kind of device member of the
373 * returned array is, and then you may use device-specific methods such as
374 * nm_device_ethernet_get_hw_address().
375 *
376 * Returns: (transfer none) (element-type NMClient.Device): a #GPtrArray
377 * containing all the #NMDevices. The returned array is owned by the
378 * #NMClient object and should not be modified.
379 **/
380 const GPtrArray *
381 nm_client_get_devices (NMClient *client)
382 {
383 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
384
385 _nm_object_ensure_inited (NM_OBJECT (client));
386
387 return handle_ptr_array_return (NM_CLIENT_GET_PRIVATE (client)->devices);
388 }
389
390 /**
391 * nm_client_get_device_by_path:
392 * @client: a #NMClient
393 * @object_path: the object path to search for
394 *
395 * Gets a #NMDevice from a #NMClient.
396 *
397 * Returns: (transfer none): the #NMDevice for the given @object_path or %NULL if none is found.
398 **/
399 NMDevice *
400 nm_client_get_device_by_path (NMClient *client, const char *object_path)
401 {
402 const GPtrArray *devices;
403 int i;
404 NMDevice *device = NULL;
405
406 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
407 g_return_val_if_fail (object_path, NULL);
408
409 devices = nm_client_get_devices (client);
410 if (!devices)
411 return NULL;
412
413 for (i = 0; i < devices->len; i++) {
414 NMDevice *candidate = g_ptr_array_index (devices, i);
415 if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
416 device = candidate;
417 break;
418 }
419 }
420
421 return device;
422 }
423
424 /**
425 * nm_client_get_device_by_iface:
426 * @client: a #NMClient
427 * @iface: the interface name to search for
428 *
429 * Gets a #NMDevice from a #NMClient.
430 *
431 * Returns: (transfer none): the #NMDevice for the given @iface or %NULL if none is found.
432 **/
433 NMDevice *
434 nm_client_get_device_by_iface (NMClient *client, const char *iface)
435 {
436 const GPtrArray *devices;
437 int i;
438 NMDevice *device = NULL;
439
440 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
441 g_return_val_if_fail (iface, NULL);
442
443 devices = nm_client_get_devices (client);
444 if (!devices)
445 return NULL;
446
447 for (i = 0; i < devices->len; i++) {
448 NMDevice *candidate = g_ptr_array_index (devices, i);
449 if (!strcmp (nm_device_get_iface (candidate), iface)) {
450 device = candidate;
451 break;
452 }
453 }
454
455 return device;
456 }
457
458 typedef struct {
459 NMClient *client;
460 NMClientActivateFn act_fn;
461 NMClientAddActivateFn add_act_fn;
462 char *active_path;
463 char *new_connection_path;
464 guint idle_id;
465 gpointer user_data;
466 } ActivateInfo;
467
468 static void
469 activate_info_free (ActivateInfo *info)
470 {
471 if (info->idle_id)
472 g_source_remove (info->idle_id);
473 g_free (info->active_path);
474 g_free (info->new_connection_path);
475 memset (info, 0, sizeof (*info));
476 g_slice_free (ActivateInfo, info);
477 }
478
479 static void
480 activate_info_complete (ActivateInfo *info,
481 NMActiveConnection *active,
482 GError *error)
483 {
484 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (info->client);
485
486 if (info->act_fn)
487 info->act_fn (info->client, error ? NULL : active, error, info->user_data);
488 else if (info->add_act_fn) {
489 info->add_act_fn (info->client,
490 error ? NULL : active,
491 error ? NULL : info->new_connection_path,
492 error,
493 info->user_data);
494 } else if (error)
495 g_warning ("Device activation failed: (%d) %s", error->code, error->message);
496
497 priv->pending_activations = g_slist_remove (priv->pending_activations, info);
498 }
499
500 static void
501 recheck_pending_activations (NMClient *self, const char *failed_path, GError *error)
502 {
503 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
504 GSList *iter, *next;
505 const GPtrArray *active_connections;
506 gboolean found_in_active = FALSE;
507 gboolean found_in_pending = FALSE;
508 ActivateInfo *ainfo = NULL;
509 int i;
510
511 active_connections = nm_client_get_active_connections (self);
512
513 /* For each pending activation, look for a active connection that has
514 * the pending activation's object path, and call pending connection's
515 * callback.
516 * If the connection to activate doesn't make it to active_connections,
517 * due to an error, we have to call the callback for failed_path.
518 */
519 for (iter = priv->pending_activations; iter; iter = next) {
520 ActivateInfo *info = iter->data;
521
522 next = g_slist_next (iter);
523
524 if (!found_in_pending && failed_path && g_strcmp0 (failed_path, info->active_path) == 0) {
525 found_in_pending = TRUE;
526 ainfo = info;
527 }
528
529 for (i = 0; active_connections && i < active_connections->len; i++) {
530 NMActiveConnection *active = g_ptr_array_index (active_connections, i);
531 const char *active_path = nm_object_get_path (NM_OBJECT (active));
532
533 if (!found_in_active && failed_path && g_strcmp0 (failed_path, active_path) == 0)
534 found_in_active = TRUE;
535
536 if (g_strcmp0 (info->active_path, active_path) == 0) {
537 /* Call the pending activation's callback and it all up */
538 activate_info_complete (info, active, NULL);
539 activate_info_free (info);
540 break;
541 }
542 }
543 }
544
545 if (!found_in_active && found_in_pending) {
546 /* A newly activated connection failed due to some immediate error
547 * and disappeared from active connection list. Make sure the
548 * callback gets called.
549 */
550 activate_info_complete (ainfo, NULL, error);
551 activate_info_free (ainfo);
552 }
553 }
554
555 static void
556 activate_cb (DBusGProxy *proxy,
557 DBusGProxyCall *call,
558 gpointer user_data)
559 {
560 ActivateInfo *info = user_data;
561 char *path;
562 GError *error = NULL;
563
564 dbus_g_proxy_end_call (proxy, call, &error,
565 DBUS_TYPE_G_OBJECT_PATH, &path,
566 G_TYPE_INVALID);
567 if (error) {
568 activate_info_complete (info, NULL, error);
569 activate_info_free (info);
570 g_clear_error (&error);
571 } else {
572 info->active_path = path;
573 recheck_pending_activations (info->client, NULL, NULL);
574 }
575 }
576
577 static gboolean
578 activate_nm_not_running (gpointer user_data)
579 {
580 ActivateInfo *info = user_data;
581 GError *error;
582
583 info->idle_id = 0;
584
585 error = g_error_new_literal (NM_CLIENT_ERROR,
586 NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
587 "NetworkManager is not running");
588 activate_info_complete (info, NULL, error);
589 activate_info_free (info);
590 g_clear_error (&error);
591 return FALSE;
592 }
593
594 /**
595 * nm_client_activate_connection:
596 * @client: a #NMClient
597 * @connection: an #NMConnection
598 * @device: (allow-none): the #NMDevice
599 * @specific_object: (allow-none): the object path of a connection-type-specific
600 * object this activation should use. This parameter is currently ignored for
601 * wired and mobile broadband connections, and the value of %NULL should be used
602 * (ie, no specific object). For WiFi or WiMAX connections, pass the object
603 * path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can
604 * get using nm_object_get_path(), and which will be used to complete the
605 * details of the newly added connection.
606 * @callback: (scope async) (allow-none): the function to call when the call is done
607 * @user_data: (closure): user data to pass to the callback function
608 *
609 * Starts a connection to a particular network using the configuration settings
610 * from @connection and the network device @device. Certain connection types
611 * also take a "specific object" which is the object path of a connection-
612 * specific object, like an #NMAccessPoint for WiFi connections, or an
613 * #NMWimaxNsp for WiMAX connections, to which you wish to connect. If the
614 * specific object is not given, NetworkManager can, in some cases, automatically
615 * determine which network to connect to given the settings in @connection.
616 **/
617 void
618 nm_client_activate_connection (NMClient *client,
619 NMConnection *connection,
620 NMDevice *device,
621 const char *specific_object,
622 NMClientActivateFn callback,
623 gpointer user_data)
624 {
625 NMClientPrivate *priv;
626 ActivateInfo *info;
627
628 g_return_if_fail (NM_IS_CLIENT (client));
629 if (device)
630 g_return_if_fail (NM_IS_DEVICE (device));
631 g_return_if_fail (NM_IS_CONNECTION (connection));
632
633 info = g_slice_new0 (ActivateInfo);
634 info->act_fn = callback;
635 info->user_data = user_data;
636 info->client = client;
637
638 priv = NM_CLIENT_GET_PRIVATE (client);
639 priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
640
641 if (priv->manager_running == FALSE) {
642 info->idle_id = g_idle_add (activate_nm_not_running, info);
643 return;
644 }
645
646 dbus_g_proxy_begin_call (priv->client_proxy, "ActivateConnection",
647 activate_cb, info, NULL,
648 DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
649 DBUS_TYPE_G_OBJECT_PATH, device ? nm_object_get_path (NM_OBJECT (device)) : "/",
650 DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
651 G_TYPE_INVALID);
652 }
653
654 static void
655 add_activate_cb (DBusGProxy *proxy,
656 DBusGProxyCall *call,
657 gpointer user_data)
658 {
659 ActivateInfo *info = user_data;
660 char *connection_path;
661 char *active_path;
662 GError *error = NULL;
663
664 dbus_g_proxy_end_call (proxy, call, &error,
665 DBUS_TYPE_G_OBJECT_PATH, &connection_path,
666 DBUS_TYPE_G_OBJECT_PATH, &active_path,
667 G_TYPE_INVALID);
668 if (error) {
669 activate_info_complete (info, NULL, error);
670 activate_info_free (info);
671 } else {
672 info->new_connection_path = connection_path;
673 info->active_path = active_path;
674 recheck_pending_activations (info->client, NULL, NULL);
675 }
676 }
677
678 /**
679 * nm_client_add_and_activate_connection:
680 * @client: a #NMClient
681 * @partial: (allow-none): an #NMConnection to add; the connection may be
682 * partially filled (or even %NULL) and will be completed by NetworkManager
683 * using the given @device and @specific_object before being added
684 * @device: the #NMDevice
685 * @specific_object: (allow-none): the object path of a connection-type-specific
686 * object this activation should use. This parameter is currently ignored for
687 * wired and mobile broadband connections, and the value of %NULL should be used
688 * (ie, no specific object). For WiFi or WiMAX connections, pass the object
689 * path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can
690 * get using nm_object_get_path(), and which will be used to complete the
691 * details of the newly added connection.
692 * @callback: (scope async) (allow-none): the function to call when the call is done
693 * @user_data: (closure): user data to pass to the callback function
694 *
695 * Adds a new connection using the given details (if any) as a template,
696 * automatically filling in missing settings with the capabilities of the
697 * given device and specific object. The new connection is then activated.
698 * Cannot be used for VPN connections at this time.
699 **/
700 void
701 nm_client_add_and_activate_connection (NMClient *client,
702 NMConnection *partial,
703 NMDevice *device,
704 const char *specific_object,
705 NMClientAddActivateFn callback,
706 gpointer user_data)
707 {
708 NMClientPrivate *priv;
709 ActivateInfo *info;
710 GHashTable *hash = NULL;
711
712 g_return_if_fail (NM_IS_CLIENT (client));
713 g_return_if_fail (NM_IS_DEVICE (device));
714
715 info = g_slice_new0 (ActivateInfo);
716 info->add_act_fn = callback;
717 info->user_data = user_data;
718 info->client = client;
719
720 if (partial)
721 hash = nm_connection_to_hash (partial, NM_SETTING_HASH_FLAG_ALL);
722 if (!hash)
723 hash = g_hash_table_new (g_str_hash, g_str_equal);
724
725 priv = NM_CLIENT_GET_PRIVATE (client);
726 priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
727
728 if (priv->manager_running) {
729 dbus_g_proxy_begin_call (priv->client_proxy, "AddAndActivateConnection",
730 add_activate_cb, info, NULL,
731 DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
732 DBUS_TYPE_G_OBJECT_PATH, nm_object_get_path (NM_OBJECT (device)),
733 DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
734 G_TYPE_INVALID);
735 } else
736 info->idle_id = g_idle_add (activate_nm_not_running, info);
737
738 g_hash_table_unref (hash);
739 }
740
741 static void
742 active_connections_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
743 {
744 recheck_pending_activations (NM_CLIENT (object), NULL, NULL);
745 }
746
747 static void
748 object_creation_failed_cb (GObject *object, GError *error, char *failed_path)
749 {
750 if (error)
751 recheck_pending_activations (NM_CLIENT (object), failed_path, error);
752 }
753
754 /**
755 * nm_client_deactivate_connection:
756 * @client: a #NMClient
757 * @active: the #NMActiveConnection to deactivate
758 *
759 * Deactivates an active #NMActiveConnection.
760 **/
761 void
762 nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active)
763 {
764 NMClientPrivate *priv;
765 const char *path;
766 GError *error = NULL;
767
768 g_return_if_fail (NM_IS_CLIENT (client));
769 g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
770
771 priv = NM_CLIENT_GET_PRIVATE (client);
772 if (!priv->manager_running)
773 return;
774
775 path = nm_object_get_path (NM_OBJECT (active));
(7) Event example_checked: |
Example5: "dbus_g_proxy_call(priv->client_proxy, "DeactivateConnection", &error, dbus_g_object_path_get_g_type(), path, 0UL, 0UL)" has its value checked in "dbus_g_proxy_call(priv->client_proxy, "DeactivateConnection", &error, dbus_g_object_path_get_g_type(), path, 0UL, 0UL)". |
Also see events: |
[check_return][example_checked][example_checked][example_checked][example_checked][unchecked_value] |
776 if (!dbus_g_proxy_call (priv->client_proxy, "DeactivateConnection", &error,
777 DBUS_TYPE_G_OBJECT_PATH, path,
778 G_TYPE_INVALID,
779 G_TYPE_INVALID)) {
780 g_warning ("Could not deactivate connection '%s': %s", path, error->message);
781 g_error_free (error);
782 }
783 }
784
785 /**
786 * nm_client_get_active_connections:
787 * @client: a #NMClient
788 *
789 * Gets the active connections.
790 *
791 * Returns: (transfer none) (element-type NMClient.ActiveConnection): a #GPtrArray
792 * containing all the active #NMActiveConnections.
793 * The returned array is owned by the client and should not be modified.
794 **/
795 const GPtrArray *
796 nm_client_get_active_connections (NMClient *client)
797 {
798 NMClientPrivate *priv;
799
800 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
801
802 _nm_object_ensure_inited (NM_OBJECT (client));
803
804 priv = NM_CLIENT_GET_PRIVATE (client);
805 if (!priv->manager_running)
806 return NULL;
807
808 return handle_ptr_array_return (priv->active_connections);
809 }
810
811 /**
812 * nm_client_wireless_get_enabled:
813 * @client: a #NMClient
814 *
815 * Determines whether the wireless is enabled.
816 *
817 * Returns: %TRUE if wireless is enabled
818 **/
819 gboolean
820 nm_client_wireless_get_enabled (NMClient *client)
821 {
822 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
823
824 _nm_object_ensure_inited (NM_OBJECT (client));
825 return NM_CLIENT_GET_PRIVATE (client)->wireless_enabled;
826 }
827
828 /**
829 * nm_client_wireless_set_enabled:
830 * @client: a #NMClient
831 * @enabled: %TRUE to enable wireless
832 *
833 * Enables or disables wireless devices.
834 **/
835 void
836 nm_client_wireless_set_enabled (NMClient *client, gboolean enabled)
837 {
838 GValue value = G_VALUE_INIT;
839
840 g_return_if_fail (NM_IS_CLIENT (client));
841
842 if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
843 return;
844
845 g_value_init (&value, G_TYPE_BOOLEAN);
846 g_value_set_boolean (&value, enabled);
847
848 _nm_object_set_property (NM_OBJECT (client),
849 NM_DBUS_INTERFACE,
850 "WirelessEnabled",
851 &value);
852 }
853
854 /**
855 * nm_client_wireless_hardware_get_enabled:
856 * @client: a #NMClient
857 *
858 * Determines whether the wireless hardware is enabled.
859 *
860 * Returns: %TRUE if the wireless hardware is enabled
861 **/
862 gboolean
863 nm_client_wireless_hardware_get_enabled (NMClient *client)
864 {
865 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
866
867 _nm_object_ensure_inited (NM_OBJECT (client));
868 return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled;
869 }
870
871 /**
872 * nm_client_wwan_get_enabled:
873 * @client: a #NMClient
874 *
875 * Determines whether WWAN is enabled.
876 *
877 * Returns: %TRUE if WWAN is enabled
878 **/
879 gboolean
880 nm_client_wwan_get_enabled (NMClient *client)
881 {
882 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
883
884 _nm_object_ensure_inited (NM_OBJECT (client));
885 return NM_CLIENT_GET_PRIVATE (client)->wwan_enabled;
886 }
887
888 /**
889 * nm_client_wwan_set_enabled:
890 * @client: a #NMClient
891 * @enabled: %TRUE to enable WWAN
892 *
893 * Enables or disables WWAN devices.
894 **/
895 void
896 nm_client_wwan_set_enabled (NMClient *client, gboolean enabled)
897 {
898 GValue value = G_VALUE_INIT;
899
900 g_return_if_fail (NM_IS_CLIENT (client));
901
902 if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
903 return;
904
905 g_value_init (&value, G_TYPE_BOOLEAN);
906 g_value_set_boolean (&value, enabled);
907
908 _nm_object_set_property (NM_OBJECT (client),
909 NM_DBUS_INTERFACE,
910 "WwanEnabled",
911 &value);
912 }
913
914 /**
915 * nm_client_wwan_hardware_get_enabled:
916 * @client: a #NMClient
917 *
918 * Determines whether the WWAN hardware is enabled.
919 *
920 * Returns: %TRUE if the WWAN hardware is enabled
921 **/
922 gboolean
923 nm_client_wwan_hardware_get_enabled (NMClient *client)
924 {
925 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
926
927 _nm_object_ensure_inited (NM_OBJECT (client));
928 return NM_CLIENT_GET_PRIVATE (client)->wwan_hw_enabled;
929 }
930
931 /**
932 * nm_client_wimax_get_enabled:
933 * @client: a #NMClient
934 *
935 * Determines whether WiMAX is enabled.
936 *
937 * Returns: %TRUE if WiMAX is enabled
938 **/
939 gboolean
940 nm_client_wimax_get_enabled (NMClient *client)
941 {
942 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
943
944 _nm_object_ensure_inited (NM_OBJECT (client));
945 return NM_CLIENT_GET_PRIVATE (client)->wimax_enabled;
946 }
947
948 /**
949 * nm_client_wimax_set_enabled:
950 * @client: a #NMClient
951 * @enabled: %TRUE to enable WiMAX
952 *
953 * Enables or disables WiMAX devices.
954 **/
955 void
956 nm_client_wimax_set_enabled (NMClient *client, gboolean enabled)
957 {
958 GValue value = G_VALUE_INIT;
959
960 g_return_if_fail (NM_IS_CLIENT (client));
961
962 if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
963 return;
964
965 g_value_init (&value, G_TYPE_BOOLEAN);
966 g_value_set_boolean (&value, enabled);
967
968 _nm_object_set_property (NM_OBJECT (client),
969 NM_DBUS_INTERFACE,
970 "WimaxEnabled",
971 &value);
972 }
973
974 /**
975 * nm_client_wimax_hardware_get_enabled:
976 * @client: a #NMClient
977 *
978 * Determines whether the WiMAX hardware is enabled.
979 *
980 * Returns: %TRUE if the WiMAX hardware is enabled
981 **/
982 gboolean
983 nm_client_wimax_hardware_get_enabled (NMClient *client)
984 {
985 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
986
987 _nm_object_ensure_inited (NM_OBJECT (client));
988 return NM_CLIENT_GET_PRIVATE (client)->wimax_hw_enabled;
989 }
990
991 /**
992 * nm_client_get_version:
993 * @client: a #NMClient
994 *
995 * Gets NetworkManager version.
996 *
997 * Returns: string with the version
998 **/
999 const char *
1000 nm_client_get_version (NMClient *client)
1001 {
1002 NMClientPrivate *priv;
1003
1004 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
1005
1006 priv = NM_CLIENT_GET_PRIVATE (client);
1007
1008 _nm_object_ensure_inited (NM_OBJECT (client));
1009
1010 return priv->manager_running ? priv->version : NULL;
1011 }
1012
1013 /**
1014 * nm_client_get_state:
1015 * @client: a #NMClient
1016 *
1017 * Gets the current daemon state.
1018 *
1019 * Returns: the current %NMState
1020 **/
1021 NMState
1022 nm_client_get_state (NMClient *client)
1023 {
1024 g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
1025
1026 _nm_object_ensure_inited (NM_OBJECT (client));
1027
1028 return NM_CLIENT_GET_PRIVATE (client)->state;
1029 }
1030
1031 /**
1032 * nm_client_get_startup:
1033 * @client: a #NMClient
1034 *
1035 * Tests whether the daemon is still in the process of activating
1036 * connections at startup.
1037 *
1038 * Returns: whether the daemon is still starting up
1039 *
1040 * Since: 0.9.10
1041 **/
1042 gboolean
1043 nm_client_get_startup (NMClient *client)
1044 {
1045 g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
1046
1047 _nm_object_ensure_inited (NM_OBJECT (client));
1048
1049 return NM_CLIENT_GET_PRIVATE (client)->startup;
1050 }
1051
1052 /**
1053 * nm_client_networking_get_enabled:
1054 * @client: a #NMClient
1055 *
1056 * Whether networking is enabled or disabled.
1057 *
1058 * Returns: %TRUE if networking is enabled, %FALSE if networking is disabled
1059 **/
1060 gboolean
1061 nm_client_networking_get_enabled (NMClient *client)
1062 {
1063 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1064
1065 _nm_object_ensure_inited (NM_OBJECT (client));
1066 return NM_CLIENT_GET_PRIVATE (client)->networking_enabled;
1067 }
1068
1069 /**
1070 * nm_client_networking_set_enabled:
1071 * @client: a #NMClient
1072 * @enabled: %TRUE to set networking enabled, %FALSE to set networking disabled
1073 *
1074 * Enables or disables networking. When networking is disabled, all controlled
1075 * interfaces are disconnected and deactivated. When networking is enabled,
1076 * all controlled interfaces are available for activation.
1077 **/
1078 void
1079 nm_client_networking_set_enabled (NMClient *client, gboolean enable)
1080 {
1081 GError *err = NULL;
1082
1083 g_return_if_fail (NM_IS_CLIENT (client));
1084
1085 if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
1086 return;
1087
1088 if (!dbus_g_proxy_call (NM_CLIENT_GET_PRIVATE (client)->client_proxy, "Enable", &err,
1089 G_TYPE_BOOLEAN, enable,
1090 G_TYPE_INVALID,
1091 G_TYPE_INVALID)) {
1092 g_warning ("Error enabling/disabling networking: %s", err->message);
1093 g_error_free (err);
1094 }
1095 }
1096
1097 /**
1098 * nm_client_sleep:
1099 * @client: a #NMClient
1100 * @sleep_: %TRUE to put the daemon to sleep
1101 *
1102 * Deprecated; use nm_client_networking_set_enabled() instead.
1103 **/
1104 void
1105 nm_client_sleep (NMClient *client, gboolean sleep_)
1106 {
1107 nm_client_networking_set_enabled (client, !sleep_);
1108 }
1109
1110 /**
1111 * nm_client_get_manager_running:
1112 * @client: a #NMClient
1113 *
1114 * Determines whether the daemon is running.
1115 *
1116 * Returns: %TRUE if the daemon is running
1117 **/
1118 gboolean
1119 nm_client_get_manager_running (NMClient *client)
1120 {
1121 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1122
1123 return NM_CLIENT_GET_PRIVATE (client)->manager_running;
1124 }
1125
1126 /**
1127 * nm_client_get_permission_result:
1128 * @client: a #NMClient
1129 * @permission: the permission for which to return the result, one of #NMClientPermission
1130 *
1131 * Requests the result of a specific permission, which indicates whether the
1132 * client can or cannot perform the action the permission represents
1133 *
1134 * Returns: the permission's result, one of #NMClientPermissionResult
1135 **/
1136 NMClientPermissionResult
1137 nm_client_get_permission_result (NMClient *client, NMClientPermission permission)
1138 {
1139 gpointer result;
1140
1141 g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
1142
1143 result = g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (client)->permissions,
1144 GUINT_TO_POINTER (permission));
1145 return GPOINTER_TO_UINT (result);
1146 }
1147
1148 /**
1149 * nm_client_get_logging:
1150 * @client: a #NMClient
1151 * @level: (allow-none): return location for logging level string
1152 * @domains: (allow-none): return location for log domains string. The string is
1153 * a list of domains separated by ","
1154 * @error: (allow-none): return location for a #GError, or %NULL
1155 *
1156 * Gets NetworkManager current logging level and domains.
1157 *
1158 * Returns: %TRUE on success, %FALSE otherwise
1159 *
1160 * Since: 0.9.8
1161 **/
1162 gboolean
1163 nm_client_get_logging (NMClient *client, char **level, char **domains, GError **error)
1164 {
1165 NMClientPrivate *priv;
1166
1167 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1168 g_return_val_if_fail (level == NULL || *level == NULL, FALSE);
1169 g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE);
1170 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1171
1172 priv = NM_CLIENT_GET_PRIVATE (client);
1173 if (!priv->manager_running) {
1174 g_set_error_literal (error,
1175 NM_CLIENT_ERROR,
1176 NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
1177 "NetworkManager is not running");
1178 return FALSE;
1179 }
1180
1181 if (!level && !domains)
1182 return TRUE;
1183
1184 return dbus_g_proxy_call (priv->client_proxy, "GetLogging", error,
1185 G_TYPE_INVALID,
1186 G_TYPE_STRING, level,
1187 G_TYPE_STRING, domains,
1188 G_TYPE_INVALID);
1189 }
1190
1191 /**
1192 * nm_client_set_logging:
1193 * @client: a #NMClient
1194 * @level: (allow-none): logging level to set (%NULL or an empty string for no change)
1195 * @domains: (allow-none): logging domains to set. The string should be a list of log
1196 * domains separated by ",". (%NULL or an empty string for no change)
1197 * @error: (allow-none): return location for a #GError, or %NULL
1198 *
1199 * Sets NetworkManager logging level and/or domains.
1200 *
1201 * Returns: %TRUE on success, %FALSE otherwise
1202 *
1203 * Since: 0.9.8
1204 **/
1205 gboolean
1206 nm_client_set_logging (NMClient *client, const char *level, const char *domains, GError **error)
1207 {
1208 NMClientPrivate *priv;
1209
1210 g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1211 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1212
1213 priv = NM_CLIENT_GET_PRIVATE (client);
1214 if (!priv->manager_running) {
1215 g_set_error_literal (error,
1216 NM_CLIENT_ERROR,
1217 NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
1218 "NetworkManager is not running");
1219 return FALSE;
1220 }
1221
1222 if (!level && !domains)
1223 return TRUE;
1224
1225 return dbus_g_proxy_call (priv->client_proxy, "SetLogging", error,
1226 G_TYPE_STRING, level ? level : "",
1227 G_TYPE_STRING, domains ? domains : "",
1228 G_TYPE_INVALID,
1229 G_TYPE_INVALID);
1230 }
1231
1232 /**
1233 * nm_client_get_primary_connection:
1234 * @client: an #NMClient
1235 *
1236 * Gets the #NMActiveConnection corresponding to the primary active
1237 * network device.
1238 *
1239 * In particular, when there is no VPN active, or the VPN does not
1240 * have the default route, this returns the active connection that has
1241 * the default route. If there is a VPN active with the default route,
1242 * then this function returns the active connection that contains the
1243 * route to the VPN endpoint.
1244 *
1245 * If there is no default route, or the default route is over a
1246 * non-NetworkManager-recognized device, this will return %NULL.
1247 *
1248 * Returns: (transfer none): the appropriate #NMActiveConnection, if
1249 * any
1250 *
1251 * Since: 0.9.8.6
1252 */
1253 NMActiveConnection *
1254 nm_client_get_primary_connection (NMClient *client)
1255 {
1256 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
1257
1258 _nm_object_ensure_inited (NM_OBJECT (client));
1259 return NM_CLIENT_GET_PRIVATE (client)->primary_connection;
1260 }
1261
1262 /**
1263 * nm_client_get_activating_connection:
1264 * @client: an #NMClient
1265 *
1266 * Gets the #NMActiveConnection corresponding to a
1267 * currently-activating connection that is expected to become the new
1268 * #NMClient:primary-connection upon successful activation.
1269 *
1270 * Returns: (transfer none): the appropriate #NMActiveConnection, if
1271 * any.
1272 *
1273 * Since: 0.9.8.6
1274 */
1275 NMActiveConnection *
1276 nm_client_get_activating_connection (NMClient *client)
1277 {
1278 g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
1279
1280 _nm_object_ensure_inited (NM_OBJECT (client));
1281 return NM_CLIENT_GET_PRIVATE (client)->activating_connection;
1282 }
1283
1284 /****************************************************************/
1285
1286 static void
1287 free_devices (NMClient *client, gboolean emit_signals)
1288 {
1289 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1290 GPtrArray *devices;
1291 NMDevice *device;
1292 int i;
1293
1294 if (!priv->devices)
1295 return;
1296
1297 devices = priv->devices;
1298 priv->devices = NULL;
1299 for (i = 0; i < devices->len; i++) {
1300 device = devices->pdata[i];
1301 if (emit_signals)
1302 g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
1303 g_object_unref (device);
1304 }
1305 g_ptr_array_free (devices, TRUE);
1306 }
1307
1308 static void
1309 free_active_connections (NMClient *client, gboolean emit_signals)
1310 {
1311 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1312 GPtrArray *active_connections;
1313 NMActiveConnection *active_connection;
1314 int i;
1315
1316 if (!priv->active_connections)
1317 return;
1318
1319 active_connections = priv->active_connections;
1320 priv->active_connections = NULL;
1321 for (i = 0; i < active_connections->len; i++) {
1322 active_connection = active_connections->pdata[i];
1323 /* Break circular refs */
1324 g_object_run_dispose (G_OBJECT (active_connection));
1325 g_object_unref (active_connection);
1326 }
1327 g_ptr_array_free (active_connections, TRUE);
1328
1329 if (emit_signals)
1330 g_object_notify (G_OBJECT (client), NM_CLIENT_ACTIVE_CONNECTIONS);
1331 }
1332
1333 static void
1334 updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
1335 {
1336 NMClient *client = NM_CLIENT (user_data);
1337 GError *error = NULL;
1338
1339 if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
1340 g_warning ("%s: error reading NMClient properties: %s", __func__, error->message);
1341 g_error_free (error);
1342 }
1343
1344 _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
1345 }
1346
1347 static void
1348 proxy_name_owner_changed (DBusGProxy *proxy,
1349 const char *name,
1350 const char *old_owner,
1351 const char *new_owner,
1352 gpointer user_data)
1353 {
1354 NMClient *client = NM_CLIENT (user_data);
1355 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1356 gboolean old_good = (old_owner && strlen (old_owner));
1357 gboolean new_good = (new_owner && strlen (new_owner));
1358 gboolean new_running = FALSE;
1359
1360 if (!name || strcmp (name, NM_DBUS_SERVICE))
1361 return;
1362
1363 if (!old_good && new_good)
1364 new_running = TRUE;
1365 else if (old_good && !new_good)
1366 new_running = FALSE;
1367
1368 if (new_running == priv->manager_running)
1369 return;
1370
1371 priv->manager_running = new_running;
1372 if (!priv->manager_running) {
1373 priv->state = NM_STATE_UNKNOWN;
1374 priv->startup = FALSE;
1375 _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
1376 _nm_object_suppress_property_updates (NM_OBJECT (client), TRUE);
1377 poke_wireless_devices_with_rf_status (client);
1378 free_devices (client, TRUE);
1379 free_active_connections (client, TRUE);
1380 update_permissions (client, NULL);
1381 priv->wireless_enabled = FALSE;
1382 priv->wireless_hw_enabled = FALSE;
1383 priv->wwan_enabled = FALSE;
1384 priv->wwan_hw_enabled = FALSE;
1385 priv->wimax_enabled = FALSE;
1386 priv->wimax_hw_enabled = FALSE;
1387 g_free (priv->version);
1388 priv->version = NULL;
1389
1390 /* Clear object cache to ensure bad refcounting by clients doesn't
1391 * keep objects in the cache.
1392 */
1393 _nm_object_cache_clear (NM_OBJECT (client));
1394 } else {
1395 _nm_object_suppress_property_updates (NM_OBJECT (client), FALSE);
1396 _nm_object_reload_properties_async (NM_OBJECT (client), updated_properties, client);
1397 client_recheck_permissions (priv->client_proxy, client);
1398 }
1399 }
1400
1401 static void
1402 client_device_added (NMObject *client, NMObject *device)
1403 {
1404 g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
1405 }
1406
1407 static void
1408 client_device_removed (NMObject *client, NMObject *device)
1409 {
1410 g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
1411 }
1412
1413 /**
1414 * nm_client_get_connectivity:
1415 * @client: an #NMClient
1416 *
1417 * Gets the current network connectivity state. Contrast
1418 * nm_client_check_connectivity() and
1419 * nm_client_check_connectivity_async(), which re-check the
1420 * connectivity state first before returning any information.
1421 *
1422 * Returns: the current connectivity state
1423 * Since: 0.9.8.6
1424 */
1425 NMConnectivityState
1426 nm_client_get_connectivity (NMClient *client)
1427 {
1428 NMClientPrivate *priv;
1429
1430 g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
1431 priv = NM_CLIENT_GET_PRIVATE (client);
1432
1433 _nm_object_ensure_inited (NM_OBJECT (client));
1434
1435 return priv->connectivity;
1436 }
1437
1438 /**
1439 * nm_client_check_connectivity:
1440 * @client: an #NMClient
1441 * @cancellable: a #GCancellable
1442 * @error: return location for a #GError
1443 *
1444 * Updates the network connectivity state and returns the (new)
1445 * current state. Contrast nm_client_get_connectivity(), which returns
1446 * the most recent known state without re-checking.
1447 *
1448 * This is a blocking call; use nm_client_check_connectivity_async()
1449 * if you do not want to block.
1450 *
1451 * Returns: the (new) current connectivity state
1452 * Since: 0.9.8.6
1453 */
1454 NMConnectivityState
1455 nm_client_check_connectivity (NMClient *client,
1456 GCancellable *cancellable,
1457 GError **error)
1458 {
1459 NMClientPrivate *priv;
1460 NMConnectivityState connectivity;
1461
1462 g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN);
1463 priv = NM_CLIENT_GET_PRIVATE (client);
1464
1465 if (!dbus_g_proxy_call (priv->client_proxy, "CheckConnectivity", error,
1466 G_TYPE_INVALID,
1467 G_TYPE_UINT, &connectivity,
1468 G_TYPE_INVALID))
1469 connectivity = NM_CONNECTIVITY_UNKNOWN;
1470
1471 return connectivity;
1472 }
1473
1474 typedef struct {
1475 NMClient *client;
1476 DBusGProxyCall *call;
1477 GCancellable *cancellable;
1478 guint cancelled_id;
1479 NMConnectivityState connectivity;
1480 } CheckConnectivityData;
1481
1482 static void
1483 check_connectivity_data_free (CheckConnectivityData *ccd)
1484 {
1485 if (ccd->cancellable) {
1486 if (ccd->cancelled_id)
1487 g_signal_handler_disconnect (ccd->cancellable, ccd->cancelled_id);
1488 g_object_unref (ccd->cancellable);
1489 }
1490
1491 g_slice_free (CheckConnectivityData, ccd);
1492 }
1493
1494 static void
1495 check_connectivity_cb (DBusGProxy *proxy,
1496 DBusGProxyCall *call,
1497 gpointer user_data)
1498 {
1499 GSimpleAsyncResult *simple = user_data;
1500 CheckConnectivityData *ccd = g_simple_async_result_get_op_res_gpointer (simple);
1501 GError *error = NULL;
1502
1503 if (!dbus_g_proxy_end_call (proxy, call, &error,
1504 G_TYPE_UINT, &ccd->connectivity,
1505 G_TYPE_INVALID))
1506 g_simple_async_result_take_error (simple, error);
1507
1508 g_simple_async_result_complete (simple);
1509 g_object_unref (simple);
1510 }
1511
1512 static void
1513 check_connectivity_cancelled_cb (GCancellable *cancellable,
1514 gpointer user_data)
1515 {
1516 GSimpleAsyncResult *simple = user_data;
1517 CheckConnectivityData *ccd = g_simple_async_result_get_op_res_gpointer (simple);
1518
1519 g_signal_handler_disconnect (cancellable, ccd->cancelled_id);
1520 ccd->cancelled_id = 0;
1521
1522 dbus_g_proxy_cancel_call (NM_CLIENT_GET_PRIVATE (ccd->client)->client_proxy, ccd->call);
1523 g_simple_async_result_complete_in_idle (simple);
1524 }
1525
1526 /**
1527 * nm_client_check_connectivity_async:
1528 * @client: an #NMClient
1529 * @cancellable: a #GCancellable
1530 * @callback: callback to call with the result
1531 * @user_data: data for @callback.
1532 *
1533 * Asynchronously updates the network connectivity state and invokes
1534 * @callback when complete. Contrast nm_client_get_connectivity(),
1535 * which (immediately) returns the most recent known state without
1536 * re-checking, and nm_client_check_connectivity(), which blocks.
1537 *
1538 * Since: 0.9.8.6
1539 */
1540 void
1541 nm_client_check_connectivity_async (NMClient *client,
1542 GCancellable *cancellable,
1543 GAsyncReadyCallback callback,
1544 gpointer user_data)
1545 {
1546 NMClientPrivate *priv;
1547 GSimpleAsyncResult *simple;
1548 CheckConnectivityData *ccd;
1549
1550 g_return_if_fail (NM_IS_CLIENT (client));
1551 priv = NM_CLIENT_GET_PRIVATE (client);
1552
1553 ccd = g_slice_new (CheckConnectivityData);
1554 ccd->client = client;
1555
1556 simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
1557 nm_client_check_connectivity_async);
1558 g_simple_async_result_set_op_res_gpointer (simple, ccd, (GDestroyNotify) check_connectivity_data_free);
1559
1560 if (cancellable) {
1561 ccd->cancellable = g_object_ref (cancellable);
1562 ccd->cancelled_id = g_signal_connect (cancellable, "cancelled",
1563 G_CALLBACK (check_connectivity_cancelled_cb),
1564 simple);
1565 g_simple_async_result_set_check_cancellable (simple, cancellable);
1566 }
1567
1568 ccd->call = dbus_g_proxy_begin_call (priv->client_proxy, "CheckConnectivity",
1569 check_connectivity_cb, simple, NULL,
1570 G_TYPE_INVALID);
1571 }
1572
1573 /**
1574 * nm_client_check_connectivity_finish:
1575 * @client: an #NMClient
1576 * @result: the #GAsyncResult
1577 * @error: return location for a #GError
1578 *
1579 * Retrieves the result of an nm_client_check_connectivity_async()
1580 * call.
1581 *
1582 * Returns: the (new) current connectivity state
1583 * Since: 0.9.8.6
1584 */
1585 NMConnectivityState
1586 nm_client_check_connectivity_finish (NMClient *client,
1587 GAsyncResult *result,
1588 GError **error)
1589 {
1590 GSimpleAsyncResult *simple;
1591 CheckConnectivityData *ccd;
1592
1593 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), nm_client_check_connectivity_async), NM_CONNECTIVITY_UNKNOWN);
1594
1595 simple = G_SIMPLE_ASYNC_RESULT (result);
1596 ccd = g_simple_async_result_get_op_res_gpointer (simple);
1597
1598 if (g_simple_async_result_propagate_error (simple, error))
1599 return NM_CONNECTIVITY_UNKNOWN;
1600
1601 return ccd->connectivity;
1602 }
1603
1604 /****************************************************************/
1605
1606 /**
1607 * nm_client_new:
1608 *
1609 * Creates a new #NMClient.
1610 *
1611 * Note that this will do blocking D-Bus calls to initialize the
1612 * client. You can use nm_client_new_async() if you want to avoid
1613 * that.
1614 *
1615 * NOTE: #NMClient provides information about devices and a mechanism to
1616 * control them. To access and modify network configuration data, use the
1617 * #NMRemoteSettings object.
1618 *
1619 * Returns: a new #NMClient or NULL on an error
1620 **/
1621 NMClient *
1622 nm_client_new (void)
1623 {
1624 NMClient *client;
1625
1626 client = g_object_new (NM_TYPE_CLIENT, NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, NULL);
1627
1628 /* NMObject's constructor() can fail on a D-Bus connection error. So we can
1629 * get NULL here instead of a valid NMClient object.
1630 */
1631 if (client)
1632 _nm_object_ensure_inited (NM_OBJECT (client));
1633
1634 return client;
1635 }
1636
1637 static void
1638 client_inited (GObject *source, GAsyncResult *result, gpointer user_data)
1639 {
1640 GSimpleAsyncResult *simple = user_data;
1641 GError *error = NULL;
1642
1643 if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source), result, &error))
1644 g_simple_async_result_take_error (simple, error);
1645 else
1646 g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
1647 g_simple_async_result_complete (simple);
1648 g_object_unref (simple);
1649 }
1650
1651 /**
1652 * nm_client_new_async:
1653 * @cancellable: a #GCancellable, or %NULL
1654 * @callback: callback to call when the client is created
1655 * @user_data: data for @callback
1656 *
1657 * Creates a new #NMClient and begins asynchronously initializing it.
1658 * @callback will be called when it is done; use
1659 * nm_client_new_finish() to get the result. Note that on an error,
1660 * the callback can be invoked with two first parameters as NULL.
1661 *
1662 * NOTE: #NMClient provides information about devices and a mechanism to
1663 * control them. To access and modify network configuration data, use the
1664 * #NMRemoteSettings object.
1665 **/
1666 void
1667 nm_client_new_async (GCancellable *cancellable,
1668 GAsyncReadyCallback callback,
1669 gpointer user_data)
1670 {
1671 NMClient *client;
1672 GSimpleAsyncResult *simple;
1673
1674 client = g_object_new (NM_TYPE_CLIENT, NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, NULL);
1675 /* When client is NULL, do no continue with initialization and run callback
1676 * directly with result == NULL indicating NMClient creation failure.
1677 */
1678 if (!client) {
1679 callback (NULL, NULL, user_data);
1680 return;
1681 }
1682
1683 simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async);
1684 g_async_initable_init_async (G_ASYNC_INITABLE (client), G_PRIORITY_DEFAULT,
1685 cancellable, client_inited, simple);
1686 }
1687
1688 /**
1689 * nm_client_new_finish:
1690 * @result: a #GAsyncResult
1691 * @error: location for a #GError, or %NULL
1692 *
1693 * Gets the result of an nm_client_new_async() call.
1694 *
1695 * Returns: a new #NMClient, or %NULL on error
1696 **/
1697 NMClient *
1698 nm_client_new_finish (GAsyncResult *result, GError **error)
1699 {
1700 GSimpleAsyncResult *simple;
1701
1702 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1703
1704 if (!result) {
1705 g_set_error_literal (error,
1706 NM_CLIENT_ERROR,
1707 NM_CLIENT_ERROR_UNKNOWN,
1708 "NMClient initialization failed (or you passed NULL 'result' by mistake)");
1709 return NULL;
1710 }
1711
1712 g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_client_new_async), NULL);
1713
1714 simple = G_SIMPLE_ASYNC_RESULT (result);
1715 if (g_simple_async_result_propagate_error (simple, error))
1716 return NULL;
1717 else
1718 return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
1719 }
1720
1721 /*
1722 * Validate D-Bus object path.
1723 * The function is copied and adjusted version of
1724 * g_variant_serialiser_is_object_path() from glib.
1725 * FIXME: The function can be replaced by g_variant_is_object_path()
1726 * when we start using GLib >= 2.24
1727 */
1728 static gboolean
1729 _nm_client_is_object_path (const char *string)
1730 {
1731 gsize i;
1732
1733 if (!g_utf8_validate (string, -1, NULL))
1734 return FALSE;
1735
1736 /* The path must begin with an ASCII '/' (integer 47) character */
1737 if (string[0] != '/')
1738 return FALSE;
1739
1740 for (i = 1; string[i]; i++) {
1741 /* Each element must only contain the ASCII characters
1742 * "[A-Z][a-z][0-9]_"
1743 */
1744 if (g_ascii_isalnum (string[i]) || string[i] == '_')
1745 ;
1746 /* must consist of elements separated by slash characters. */
1747 else if (string[i] == '/') {
1748 /* No element may be the empty string. */
1749 /* Multiple '/' characters cannot occur in sequence. */
1750 if (string[i - 1] == '/')
1751 return FALSE;
1752 } else
1753 return FALSE;
1754 }
1755
1756 /* A trailing '/' character is not allowed unless the path is the
1757 * root path (a single '/' character).
1758 */
1759 if (i > 1 && string[i - 1] == '/')
1760 return FALSE;
1761
1762 return TRUE;
1763 }
1764
1765 /*
1766 * constructor() shouldn't be overriden in most cases, rather constructed()
1767 * method is preferred and more useful.
1768 * But, this serves as a workaround for bindings (use) calling the constructor()
1769 * directly instead of nm_client_new() function, and neither providing
1770 * construction properties. So, we fill "dbus-path" here if it was not specified
1771 * (was set to default value (NULL)).
1772 *
1773 * It allows this python code:
1774 * from gi.repository import NMClient
1775 * nmclient = NMClient.Client()
1776 * print nmclient.get_active_connections()
1777 *
1778 * instead of proper
1779 * nmclient = NMClient.Client().new()
1780 *
1781 * Note:
1782 * A nice overview of GObject construction is here:
1783 * http://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction
1784 * It is much better explanation than the official docs
1785 * http://developer.gnome.org/gobject/unstable/chapter-gobject.html#gobject-instantiation
1786 */
1787 static GObject*
1788 constructor (GType type,
1789 guint n_construct_params,
1790 GObjectConstructParam *construct_params)
1791 {
1792 GObject *object;
1793 guint i;
1794 const char *dbus_path;
1795
1796 for (i = 0; i < n_construct_params; i++) {
1797 if (strcmp (construct_params[i].pspec->name, NM_OBJECT_DBUS_PATH) == 0) {
1798 dbus_path = g_value_get_string (construct_params[i].value);
1799 if (dbus_path == NULL) {
1800 g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH);
1801 } else {
1802 if (!_nm_client_is_object_path (dbus_path)) {
1803 g_warning ("Passsed D-Bus object path '%s' is invalid; using default '%s' instead",
1804 dbus_path, NM_DBUS_PATH);
1805 g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH);
1806 }
1807 }
1808 break;
1809 }
1810 }
1811
1812 object = G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
1813 n_construct_params,
1814 construct_params);
1815
1816 return object;
1817 }
1818
1819 static void
1820 constructed (GObject *object)
1821 {
1822 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
1823
1824 nm_utils_init (NULL);
1825
1826 G_OBJECT_CLASS (nm_client_parent_class)->constructed (object);
1827
1828 priv->client_proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE);
1829
1830 register_properties (NM_CLIENT (object));
1831
1832 /* Permissions */
1833 dbus_g_proxy_add_signal (priv->client_proxy, "CheckPermissions", G_TYPE_INVALID);
1834 dbus_g_proxy_connect_signal (priv->client_proxy,
1835 "CheckPermissions",
1836 G_CALLBACK (client_recheck_permissions),
1837 object,
1838 NULL);
1839
1840 if (_nm_object_is_connection_private (NM_OBJECT (object)))
1841 priv->manager_running = TRUE;
1842 else {
1843 priv->bus_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
1844 DBUS_SERVICE_DBUS,
1845 DBUS_PATH_DBUS,
1846 DBUS_INTERFACE_DBUS);
1847 g_assert (priv->bus_proxy);
1848
1849 dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged",
1850 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
1851 G_TYPE_INVALID);
1852 dbus_g_proxy_connect_signal (priv->bus_proxy,
1853 "NameOwnerChanged",
1854 G_CALLBACK (proxy_name_owner_changed),
1855 object, NULL);
1856 }
1857
1858 g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED,
1859 G_CALLBACK (wireless_enabled_cb), NULL);
1860
1861 g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
1862 G_CALLBACK (active_connections_changed_cb), NULL);
1863
1864 g_signal_connect (object, "object-creation-failed",
1865 G_CALLBACK (object_creation_failed_cb), NULL);
1866 }
1867
1868 static gboolean
1869 init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
1870 {
1871 NMClient *client = NM_CLIENT (initable);
1872 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1873
1874 if (!nm_client_parent_initable_iface->init (initable, cancellable, error))
1875 return FALSE;
1876
1877 if (!_nm_object_is_connection_private (NM_OBJECT (client))) {
1878 if (!dbus_g_proxy_call (priv->bus_proxy,
1879 "NameHasOwner", error,
1880 G_TYPE_STRING, NM_DBUS_SERVICE,
1881 G_TYPE_INVALID,
1882 G_TYPE_BOOLEAN, &priv->manager_running,
1883 G_TYPE_INVALID))
1884 return FALSE;
1885 }
1886
1887 if (priv->manager_running && !get_permissions_sync (client, error))
1888 return FALSE;
1889
1890 return TRUE;
1891 }
1892
1893 typedef struct {
1894 NMClient *client;
1895 GSimpleAsyncResult *result;
1896 gboolean properties_pending;
1897 gboolean permissions_pending;
1898 } NMClientInitData;
1899
1900 static void
1901 init_async_complete (NMClientInitData *init_data)
1902 {
1903 if (init_data->properties_pending || init_data->permissions_pending)
1904 return;
1905
1906 g_simple_async_result_complete (init_data->result);
1907 g_object_unref (init_data->result);
1908 g_slice_free (NMClientInitData, init_data);
1909 }
1910
1911 static void
1912 init_async_got_permissions (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
1913 {
1914 NMClientInitData *init_data = user_data;
1915 GHashTable *permissions;
1916 GError *error = NULL;
1917
1918 dbus_g_proxy_end_call (proxy, call, &error,
1919 DBUS_TYPE_G_MAP_OF_STRING, &permissions,
1920 G_TYPE_INVALID);
1921 update_permissions (init_data->client, error ? NULL : permissions);
1922 g_clear_error (&error);
1923
1924 init_data->permissions_pending = FALSE;
1925 init_async_complete (init_data);
1926 }
1927
1928 static void
1929 init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_data)
1930 {
1931 NMClientInitData *init_data = user_data;
1932 GError *error = NULL;
1933
1934 if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error))
1935 g_simple_async_result_take_error (init_data->result, error);
1936
1937 init_data->properties_pending = FALSE;
1938 init_async_complete (init_data);
1939 }
1940
1941 static void
1942 finish_init (NMClientInitData *init_data)
1943 {
1944 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
1945
1946 nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client),
1947 G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */
1948 init_async_got_properties, init_data);
1949 init_data->properties_pending = TRUE;
1950
1951 dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions",
1952 init_async_got_permissions, init_data, NULL,
1953 G_TYPE_INVALID);
1954 init_data->permissions_pending = TRUE;
1955 }
1956
1957 static void
1958 init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
1959 gpointer user_data)
1960 {
1961 NMClientInitData *init_data = user_data;
1962 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
1963 GError *error = NULL;
1964
1965 if (!dbus_g_proxy_end_call (proxy, call, &error,
1966 G_TYPE_BOOLEAN, &priv->manager_running,
1967 G_TYPE_INVALID)) {
1968 g_simple_async_result_take_error (init_data->result, error);
1969 init_async_complete (init_data);
1970 return;
1971 }
1972
1973 if (!priv->manager_running) {
1974 init_async_complete (init_data);
1975 return;
1976 }
1977
1978 finish_init (init_data);
1979 }
1980
1981 static void
1982 init_async (GAsyncInitable *initable, int io_priority,
1983 GCancellable *cancellable, GAsyncReadyCallback callback,
1984 gpointer user_data)
1985 {
1986 NMClientInitData *init_data;
1987 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable);
1988
1989 init_data = g_slice_new0 (NMClientInitData);
1990 init_data->client = NM_CLIENT (initable);
1991 init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
1992 user_data, init_async);
1993 g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
1994
1995 if (_nm_object_is_connection_private (NM_OBJECT (init_data->client)))
1996 finish_init (init_data);
1997 else {
1998 /* Check if NM is running */
1999 dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner",
2000 init_async_got_manager_running,
2001 init_data, NULL,
2002 G_TYPE_STRING, NM_DBUS_SERVICE,
2003 G_TYPE_INVALID);
2004 }
2005 }
2006
2007 static gboolean
2008 init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
2009 {
2010 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
2011
2012 if (g_simple_async_result_propagate_error (simple, error))
2013 return FALSE;
2014 else
2015 return TRUE;
2016 }
2017
2018 static void
2019 dispose (GObject *object)
2020 {
2021 NMClient *client = NM_CLIENT (object);
2022 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
2023
2024 if (priv->perm_call) {
2025 dbus_g_proxy_cancel_call (priv->client_proxy, priv->perm_call);
2026 priv->perm_call = NULL;
2027 }
2028
2029 g_clear_object (&priv->client_proxy);
2030 g_clear_object (&priv->bus_proxy);
2031
2032 free_devices (client, FALSE);
2033 free_active_connections (client, FALSE);
2034 g_clear_object (&priv->primary_connection);
2035 g_clear_object (&priv->activating_connection);
2036
2037 g_slist_free_full (priv->pending_activations, (GDestroyNotify) activate_info_free);
2038 priv->pending_activations = NULL;
2039
2040 g_hash_table_destroy (priv->permissions);
2041 priv->permissions = NULL;
2042
2043 G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
2044 }
2045
2046 static void
2047 finalize (GObject *object)
2048 {
2049 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
2050
2051 g_free (priv->version);
2052
2053 G_OBJECT_CLASS (nm_client_parent_class)->finalize (object);
2054 }
2055
2056 static void
2057 set_property (GObject *object, guint prop_id,
2058 const GValue *value, GParamSpec *pspec)
2059 {
2060 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
2061 gboolean b;
2062
2063 switch (prop_id) {
2064 case PROP_NETWORKING_ENABLED:
2065 b = g_value_get_boolean (value);
2066 if (priv->networking_enabled != b) {
2067 nm_client_networking_set_enabled (NM_CLIENT (object), b);
2068 /* Let the property value flip when we get the change signal from NM */
2069 }
2070 break;
2071 case PROP_WIRELESS_ENABLED:
2072 b = g_value_get_boolean (value);
2073 if (priv->wireless_enabled != b) {
2074 nm_client_wireless_set_enabled (NM_CLIENT (object), b);
2075 /* Let the property value flip when we get the change signal from NM */
2076 }
2077 break;
2078 case PROP_WWAN_ENABLED:
2079 b = g_value_get_boolean (value);
2080 if (priv->wwan_enabled != b) {
2081 nm_client_wwan_set_enabled (NM_CLIENT (object), b);
2082 /* Let the property value flip when we get the change signal from NM */
2083 }
2084 break;
2085 case PROP_WIMAX_ENABLED:
2086 b = g_value_get_boolean (value);
2087 if (priv->wimax_enabled != b) {
2088 nm_client_wimax_set_enabled (NM_CLIENT (object), b);
2089 /* Let the property value flip when we get the change signal from NM */
2090 }
2091 break;
2092 default:
2093 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2094 break;
2095 }
2096 }
2097
2098 static void
2099 get_property (GObject *object,
2100 guint prop_id,
2101 GValue *value,
2102 GParamSpec *pspec)
2103 {
2104 NMClient *self = NM_CLIENT (object);
2105 NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
2106
2107 _nm_object_ensure_inited (NM_OBJECT (object));
2108
2109 switch (prop_id) {
2110 case PROP_VERSION:
2111 g_value_set_string (value, nm_client_get_version (self));
2112 break;
2113 case PROP_STATE:
2114 g_value_set_uint (value, nm_client_get_state (self));
2115 break;
2116 case PROP_STARTUP:
2117 g_value_set_boolean (value, nm_client_get_startup (self));
2118 break;
2119 case PROP_MANAGER_RUNNING:
2120 g_value_set_boolean (value, priv->manager_running);
2121 break;
2122 case PROP_NETWORKING_ENABLED:
2123 g_value_set_boolean (value, nm_client_networking_get_enabled (self));
2124 break;
2125 case PROP_WIRELESS_ENABLED:
2126 g_value_set_boolean (value, priv->wireless_enabled);
2127 break;
2128 case PROP_WIRELESS_HARDWARE_ENABLED:
2129 g_value_set_boolean (value, priv->wireless_hw_enabled);
2130 break;
2131 case PROP_WWAN_ENABLED:
2132 g_value_set_boolean (value, priv->wwan_enabled);
2133 break;
2134 case PROP_WWAN_HARDWARE_ENABLED:
2135 g_value_set_boolean (value, priv->wwan_hw_enabled);
2136 break;
2137 case PROP_WIMAX_ENABLED:
2138 g_value_set_boolean (value, priv->wimax_enabled);
2139 break;
2140 case PROP_WIMAX_HARDWARE_ENABLED:
2141 g_value_set_boolean (value, priv->wimax_hw_enabled);
2142 break;
2143 case PROP_ACTIVE_CONNECTIONS:
2144 g_value_set_boxed (value, nm_client_get_active_connections (self));
2145 break;
2146 case PROP_CONNECTIVITY:
2147 g_value_set_uint (value, priv->connectivity);
2148 break;
2149 case PROP_PRIMARY_CONNECTION:
2150 g_value_set_object (value, priv->primary_connection);
2151 break;
2152 case PROP_ACTIVATING_CONNECTION:
2153 g_value_set_object (value, priv->activating_connection);
2154 break;
2155 default:
2156 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2157 break;
2158 }
2159 }
2160
2161 static void
2162 nm_client_class_init (NMClientClass *client_class)
2163 {
2164 GObjectClass *object_class = G_OBJECT_CLASS (client_class);
2165
2166 g_type_class_add_private (client_class, sizeof (NMClientPrivate));
2167
2168 /* virtual methods */
2169 object_class->constructor = constructor;
2170 object_class->constructed = constructed;
2171 object_class->set_property = set_property;
2172 object_class->get_property = get_property;
2173 object_class->dispose = dispose;
2174 object_class->finalize = finalize;
2175
2176 /* properties */
2177
2178 /**
2179 * NMClient:version:
2180 *
2181 * The NetworkManager version.
2182 **/
2183 g_object_class_install_property (object_class, PROP_VERSION,
2184 g_param_spec_string (NM_CLIENT_VERSION,
2185 "Version",
2186 "NetworkManager version",
2187 NULL,
2188 G_PARAM_READABLE));
2189
2190 /**
2191 * NMClient:state:
2192 *
2193 * The current daemon state.
2194 **/
2195 g_object_class_install_property
2196 (object_class, PROP_STATE,
2197 g_param_spec_uint (NM_CLIENT_STATE,
2198 "State",
2199 "NetworkManager state",
2200 NM_STATE_UNKNOWN, NM_STATE_CONNECTED_GLOBAL, NM_STATE_UNKNOWN,
2201 G_PARAM_READABLE));
2202
2203 /**
2204 * NMClient:startup:
2205 *
2206 * Whether the daemon is still starting up.
2207 *
2208 * Since: 0.9.10
2209 **/
2210 g_object_class_install_property
2211 (object_class, PROP_STARTUP,
2212 g_param_spec_boolean (NM_CLIENT_STARTUP,
2213 "Startup",
2214 "Whether the daemon is still starting up",
2215 FALSE,
2216 G_PARAM_READABLE));
2217
2218 /**
2219 * NMClient::manager-running:
2220 *
2221 * Whether the daemon is running.
2222 **/
2223 g_object_class_install_property
2224 (object_class, PROP_MANAGER_RUNNING,
2225 g_param_spec_boolean (NM_CLIENT_MANAGER_RUNNING,
2226 "ManagerRunning",
2227 "Whether NetworkManager is running",
2228 FALSE,
2229 G_PARAM_READABLE));
2230
2231 /**
2232 * NMClient::networking-enabled:
2233 *
2234 * Whether networking is enabled.
2235 **/
2236 g_object_class_install_property
2237 (object_class, PROP_NETWORKING_ENABLED,
2238 g_param_spec_boolean (NM_CLIENT_NETWORKING_ENABLED,
2239 "NetworkingEnabled",
2240 "Is networking enabled",
2241 TRUE,
2242 G_PARAM_READWRITE));
2243
2244 /**
2245 * NMClient::wireless-enabled:
2246 *
2247 * Whether wireless is enabled.
2248 **/
2249 g_object_class_install_property
2250 (object_class, PROP_WIRELESS_ENABLED,
2251 g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED,
2252 "WirelessEnabled",
2253 "Is wireless enabled",
2254 FALSE,
2255 G_PARAM_READWRITE));
2256
2257 /**
2258 * NMClient::wireless-hardware-enabled:
2259 *
2260 * Whether the wireless hardware is enabled.
2261 **/
2262 g_object_class_install_property
2263 (object_class, PROP_WIRELESS_HARDWARE_ENABLED,
2264 g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED,
2265 "WirelessHardwareEnabled",
2266 "Is wireless hardware enabled",
2267 TRUE,
2268 G_PARAM_READABLE));
2269
2270 /**
2271 * NMClient::wwan-enabled:
2272 *
2273 * Whether WWAN functionality is enabled.
2274 **/
2275 g_object_class_install_property
2276 (object_class, PROP_WWAN_ENABLED,
2277 g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED,
2278 "WwanEnabled",
2279 "Is WWAN enabled",
2280 FALSE,
2281 G_PARAM_READWRITE));
2282
2283 /**
2284 * NMClient::wwan-hardware-enabled:
2285 *
2286 * Whether the WWAN hardware is enabled.
2287 **/
2288 g_object_class_install_property
2289 (object_class, PROP_WWAN_HARDWARE_ENABLED,
2290 g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED,
2291 "WwanHardwareEnabled",
2292 "Is WWAN hardware enabled",
2293 FALSE,
2294 G_PARAM_READABLE));
2295
2296 /**
2297 * NMClient::wimax-enabled:
2298 *
2299 * Whether WiMAX functionality is enabled.
2300 **/
2301 g_object_class_install_property
2302 (object_class, PROP_WIMAX_ENABLED,
2303 g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED,
2304 "WimaxEnabled",
2305 "Is WiMAX enabled",
2306 FALSE,
2307 G_PARAM_READWRITE));
2308
2309 /**
2310 * NMClient::wimax-hardware-enabled:
2311 *
2312 * Whether the WiMAX hardware is enabled.
2313 **/
2314 g_object_class_install_property
2315 (object_class, PROP_WIMAX_HARDWARE_ENABLED,
2316 g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED,
2317 "WimaxHardwareEnabled",
2318 "Is WiMAX hardware enabled",
2319 FALSE,
2320 G_PARAM_READABLE));
2321
2322 /**
2323 * NMClient::active-connections:
2324 *
2325 * The active connections.
2326 * Type: GPtrArray<NMClient.ActiveConnection>
2327 **/
2328 g_object_class_install_property
2329 (object_class, PROP_ACTIVE_CONNECTIONS,
2330 g_param_spec_boxed (NM_CLIENT_ACTIVE_CONNECTIONS,
2331 "Active connections",
2332 "Active connections",
2333 NM_TYPE_OBJECT_ARRAY,
2334 G_PARAM_READABLE));
2335
2336 /**
2337 * NMClient:connectivity:
2338 *
2339 * The network connectivity state.
2340 *
2341 * Since: 0.9.8.6
2342 */
2343 g_object_class_install_property
2344 (object_class, PROP_CONNECTIVITY,
2345 g_param_spec_uint (NM_CLIENT_CONNECTIVITY,
2346 "Connectivity",
2347 "Connectivity state",
2348 NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
2349 G_PARAM_READABLE));
2350
2351 /**
2352 * NMClient:primary-connection:
2353 *
2354 * The #NMActiveConnection of the device with the default route;
2355 * see nm_client_get_primary_connection() for more details.
2356 *
2357 * Since: 0.9.8.6
2358 **/
2359 g_object_class_install_property
2360 (object_class, PROP_PRIMARY_CONNECTION,
2361 g_param_spec_object (NM_CLIENT_PRIMARY_CONNECTION,
2362 "Primary connection",
2363 "Primary connection",
2364 NM_TYPE_ACTIVE_CONNECTION,
2365 G_PARAM_READABLE));
2366
2367 /**
2368 * NMClient:activating-connection:
2369 *
2370 * The #NMActiveConnection of the activating connection that is
2371 * likely to become the new #NMClient:primary-connection.
2372 *
2373 * Since: 0.9.8.6
2374 **/
2375 g_object_class_install_property
2376 (object_class, PROP_ACTIVATING_CONNECTION,
2377 g_param_spec_object (NM_CLIENT_ACTIVATING_CONNECTION,
2378 "Activating connection",
2379 "Activating connection",
2380 NM_TYPE_ACTIVE_CONNECTION,
2381 G_PARAM_READABLE));
2382
2383 /* signals */
2384
2385 /**
2386 * NMClient::device-added:
2387 * @client: the client that received the signal
2388 * @device: (type NMClient.Device): the new device
2389 *
2390 * Notifies that a #NMDevice is added.
2391 **/
2392 signals[DEVICE_ADDED] =
2393 g_signal_new ("device-added",
2394 G_OBJECT_CLASS_TYPE (object_class),
2395 G_SIGNAL_RUN_FIRST,
2396 G_STRUCT_OFFSET (NMClientClass, device_added),
2397 NULL, NULL, NULL,
2398 G_TYPE_NONE, 1,
2399 G_TYPE_OBJECT);
2400
2401 /**
2402 * NMClient::device-removed:
2403 * @client: the client that received the signal
2404 * @device: (type NMClient.Device): the removed device
2405 *
2406 * Notifies that a #NMDevice is removed.
2407 **/
2408 signals[DEVICE_REMOVED] =
2409 g_signal_new ("device-removed",
2410 G_OBJECT_CLASS_TYPE (object_class),
2411 G_SIGNAL_RUN_FIRST,
2412 G_STRUCT_OFFSET (NMClientClass, device_removed),
2413 NULL, NULL, NULL,
2414 G_TYPE_NONE, 1,
2415 G_TYPE_OBJECT);
2416
2417 /**
2418 * NMClient::permission-changed:
2419 * @client: the client that received the signal
2420 * @permission: a permission from #NMClientPermission
2421 * @result: the permission's result, one of #NMClientPermissionResult
2422 *
2423 * Notifies that a permission has changed
2424 **/
2425 signals[PERMISSION_CHANGED] =
2426 g_signal_new ("permission-changed",
2427 G_OBJECT_CLASS_TYPE (object_class),
2428 G_SIGNAL_RUN_FIRST,
2429 0, NULL, NULL, NULL,
2430 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2431 }
2432
2433 static void
2434 nm_client_initable_iface_init (GInitableIface *iface)
2435 {
2436 nm_client_parent_initable_iface = g_type_interface_peek_parent (iface);
2437
2438 iface->init = init_sync;
2439 }
2440
2441 static void
2442 nm_client_async_initable_iface_init (GAsyncInitableIface *iface)
2443 {
2444 nm_client_parent_async_initable_iface = g_type_interface_peek_parent (iface);
2445
2446 iface->init_async = init_async;
2447 iface->init_finish = init_finish;
2448 }
2449