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 */
(17) 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