GCC Code Coverage Report


Directory: ./
File: panels/network/network-dialogs.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 208 0.0%
Functions: 0 16 0.0%
Branches: 0 96 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Portions of this code were taken from network-manager-applet.
20 * Copyright 2008 - 2011 Red Hat, Inc.
21 */
22
23 #include <NetworkManager.h>
24 #include <nma-wifi-dialog.h>
25 #include <nma-mobile-wizard.h>
26
27 #include "network-dialogs.h"
28
29 typedef struct {
30 NMClient *client;
31 } WirelessDialogClosure;
32
33 typedef struct {
34 NMClient *client;
35 NMDevice *device;
36 } MobileDialogClosure;
37
38 static void
39 wireless_dialog_closure_closure_notify (gpointer data,
40 GClosure *gclosure)
41 {
42 WirelessDialogClosure *closure = data;
43
44 g_clear_object (&closure->client);
45 g_slice_free (WirelessDialogClosure, data);
46 }
47
48 static void
49 mobile_dialog_closure_free (gpointer data)
50 {
51 MobileDialogClosure *closure = data;
52
53 g_clear_object (&closure->client);
54 g_clear_object (&closure->device);
55 g_slice_free (MobileDialogClosure, data);
56 }
57
58 static gboolean
59 wifi_can_create_wifi_network (NMClient *client)
60 {
61 NMClientPermissionResult perm;
62
63 /* FIXME: check WIFI_SHARE_PROTECTED too, and make the wireless dialog
64 * handle the permissions as well so that admins can restrict open network
65 * creation separately from protected network creation.
66 */
67 perm = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN);
68 if (perm == NM_CLIENT_PERMISSION_RESULT_YES || perm == NM_CLIENT_PERMISSION_RESULT_AUTH)
69 return TRUE;
70
71 return FALSE;
72 }
73
74 static void
75 activate_existing_cb (GObject *source_object,
76 GAsyncResult *res,
77 gpointer user_data)
78 {
79 g_autoptr(GError) error = NULL;
80
81 if (!nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error))
82 g_warning ("Failed to activate connection: (%d) %s", error->code, error->message);
83 }
84
85 static void
86 activate_new_cb (GObject *source_object,
87 GAsyncResult *res,
88 gpointer user_data)
89 {
90 g_autoptr(GError) error = NULL;
91
92 if (!nm_client_add_and_activate_connection_finish (NM_CLIENT (source_object), res, &error))
93 g_warning ("Failed to add new connection: (%d) %s", error->code, error->message);
94 }
95
96 static void
97 wireless_dialog_response_cb (GtkDialog *foo,
98 gint response,
99 gpointer user_data)
100 {
101 NMAWifiDialog *dialog = NMA_WIFI_DIALOG (foo);
102 WirelessDialogClosure *closure = user_data;
103 g_autoptr(NMConnection) connection = NULL;
104 NMConnection *fuzzy_match = NULL;
105 NMDevice *device;
106 NMAccessPoint *ap;
107 const GPtrArray *all;
108 guint i;
109
110 if (response != GTK_RESPONSE_OK)
111 goto done;
112
113 /* nma_wifi_dialog_get_connection() returns a connection with the
114 * refcount incremented, so the caller must remember to unref it.
115 */
116 connection = nma_wifi_dialog_get_connection (dialog, &device, &ap);
117 g_assert (connection);
118 g_assert (device);
119
120 /* Find a similar connection and use that instead */
121 all = nm_client_get_connections (closure->client);
122 for (i = 0; i < all->len; i++) {
123 if (nm_connection_compare (connection,
124 NM_CONNECTION (g_ptr_array_index (all, i)),
125 (NM_SETTING_COMPARE_FLAG_FUZZY | NM_SETTING_COMPARE_FLAG_IGNORE_ID))) {
126 fuzzy_match = NM_CONNECTION (g_ptr_array_index (all, i));
127 break;
128 }
129 }
130
131 if (fuzzy_match) {
132 nm_client_activate_connection_async (closure->client,
133 fuzzy_match,
134 device,
135 ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL,
136 NULL,
137 activate_existing_cb,
138 NULL);
139 } else {
140 NMSetting *s_con;
141 NMSettingWireless *s_wifi;
142 const char *mode = NULL;
143
144 /* Entirely new connection */
145
146 /* Don't autoconnect adhoc networks by default for now */
147 s_wifi = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
148 if (s_wifi)
149 mode = nm_setting_wireless_get_mode (s_wifi);
150 if (g_strcmp0 (mode, "adhoc") == 0) {
151 s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
152 if (!s_con) {
153 s_con = nm_setting_connection_new ();
154 nm_connection_add_setting (connection, s_con);
155 }
156 g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL);
157 }
158
159 nm_client_add_and_activate_connection_async (closure->client,
160 connection,
161 device,
162 ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL,
163 NULL,
164 activate_new_cb,
165 NULL);
166 }
167
168 done:
169 gtk_window_destroy (GTK_WINDOW (dialog));
170 }
171
172 static void
173 show_wireless_dialog (GtkWidget *toplevel,
174 NMClient *client,
175 GtkWidget *dialog)
176 {
177 WirelessDialogClosure *closure;
178
179 g_debug ("About to parent and show a network dialog");
180
181 g_assert (GTK_IS_NATIVE (toplevel));
182 g_object_set (G_OBJECT (dialog),
183 "modal", TRUE,
184 "transient-for", toplevel,
185 NULL);
186
187 closure = g_slice_new (WirelessDialogClosure);
188 closure->client = g_object_ref (client);
189 g_signal_connect_data (dialog, "response",
190 G_CALLBACK (wireless_dialog_response_cb),
191 closure, wireless_dialog_closure_closure_notify, 0);
192
193 g_object_bind_property (G_OBJECT (toplevel), "visible",
194 G_OBJECT (dialog), "visible",
195 G_BINDING_SYNC_CREATE);
196 }
197
198 void
199 cc_network_panel_create_wifi_network (GtkWidget *toplevel,
200 NMClient *client)
201 {
202 if (wifi_can_create_wifi_network (client)) {
203 show_wireless_dialog (toplevel, client,
204 nma_wifi_dialog_new_for_create (client));
205 }
206 }
207
208 void
209 cc_network_panel_connect_to_hidden_network (GtkWidget *toplevel,
210 NMClient *client)
211 {
212 g_debug ("connect to hidden wifi");
213 show_wireless_dialog (toplevel, client,
214 nma_wifi_dialog_new_for_hidden (client));
215 }
216
217 void
218 cc_network_panel_connect_to_8021x_network (GtkWidget *toplevel,
219 NMClient *client,
220 NMDevice *device,
221 const gchar *arg_access_point)
222 {
223 NMConnection *connection;
224 NMSettingConnection *s_con;
225 NMSettingWireless *s_wifi;
226 NMSettingWirelessSecurity *s_wsec;
227 NMSetting8021x *s_8021x;
228 NM80211ApSecurityFlags wpa_flags, rsn_flags;
229 GtkWidget *dialog;
230 g_autofree gchar *uuid = NULL;
231 NMAccessPoint *ap;
232
233 g_debug ("connect to 8021x wifi");
234 ap = nm_device_wifi_get_access_point_by_path (NM_DEVICE_WIFI (device), arg_access_point);
235 if (ap == NULL) {
236 g_warning ("didn't find access point with path %s", arg_access_point);
237 return;
238 }
239
240 /* If the AP is WPA[2]-Enterprise then we need to set up a minimal 802.1x
241 * setting and ask the user for more information.
242 */
243 rsn_flags = nm_access_point_get_rsn_flags (ap);
244 wpa_flags = nm_access_point_get_wpa_flags (ap);
245 if (!(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
246 && !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
247 g_warning ("Network panel loaded with connect-8021x-wifi but the "
248 "access point does not support 802.1x");
249 return;
250 }
251
252 connection = nm_simple_connection_new ();
253
254 /* Need a UUID for the "always ask" stuff in the Dialog of Doom */
255 s_con = (NMSettingConnection *) nm_setting_connection_new ();
256 uuid = nm_utils_uuid_generate ();
257 g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL);
258 nm_connection_add_setting (connection, NM_SETTING (s_con));
259
260 s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
261 nm_connection_add_setting (connection, NM_SETTING (s_wifi));
262 g_object_set (s_wifi,
263 NM_SETTING_WIRELESS_SSID, nm_access_point_get_ssid (ap),
264 NULL);
265
266 s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
267 g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
268 nm_connection_add_setting (connection, NM_SETTING (s_wsec));
269
270 s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
271 nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
272 g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", NULL);
273 nm_connection_add_setting (connection, NM_SETTING (s_8021x));
274
275 dialog = nma_wifi_dialog_new (client, connection, device, ap, FALSE);
276 show_wireless_dialog (toplevel, client, dialog);
277 }
278
279 static void
280 connect_3g (NMConnection *connection,
281 gboolean canceled,
282 gpointer user_data)
283 {
284 MobileDialogClosure *closure = user_data;
285
286 if (canceled == FALSE) {
287 g_return_if_fail (connection != NULL);
288
289 /* Ask NM to add the new connection and activate it; NM will fill in the
290 * missing details based on the specific object and the device.
291 */
292 nm_client_add_and_activate_connection_async (closure->client,
293 connection,
294 closure->device,
295 "/",
296 NULL,
297 activate_new_cb,
298 NULL);
299 }
300
301 mobile_dialog_closure_free (closure);
302 }
303
304 static void
305 cdma_mobile_wizard_done (NMAMobileWizard *wizard,
306 gboolean canceled,
307 NMAMobileWizardAccessMethod *method,
308 gpointer user_data)
309 {
310 NMConnection *connection = NULL;
311
312 if (!canceled && method) {
313 NMSetting *setting;
314 g_autofree gchar *uuid = NULL;
315 g_autofree gchar *id = NULL;
316
317 if (method->devtype != NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
318 g_warning ("Unexpected device type (not CDMA).");
319 canceled = TRUE;
320 goto done;
321 }
322
323 connection = nm_simple_connection_new ();
324
325 setting = nm_setting_cdma_new ();
326 g_object_set (setting,
327 NM_SETTING_CDMA_NUMBER, "#777",
328 NM_SETTING_CDMA_USERNAME, method->username,
329 NM_SETTING_CDMA_PASSWORD, method->password,
330 NULL);
331 nm_connection_add_setting (connection, setting);
332
333 /* Serial setting */
334 setting = nm_setting_serial_new ();
335 g_object_set (setting,
336 NM_SETTING_SERIAL_BAUD, 115200,
337 NM_SETTING_SERIAL_BITS, 8,
338 NM_SETTING_SERIAL_PARITY, 'n',
339 NM_SETTING_SERIAL_STOPBITS, 1,
340 NULL);
341 nm_connection_add_setting (connection, setting);
342
343 nm_connection_add_setting (connection, nm_setting_ppp_new ());
344
345 setting = nm_setting_connection_new ();
346 if (method->plan_name)
347 id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name);
348 else
349 id = g_strdup_printf ("%s connection", method->provider_name);
350 uuid = nm_utils_uuid_generate ();
351 g_object_set (setting,
352 NM_SETTING_CONNECTION_ID, id,
353 NM_SETTING_CONNECTION_TYPE, NM_SETTING_CDMA_SETTING_NAME,
354 NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
355 NM_SETTING_CONNECTION_UUID, uuid,
356 NULL);
357 nm_connection_add_setting (connection, setting);
358 }
359
360 done:
361 connect_3g (connection, canceled, user_data);
362 nma_mobile_wizard_destroy (wizard);
363 }
364
365 static void
366 gsm_mobile_wizard_done (NMAMobileWizard *wizard,
367 gboolean canceled,
368 NMAMobileWizardAccessMethod *method,
369 gpointer user_data)
370 {
371 NMConnection *connection = NULL;
372
373 if (!canceled && method) {
374 NMSetting *setting;
375 g_autofree gchar *uuid = NULL;
376 g_autofree gchar *id = NULL;
377
378 if (method->devtype != NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) {
379 g_warning ("Unexpected device type (not GSM).");
380 canceled = TRUE;
381 goto done;
382 }
383
384 connection = nm_simple_connection_new ();
385
386 setting = nm_setting_gsm_new ();
387 g_object_set (setting,
388 NM_SETTING_GSM_NUMBER, "*99#",
389 NM_SETTING_GSM_USERNAME, method->username,
390 NM_SETTING_GSM_PASSWORD, method->password,
391 NM_SETTING_GSM_APN, method->gsm_apn,
392 NULL);
393 nm_connection_add_setting (connection, setting);
394
395 /* Serial setting */
396 setting = nm_setting_serial_new ();
397 g_object_set (setting,
398 NM_SETTING_SERIAL_BAUD, 115200,
399 NM_SETTING_SERIAL_BITS, 8,
400 NM_SETTING_SERIAL_PARITY, 'n',
401 NM_SETTING_SERIAL_STOPBITS, 1,
402 NULL);
403 nm_connection_add_setting (connection, setting);
404
405 nm_connection_add_setting (connection, nm_setting_ppp_new ());
406
407 setting = nm_setting_connection_new ();
408 if (method->plan_name)
409 id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name);
410 else
411 id = g_strdup_printf ("%s connection", method->provider_name);
412 uuid = nm_utils_uuid_generate ();
413 g_object_set (setting,
414 NM_SETTING_CONNECTION_ID, id,
415 NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME,
416 NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
417 NM_SETTING_CONNECTION_UUID, uuid,
418 NULL);
419 nm_connection_add_setting (connection, setting);
420 }
421
422 done:
423 connect_3g (connection, canceled, user_data);
424 nma_mobile_wizard_destroy (wizard);
425 }
426
427 static void
428 toplevel_shown (GtkWindow *toplevel,
429 GParamSpec *pspec,
430 NMAMobileWizard *wizard)
431 {
432 gboolean visible = FALSE;
433
434 g_object_get (G_OBJECT (toplevel), "visible", &visible, NULL);
435 if (visible)
436 nma_mobile_wizard_present (wizard);
437 }
438
439 static gboolean
440 show_wizard_idle_cb (NMAMobileWizard *wizard)
441 {
442 nma_mobile_wizard_present (wizard);
443 return FALSE;
444 }
445
446 void
447 cc_network_panel_connect_to_3g_network (GtkWidget *toplevel,
448 NMClient *client,
449 NMDevice *device)
450 {
451 MobileDialogClosure *closure;
452 NMAMobileWizard *wizard;
453 NMDeviceModemCapabilities caps;
454 gboolean visible = FALSE;
455
456 g_debug ("connect to 3g");
457 if (!NM_IS_DEVICE_MODEM (device)) {
458 g_warning ("Network panel loaded with connect-3g but the selected device"
459 " is not a modem");
460 return;
461 }
462
463 closure = g_slice_new (MobileDialogClosure);
464 closure->client = g_object_ref (client);
465 closure->device = g_object_ref (device);
466
467 caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
468 if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) {
469 wizard = nma_mobile_wizard_new (GTK_WINDOW (toplevel), NULL, NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS, FALSE,
470 gsm_mobile_wizard_done, closure);
471 if (wizard == NULL) {
472 g_warning ("failed to construct GSM wizard");
473 return;
474 }
475 } else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
476 wizard = nma_mobile_wizard_new (GTK_WINDOW (toplevel), NULL, NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO, FALSE,
477 cdma_mobile_wizard_done, closure);
478 if (wizard == NULL) {
479 g_warning ("failed to construct CDMA wizard");
480 return;
481 }
482 } else {
483 g_warning ("Network panel loaded with connect-3g but the selected device"
484 " does not support GSM or CDMA");
485 mobile_dialog_closure_free (closure);
486 return;
487 }
488
489 g_object_get (G_OBJECT (toplevel), "visible", &visible, NULL);
490 if (visible) {
491 g_debug ("Scheduling showing the Mobile wizard");
492 g_idle_add ((GSourceFunc) show_wizard_idle_cb, wizard);
493 } else {
494 g_debug ("Will show wizard a bit later, toplevel is not visible");
495 g_signal_connect (G_OBJECT (toplevel), "notify::visible",
496 G_CALLBACK (toplevel_shown), wizard);
497 }
498 }
499