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 - 2011 Red Hat, Inc.
21   	 * Copyright (C) 2008 Novell, Inc.
22   	 */
23   	
24   	#include <string.h>
25   	
26   	#include "NetworkManager.h"
27   	#include "nm-active-connection.h"
28   	#include "nm-object-private.h"
29   	#include "nm-types-private.h"
30   	#include "nm-device.h"
31   	#include "nm-device-private.h"
32   	#include "nm-connection.h"
33   	#include "nm-vpn-connection.h"
34   	#include "nm-glib-compat.h"
35   	#include "nm-dbus-helpers-private.h"
36   	
37   	static GType _nm_active_connection_type_for_path (DBusGConnection *connection,
38   	                                                  const char *path);
39   	static void  _nm_active_connection_type_for_path_async (DBusGConnection *connection,
40   	                                                        const char *path,
41   	                                                        NMObjectTypeCallbackFunc callback,
42   	                                                        gpointer user_data);
43   	
44   	G_DEFINE_TYPE_WITH_CODE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT,
45   	                         _nm_object_register_type_func (g_define_type_id,
46   	                                                        _nm_active_connection_type_for_path,
47   	                                                        _nm_active_connection_type_for_path_async);
48   	                         )
49   	
50   	#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
51   	
52   	typedef struct {
53   		DBusGProxy *proxy;
54   	
55   		char *connection;
56   		char *uuid;
57   		char *specific_object;
58   		GPtrArray *devices;
59   		NMActiveConnectionState state;
60   		gboolean is_default;
61   		gboolean is_default6;
62   		char *master;
63   	} NMActiveConnectionPrivate;
64   	
65   	enum {
66   		PROP_0,
67   		PROP_CONNECTION,
68   		PROP_UUID,
69   		PROP_SPECIFIC_OBJECT,
70   		PROP_DEVICES,
71   		PROP_STATE,
72   		PROP_DEFAULT,
73   		PROP_DEFAULT6,
74   		PROP_MASTER,
75   	
76   		LAST_PROP
77   	};
78   	
79   	#define DBUS_PROP_CONNECTION "Connection"
80   	#define DBUS_PROP_UUID "Uuid"
81   	#define DBUS_PROP_SPECIFIC_OBJECT "SpecificObject"
82   	#define DBUS_PROP_DEVICES "Devices"
83   	#define DBUS_PROP_STATE "State"
84   	#define DBUS_PROP_DEFAULT "Default"
85   	#define DBUS_PROP_DEFAULT6 "Default6"
86   	#define DBUS_PROP_MASTER "Master"
87   	
88   	/**
89   	 * nm_active_connection_new:
90   	 * @connection: the #DBusGConnection
91   	 * @path: the DBus object path of the device
92   	 *
93   	 * Creates a new #NMActiveConnection.
94   	 *
95   	 * Returns: (transfer full): a new active connection
96   	 **/
97   	GObject *
98   	nm_active_connection_new (DBusGConnection *connection, const char *path)
99   	{
100  		g_return_val_if_fail (connection != NULL, NULL);
101  		g_return_val_if_fail (path != NULL, NULL);
102  	
103  		return g_object_new (NM_TYPE_ACTIVE_CONNECTION,
104  							 NM_OBJECT_DBUS_CONNECTION, connection,
105  							 NM_OBJECT_DBUS_PATH, path,
106  							 NULL);
107  	}
108  	
109  	static GType
110  	_nm_active_connection_type_for_path (DBusGConnection *connection,
111  	                                     const char *path)
112  	{
113  		DBusGProxy *proxy;
114  		GError *error = NULL;
115  		GValue value = G_VALUE_INIT;
116  		GType type;
117  	
118  		proxy = _nm_dbus_new_proxy_for_connection (connection, path, "org.freedesktop.DBus.Properties");
119  		if (!proxy) {
120  			g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
121  			return G_TYPE_INVALID;
122  		}
123  	
124  		/* Have to create an NMVPNConnection if it's a VPN connection, otherwise
125  		 * a plain NMActiveConnection.
126  		 */
(5) Event example_checked: Example4: "dbus_g_proxy_call(proxy, "Get", &error, 64UL, "org.freedesktop.NetworkManager.Connection.Active", 64UL, "Vpn", 0UL, g_value_get_type(), &value, 0UL)" has its value checked in "dbus_g_proxy_call(proxy, "Get", &error, 64UL, "org.freedesktop.NetworkManager.Connection.Active", 64UL, "Vpn", 0UL, g_value_get_type(), &value, 0UL)".
Also see events: [check_return][example_checked][example_checked][example_checked][example_checked][unchecked_value]
127  		if (dbus_g_proxy_call (proxy,
128  		                       "Get", &error,
129  		                       G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
130  		                       G_TYPE_STRING, "Vpn",
131  		                       G_TYPE_INVALID,
132  		                       G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
133  			if (g_value_get_boolean (&value))
134  				type = NM_TYPE_VPN_CONNECTION;
135  			else
136  				type = NM_TYPE_ACTIVE_CONNECTION;
137  		} else {
138  			g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
139  			           error->code, error->message);
140  			g_error_free (error);
141  			type = G_TYPE_INVALID;
142  		}
143  	
144  		g_object_unref (proxy);
145  		return type;
146  	}
147  	
148  	typedef struct {
149  		DBusGConnection *connection;
150  		NMObjectTypeCallbackFunc callback;
151  		gpointer user_data;
152  	} NMActiveConnectionAsyncData;
153  	
154  	static void
155  	async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
156  	{
157  		NMActiveConnectionAsyncData *async_data = user_data;
158  		GValue value = G_VALUE_INIT;
159  		const char *path = dbus_g_proxy_get_path (proxy);
160  		GError *error = NULL;
161  		GType type;
162  	
163  		if (dbus_g_proxy_end_call (proxy, call, &error,
164  		                           G_TYPE_VALUE, &value,
165  		                           G_TYPE_INVALID)) {
166  			if (g_value_get_boolean (&value))
167  				type = NM_TYPE_VPN_CONNECTION;
168  			else
169  				type = NM_TYPE_ACTIVE_CONNECTION;
170  		} else {
171  			g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
172  			type = G_TYPE_INVALID;
173  		}
174  	
175  		async_data->callback (type, async_data->user_data);
176  	
177  		g_object_unref (proxy);
178  		g_slice_free (NMActiveConnectionAsyncData, async_data);
179  	}
180  	
181  	static void
182  	_nm_active_connection_type_for_path_async (DBusGConnection *connection,
183  	                                           const char *path,
184  	                                           NMObjectTypeCallbackFunc callback,
185  	                                           gpointer user_data)
186  	{
187  		NMActiveConnectionAsyncData *async_data;
188  		DBusGProxy *proxy;
189  	
190  		async_data = g_slice_new (NMActiveConnectionAsyncData);
191  		async_data->connection = connection;
192  		async_data->callback = callback;
193  		async_data->user_data = user_data;
194  	
195  		proxy = _nm_dbus_new_proxy_for_connection (connection, path, "org.freedesktop.DBus.Properties");
196  		dbus_g_proxy_begin_call (proxy, "Get",
197  		                         async_got_type, async_data, NULL,
198  		                         G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
199  		                         G_TYPE_STRING, "Vpn",
200  		                         G_TYPE_INVALID);
201  	}
202  	
203  	/**
204  	 * nm_active_connection_get_connection:
205  	 * @connection: a #NMActiveConnection
206  	 *
207  	 * Gets the #NMConnection's DBus object path.
208  	 *
209  	 * Returns: the object path of the #NMConnection inside of #NMActiveConnection.
210  	 * This is the internal string used by the connection, and must not be modified.
211  	 **/
212  	const char *
213  	nm_active_connection_get_connection (NMActiveConnection *connection)
214  	{
215  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
216  	
217  		_nm_object_ensure_inited (NM_OBJECT (connection));
218  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->connection;
219  	}
220  	
221  	/**
222  	 * nm_active_connection_get_uuid:
223  	 * @connection: a #NMActiveConnection
224  	 *
225  	 * Gets the #NMConnection's UUID.
226  	 *
227  	 * Returns: the UUID of the #NMConnection that backs the #NMActiveConnection.
228  	 * This is the internal string used by the connection, and must not be modified.
229  	 **/
230  	const char *
231  	nm_active_connection_get_uuid (NMActiveConnection *connection)
232  	{
233  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
234  	
235  		_nm_object_ensure_inited (NM_OBJECT (connection));
236  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->uuid;
237  	}
238  	
239  	/**
240  	 * nm_active_connection_get_specific_object:
241  	 * @connection: a #NMActiveConnection
242  	 *
243  	 * Gets the "specific object" used at the activation.
244  	 *
245  	 * Returns: the specific object's DBus path. This is the internal string used by the
246  	 * connection, and must not be modified.
247  	 **/
248  	const char *
249  	nm_active_connection_get_specific_object (NMActiveConnection *connection)
250  	{
251  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
252  	
253  		_nm_object_ensure_inited (NM_OBJECT (connection));
254  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->specific_object;
255  	}
256  	
257  	/**
258  	 * nm_active_connection_get_devices:
259  	 * @connection: a #NMActiveConnection
260  	 *
261  	 * Gets the #NMDevices used for the active connections.
262  	 *
263  	 * Returns: (element-type NMClient.Device): the #GPtrArray containing #NMDevices.
264  	 * This is the internal copy used by the connection, and must not be modified.
265  	 **/
266  	const GPtrArray *
267  	nm_active_connection_get_devices (NMActiveConnection *connection)
268  	{
269  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
270  	
271  		_nm_object_ensure_inited (NM_OBJECT (connection));
272  		return handle_ptr_array_return (NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->devices);
273  	}
274  	
275  	/**
276  	 * nm_active_connection_get_state:
277  	 * @connection: a #NMActiveConnection
278  	 *
279  	 * Gets the active connection's state.
280  	 *
281  	 * Returns: the state
282  	 **/
283  	NMActiveConnectionState
284  	nm_active_connection_get_state (NMActiveConnection *connection)
285  	{
286  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
287  	
288  		_nm_object_ensure_inited (NM_OBJECT (connection));
289  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->state;
290  	}
291  	
292  	/**
293  	 * nm_active_connection_get_default:
294  	 * @connection: a #NMActiveConnection
295  	 *
296  	 * Whether the active connection is the default IPv4 one (that is, is used for
297  	 * the default IPv4 route and DNS information).
298  	 *
299  	 * Returns: %TRUE if the active connection is the default IPv4 connection
300  	 **/
301  	gboolean
302  	nm_active_connection_get_default (NMActiveConnection *connection)
303  	{
304  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE);
305  	
306  		_nm_object_ensure_inited (NM_OBJECT (connection));
307  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_default;
308  	}
309  	
310  	/**
311  	 * nm_active_connection_get_default6:
312  	 * @connection: a #NMActiveConnection
313  	 *
314  	 * Whether the active connection is the default IPv6 one (that is, is used for
315  	 * the default IPv6 route and DNS information).
316  	 *
317  	 * Returns: %TRUE if the active connection is the default IPv6 connection
318  	 **/
319  	gboolean
320  	nm_active_connection_get_default6 (NMActiveConnection *connection)
321  	{
322  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE);
323  	
324  		_nm_object_ensure_inited (NM_OBJECT (connection));
325  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_default6;
326  	}
327  	
328  	/**
329  	 * nm_active_connection_get_master:
330  	 * @connection: a #NMActiveConnection
331  	 *
332  	 * Gets the path to the master #NMDevice of the connection.
333  	 *
334  	 * Returns: the path of the master #NMDevice of the #NMActiveConnection.
335  	 * This is the internal string used by the connection, and must not be modified.
336  	 **/
337  	const char *
338  	nm_active_connection_get_master (NMActiveConnection *connection)
339  	{
340  		g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
341  	
342  		_nm_object_ensure_inited (NM_OBJECT (connection));
343  		return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->master;
344  	}
345  	
346  	static void
347  	nm_active_connection_init (NMActiveConnection *ap)
348  	{
349  	}
350  	
351  	static void
352  	dispose (GObject *object)
353  	{
354  		NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
355  	
356  		if (priv->devices) {
357  			g_ptr_array_set_free_func (priv->devices, g_object_unref);
358  			g_ptr_array_free (priv->devices, TRUE);
359  			priv->devices = NULL;
360  		}
361  	
362  		g_clear_object (&priv->proxy);
363  	
364  		G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
365  	}
366  	
367  	static void
368  	finalize (GObject *object)
369  	{
370  		NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
371  	
372  		g_free (priv->connection);
373  		g_free (priv->uuid);
374  		g_free (priv->specific_object);
375  		g_free (priv->master);
376  	
377  		G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
378  	}
379  	
380  	static void
381  	get_property (GObject *object,
382  	              guint prop_id,
383  	              GValue *value,
384  	              GParamSpec *pspec)
385  	{
386  		NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
387  	
388  		_nm_object_ensure_inited (NM_OBJECT (object));
389  	
390  		switch (prop_id) {
391  		case PROP_CONNECTION:
392  			g_value_set_string (value, nm_active_connection_get_connection (self));
393  			break;
394  		case PROP_UUID:
395  			g_value_set_string (value, nm_active_connection_get_uuid (self));
396  			break;
397  		case PROP_SPECIFIC_OBJECT:
398  			g_value_set_boxed (value, nm_active_connection_get_specific_object (self));
399  			break;
400  		case PROP_DEVICES:
401  			g_value_set_boxed (value, nm_active_connection_get_devices (self));
402  			break;
403  		case PROP_STATE:
404  			g_value_set_uint (value, nm_active_connection_get_state (self));
405  			break;
406  		case PROP_DEFAULT:
407  			g_value_set_boolean (value, nm_active_connection_get_default (self));
408  			break;
409  		case PROP_DEFAULT6:
410  			g_value_set_boolean (value, nm_active_connection_get_default6 (self));
411  			break;
412  		case PROP_MASTER:
413  			g_value_set_string (value, nm_active_connection_get_master (self));
414  			break;
415  		default:
416  			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
417  			break;
418  		}
419  	}
420  	
421  	static void
422  	register_properties (NMActiveConnection *connection)
423  	{
424  		NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
425  		const NMPropertiesInfo property_info[] = {
426  			{ NM_ACTIVE_CONNECTION_CONNECTION,          &priv->connection },
427  			{ NM_ACTIVE_CONNECTION_UUID,                &priv->uuid },
428  			{ NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,     &priv->specific_object },
429  			{ NM_ACTIVE_CONNECTION_DEVICES,             &priv->devices, NULL, NM_TYPE_DEVICE },
430  			{ NM_ACTIVE_CONNECTION_STATE,               &priv->state },
431  			{ NM_ACTIVE_CONNECTION_DEFAULT,             &priv->is_default },
432  			{ NM_ACTIVE_CONNECTION_DEFAULT6,            &priv->is_default6 },
433  			{ NM_ACTIVE_CONNECTION_MASTER,              &priv->master },
434  	
435  			/* not tracked after construction time */
436  			{ "vpn", NULL },
437  	
438  			{ NULL },
439  		};
440  	
441  		_nm_object_register_properties (NM_OBJECT (connection),
442  		                                priv->proxy,
443  		                                property_info);
444  	}
445  	
446  	static void
447  	constructed (GObject *object)
448  	{
449  		NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
450  	
451  		G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
452  	
453  		priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_ACTIVE_CONNECTION);
454  		register_properties (NM_ACTIVE_CONNECTION (object));
455  	}
456  	
457  	
458  	static void
459  	nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
460  	{
461  		GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
462  	
463  		g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate));
464  	
465  		/* virtual methods */
466  		object_class->constructed = constructed;
467  		object_class->get_property = get_property;
468  		object_class->dispose = dispose;
469  		object_class->finalize = finalize;
470  	
471  		/* properties */
472  	
473  		/**
474  		 * NMActiveConnection:connection:
475  		 *
476  		 * The connection's path of the active connection.
477  		 **/
478  		g_object_class_install_property
479  			(object_class, PROP_CONNECTION,
480  			 g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION,
481  							      "Connection",
482  							      "Connection",
483  							      NULL,
484  							      G_PARAM_READABLE));
485  	
486  		/**
487  		 * NMActiveConnection:uuid:
488  		 *
489  		 * The active connection's UUID
490  		 **/
491  		g_object_class_install_property
492  			(object_class, PROP_UUID,
493  			 g_param_spec_string (NM_ACTIVE_CONNECTION_UUID,
494  							      "UUID",
495  							      "UUID",
496  							      NULL,
497  							      G_PARAM_READABLE));
498  	
499  		/**
500  		 * NMActiveConnection:specific-object:
501  		 *
502  		 * The specific object's path of the active connection.
503  		 **/
504  		g_object_class_install_property
505  			(object_class, PROP_SPECIFIC_OBJECT,
506  			 g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
507  							      "Specific object",
508  							      "Specific object",
509  							      NULL,
510  							      G_PARAM_READABLE));
511  	
512  		/**
513  		 * NMActiveConnection:device:
514  		 *
515  		 * The devices (#NMDevice) of the active connection.
516  		 **/
517  		g_object_class_install_property
518  			(object_class, PROP_DEVICES,
519  			 g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES,
520  							       "Devices",
521  							       "Devices",
522  							       NM_TYPE_OBJECT_ARRAY,
523  							       G_PARAM_READABLE));
524  	
525  		/**
526  		 * NMActiveConnection:state:
527  		 *
528  		 * The state of the active connection.
529  		 **/
530  		g_object_class_install_property
531  			(object_class, PROP_STATE,
532  			 g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE,
533  								  "State",
534  								  "State",
535  								  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
536  								  NM_ACTIVE_CONNECTION_STATE_DEACTIVATING,
537  								  NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
538  								  G_PARAM_READABLE));
539  	
540  		/**
541  		 * NMActiveConnection:default:
542  		 *
543  		 * Whether the active connection is the default IPv4 one.
544  		 **/
545  		g_object_class_install_property
546  			(object_class, PROP_DEFAULT,
547  			 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
548  								   "Default",
549  								   "Is the default IPv4 active connection",
550  								   FALSE,
551  								   G_PARAM_READABLE));
552  	
553  		/**
554  		 * NMActiveConnection:default6:
555  		 *
556  		 * Whether the active connection is the default IPv6 one.
557  		 **/
558  		g_object_class_install_property
559  			(object_class, PROP_DEFAULT6,
560  			 g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
561  								   "Default6",
562  								   "Is the default IPv6 active connection",
563  								   FALSE,
564  								   G_PARAM_READABLE));
565  	
566  		/**
567  		 * NMActiveConnection:master:
568  		 *
569  		 * The path of the master device if one exists.
570  		 **/
571  		g_object_class_install_property
572  			(object_class, PROP_MASTER,
573  			 g_param_spec_string (NM_ACTIVE_CONNECTION_MASTER,
574  							      "Master",
575  							      "Path of the master device",
576  							      NULL,
577  							      G_PARAM_READABLE));
578  	}
579