1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright 2011 Red Hat, Inc.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "gio.h"
22
23 /* hack */
24 #define GIO_COMPILATION
25 #include "gnetworkmonitorbase.h"
26
27 #include <string.h>
28
29 /* Test data; the GInetAddresses and GInetAddressMasks get filled in
30 * in main(). Each address in a TestAddress matches the mask in its
31 * corresponding TestMask, and none of them match any of the other
32 * masks. The addresses in unmatched don't match any of the masks.
33 */
34
35 typedef struct {
36 const char *string;
37 GInetAddress *address;
38 } TestAddress;
39
40 typedef struct {
41 const char *mask_string;
42 GInetAddressMask *mask;
43 TestAddress *addresses;
44 } TestMask;
45
46 TestAddress net127addrs[] = {
47 { "127.0.0.1", NULL },
48 { "127.0.0.2", NULL },
49 { "127.0.0.255", NULL },
50 { "127.0.1.0", NULL },
51 { "127.0.255.0", NULL },
52 { "127.0.255.0", NULL },
53 { "127.255.255.255", NULL },
54 { NULL, NULL }
55 };
56 TestMask net127 = { "127.0.0.0/8", NULL, net127addrs };
57
58 TestAddress net10addrs[] = {
59 { "10.0.0.1", NULL },
60 { "10.0.0.2", NULL },
61 { "10.0.0.255", NULL },
62 { NULL, NULL }
63 };
64 TestMask net10 = { "10.0.0.0/24", NULL, net10addrs };
65
66 TestAddress net192addrs[] = {
67 { "192.168.0.1", NULL },
68 { "192.168.0.2", NULL },
69 { "192.168.0.255", NULL },
70 { "192.168.1.0", NULL },
71 { "192.168.15.0", NULL },
72 { NULL, NULL }
73 };
74 TestMask net192 = { "192.168.0.0/20", NULL, net192addrs };
75
76 TestAddress netlocal6addrs[] = {
77 { "::1", NULL },
78 { NULL, NULL }
79 };
80 TestMask netlocal6 = { "::1/128", NULL, netlocal6addrs };
81
82 TestAddress netfe80addrs[] = {
83 { "fe80::", NULL },
84 { "fe80::1", NULL },
85 { "fe80::21b:77ff:fea2:972a", NULL },
86 { NULL, NULL }
87 };
88 TestMask netfe80 = { "fe80::/64", NULL, netfe80addrs };
89
90 TestAddress unmatched[] = {
91 { "10.0.1.0", NULL },
92 { "10.0.255.0", NULL },
93 { "10.255.255.255", NULL },
94 { "192.168.16.0", NULL },
95 { "192.168.255.0", NULL },
96 { "192.169.0.0", NULL },
97 { "192.255.255.255", NULL },
98 { "::2", NULL },
99 { "1::1", NULL },
100 { "fe80::1:0:0:0:0", NULL },
101 { "fe80:8000::0:0:0:0", NULL },
102 { NULL, NULL }
103 };
104
105 GInetAddressMask *ip4_default, *ip6_default;
106
107 static void
108 notify_handler (GObject *object,
109 GParamSpec *pspec,
110 gpointer user_data)
111 {
112 gboolean *emitted = user_data;
113
114 *emitted = TRUE;
115 }
116
117 static void
118 network_changed_handler (GNetworkMonitor *monitor,
119 gboolean available,
120 gpointer user_data)
121 {
122 gboolean *emitted = user_data;
123
124 *emitted = TRUE;
125 }
126
127 static void
128 assert_signals (GNetworkMonitor *monitor,
129 gboolean should_emit_notify,
130 gboolean should_emit_network_changed,
131 gboolean expected_network_available)
132 {
133 gboolean emitted_notify = FALSE, emitted_network_changed = FALSE;
134 guint h1, h2;
135
136 h1 = g_signal_connect (monitor, "notify::network-available",
137 G_CALLBACK (notify_handler),
138 &emitted_notify);
139 h2 = g_signal_connect (monitor, "network-changed",
140 G_CALLBACK (network_changed_handler),
141 &emitted_network_changed);
142
143 g_main_context_iteration (NULL, FALSE);
144
145 g_signal_handler_disconnect (monitor, h1);
146 g_signal_handler_disconnect (monitor, h2);
147
148 g_assert (emitted_notify == should_emit_notify);
149 g_assert (emitted_network_changed == should_emit_network_changed);
150
151 g_assert (g_network_monitor_get_network_available (monitor) == expected_network_available);
152 }
153
154 typedef struct {
155 GNetworkMonitor *monitor;
156 GMainLoop *loop;
157 GSocketAddress *sockaddr;
158 gboolean should_be_reachable;
159 } CanReachData;
160
161 static void
162 reach_cb (GObject *source,
163 GAsyncResult *res,
164 gpointer user_data)
165 {
166 GError *error = NULL;
167 gboolean reachable;
168 CanReachData *data = user_data;
169
170 reachable = g_network_monitor_can_reach_finish (data->monitor, res, &error);
171
172 if (data->should_be_reachable)
173 g_assert_no_error (error);
174 else
175 {
176 g_assert (error != NULL);
177 g_clear_error (&error);
178 }
179 g_assert (reachable == data->should_be_reachable);
180
181 g_main_loop_quit (data->loop);
182 }
183
184 static gboolean
185 test_reach_async (gpointer user_data)
186 {
187 CanReachData *data = user_data;
188
189 g_network_monitor_can_reach_async (data->monitor,
190 G_SOCKET_CONNECTABLE (data->sockaddr),
191 NULL,
192 reach_cb,
193 data);
194 return G_SOURCE_REMOVE;
195 }
196
197 static void
198 run_tests (GNetworkMonitor *monitor,
199 TestAddress *addresses,
200 gboolean should_be_reachable)
201 {
202 GError *error = NULL;
203 int i;
204 gboolean reachable;
205 GSocketAddress *sockaddr;
206 CanReachData data;
207
208 data.monitor = monitor;
209 data.loop = g_main_loop_new (NULL, FALSE);
210
211 for (i = 0; addresses[i].address; i++)
212 {
213 sockaddr = g_inet_socket_address_new (addresses[i].address, 0);
214 reachable = g_network_monitor_can_reach (monitor,
215 G_SOCKET_CONNECTABLE (sockaddr),
216 NULL, &error);
217 data.sockaddr = sockaddr;
218 data.should_be_reachable = should_be_reachable;
219
220 g_idle_add (test_reach_async, &data);
221 g_main_loop_run (data.loop);
222
223 g_object_unref (sockaddr);
224 g_assert_cmpint (reachable, ==, should_be_reachable);
225 if (should_be_reachable)
226 g_assert_no_error (error);
227 else
228 {
229 g_assert (error != NULL);
230 g_clear_error (&error);
231 }
232 }
233
234 g_main_loop_unref (data.loop);
235 }
236
237 static void
238 test_default (void)
239 {
240 GNetworkMonitor *monitor, *m;
241 GError *error = NULL;
242
243 m = g_network_monitor_get_default ();
244 g_assert (G_IS_NETWORK_MONITOR (m));
245
246 monitor = g_object_new (G_TYPE_NETWORK_MONITOR_BASE, NULL);
247 g_initable_init (G_INITABLE (monitor), NULL, &error);
248 g_assert_no_error (error);
249
250 /* In the default configuration, all addresses are reachable */
251 run_tests (monitor, net127.addresses, TRUE);
252 run_tests (monitor, net10.addresses, TRUE);
253 run_tests (monitor, net192.addresses, TRUE);
254 run_tests (monitor, netlocal6.addresses, TRUE);
255 run_tests (monitor, netfe80.addresses, TRUE);
256 run_tests (monitor, unmatched, TRUE);
257
258 assert_signals (monitor, FALSE, FALSE, TRUE);
259
260 g_object_unref (monitor);
261 }
262
263 static void
264 test_remove_default (void)
265 {
266 GNetworkMonitor *monitor;
267 GError *error = NULL;
268
269 monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, &error, NULL);
270 g_assert_no_error (error);
271 assert_signals (monitor, FALSE, FALSE, TRUE);
272
273 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
274 ip4_default);
275 assert_signals (monitor, FALSE, TRUE, TRUE);
276 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
277 ip6_default);
278 assert_signals (monitor, TRUE, TRUE, FALSE);
279
280 /* Now nothing should be reachable */
281 run_tests (monitor, net127.addresses, FALSE);
282 run_tests (monitor, net10.addresses, FALSE);
283 run_tests (monitor, net192.addresses, FALSE);
284 run_tests (monitor, netlocal6.addresses, FALSE);
285 run_tests (monitor, netfe80.addresses, FALSE);
286 run_tests (monitor, unmatched, FALSE);
287
288 g_object_unref (monitor);
289 }
290
291 static void
292 test_add_networks (void)
293 {
294 GNetworkMonitor *monitor;
295 GError *error = NULL;
296
297 monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, &error, NULL);
298 g_assert_no_error (error);
299 assert_signals (monitor, FALSE, FALSE, TRUE);
300
301 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
302 ip4_default);
303 assert_signals (monitor, FALSE, TRUE, TRUE);
304 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
305 ip6_default);
306 assert_signals (monitor, TRUE, TRUE, FALSE);
307
308 /* Now add the masks one by one */
309
310 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
311 net127.mask);
312 assert_signals (monitor, FALSE, TRUE, FALSE);
313
314 run_tests (monitor, net127.addresses, TRUE);
315 run_tests (monitor, net10.addresses, FALSE);
316 run_tests (monitor, net192.addresses, FALSE);
317 run_tests (monitor, netlocal6.addresses, FALSE);
318 run_tests (monitor, netfe80.addresses, FALSE);
319 run_tests (monitor, unmatched, FALSE);
320
321 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
322 net10.mask);
323 assert_signals (monitor, FALSE, TRUE, FALSE);
324 run_tests (monitor, net127.addresses, TRUE);
325 run_tests (monitor, net10.addresses, TRUE);
326 run_tests (monitor, net192.addresses, FALSE);
327 run_tests (monitor, netlocal6.addresses, FALSE);
328 run_tests (monitor, netfe80.addresses, FALSE);
329 run_tests (monitor, unmatched, FALSE);
330
331 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
332 net192.mask);
333 assert_signals (monitor, FALSE, TRUE, FALSE);
334 run_tests (monitor, net127.addresses, TRUE);
335 run_tests (monitor, net10.addresses, TRUE);
336 run_tests (monitor, net192.addresses, TRUE);
337 run_tests (monitor, netlocal6.addresses, FALSE);
338 run_tests (monitor, netfe80.addresses, FALSE);
339 run_tests (monitor, unmatched, FALSE);
340
341 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
342 netlocal6.mask);
343 assert_signals (monitor, FALSE, TRUE, FALSE);
344 run_tests (monitor, net127.addresses, TRUE);
345 run_tests (monitor, net10.addresses, TRUE);
346 run_tests (monitor, net192.addresses, TRUE);
347 run_tests (monitor, netlocal6.addresses, TRUE);
348 run_tests (monitor, netfe80.addresses, FALSE);
349 run_tests (monitor, unmatched, FALSE);
350
351 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
352 netfe80.mask);
353 assert_signals (monitor, FALSE, TRUE, FALSE);
354 run_tests (monitor, net127.addresses, TRUE);
355 run_tests (monitor, net10.addresses, TRUE);
356 run_tests (monitor, net192.addresses, TRUE);
357 run_tests (monitor, netlocal6.addresses, TRUE);
358 run_tests (monitor, netfe80.addresses, TRUE);
359 run_tests (monitor, unmatched, FALSE);
360
361 g_object_unref (monitor);
362 }
363
364 static void
365 test_remove_networks (void)
366 {
367 GNetworkMonitor *monitor;
368 GError *error = NULL;
369
370 monitor = g_initable_new (G_TYPE_NETWORK_MONITOR_BASE, NULL, &error, NULL);
371 g_assert_no_error (error);
372 assert_signals (monitor, FALSE, FALSE, TRUE);
373
374 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
375 ip4_default);
376 assert_signals (monitor, FALSE, TRUE, TRUE);
377 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
378 ip6_default);
379 assert_signals (monitor, TRUE, TRUE, FALSE);
380
381 /* First add them */
382 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
383 net127.mask);
384 assert_signals (monitor, FALSE, TRUE, FALSE);
385 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
386 net10.mask);
387 assert_signals (monitor, FALSE, TRUE, FALSE);
388 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
389 net192.mask);
390 assert_signals (monitor, FALSE, TRUE, FALSE);
391 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
392 netlocal6.mask);
393 assert_signals (monitor, FALSE, TRUE, FALSE);
394 g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (monitor),
395 netfe80.mask);
396 assert_signals (monitor, FALSE, TRUE, FALSE);
397
398 run_tests (monitor, net127.addresses, TRUE);
399 run_tests (monitor, net10.addresses, TRUE);
400 run_tests (monitor, net192.addresses, TRUE);
401 run_tests (monitor, netlocal6.addresses, TRUE);
402 run_tests (monitor, netfe80.addresses, TRUE);
403 run_tests (monitor, unmatched, FALSE);
404
405 /* Now remove them one by one */
406 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
407 net127.mask);
408 assert_signals (monitor, FALSE, TRUE, FALSE);
409 run_tests (monitor, net127.addresses, FALSE);
410 run_tests (monitor, net10.addresses, TRUE);
411 run_tests (monitor, net192.addresses, TRUE);
412 run_tests (monitor, netlocal6.addresses, TRUE);
413 run_tests (monitor, netfe80.addresses, TRUE);
414 run_tests (monitor, unmatched, FALSE);
415
416 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
417 net10.mask);
418 assert_signals (monitor, FALSE, TRUE, FALSE);
419 run_tests (monitor, net127.addresses, FALSE);
420 run_tests (monitor, net10.addresses, FALSE);
421 run_tests (monitor, net192.addresses, TRUE);
422 run_tests (monitor, netlocal6.addresses, TRUE);
423 run_tests (monitor, netfe80.addresses, TRUE);
424 run_tests (monitor, unmatched, FALSE);
425
426 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
427 net192.mask);
428 assert_signals (monitor, FALSE, TRUE, FALSE);
429 run_tests (monitor, net127.addresses, FALSE);
430 run_tests (monitor, net10.addresses, FALSE);
431 run_tests (monitor, net192.addresses, FALSE);
432 run_tests (monitor, netlocal6.addresses, TRUE);
433 run_tests (monitor, netfe80.addresses, TRUE);
434 run_tests (monitor, unmatched, FALSE);
435
436 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
437 netlocal6.mask);
438 assert_signals (monitor, FALSE, TRUE, FALSE);
439 run_tests (monitor, net127.addresses, FALSE);
440 run_tests (monitor, net10.addresses, FALSE);
441 run_tests (monitor, net192.addresses, FALSE);
442 run_tests (monitor, netlocal6.addresses, FALSE);
443 run_tests (monitor, netfe80.addresses, TRUE);
444 run_tests (monitor, unmatched, FALSE);
445
446 g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (monitor),
447 netfe80.mask);
448 assert_signals (monitor, FALSE, TRUE, FALSE);
449 run_tests (monitor, net127.addresses, FALSE);
450 run_tests (monitor, net10.addresses, FALSE);
451 run_tests (monitor, net192.addresses, FALSE);
452 run_tests (monitor, netlocal6.addresses, FALSE);
453 run_tests (monitor, netfe80.addresses, FALSE);
454 run_tests (monitor, unmatched, FALSE);
455
456 g_object_unref (monitor);
457 }
458
459
460 static void
461 init_test (TestMask *test)
462 {
463 GError *error = NULL;
464 int i;
465
466 test->mask = g_inet_address_mask_new_from_string (test->mask_string, &error);
467 g_assert_no_error (error);
468
469 for (i = 0; test->addresses[i].string; i++)
470 {
471 test->addresses[i].address = g_inet_address_new_from_string (test->addresses[i].string);
472 if (strchr (test->addresses[i].string, ':'))
473 g_assert_cmpint (g_inet_address_get_family (test->addresses[i].address), ==, G_SOCKET_FAMILY_IPV6);
474 else
475 g_assert_cmpint (g_inet_address_get_family (test->addresses[i].address), ==, G_SOCKET_FAMILY_IPV4);
476 }
477 }
478
479 static void
480 cleanup_test (TestMask *test)
481 {
482 int i;
483
484 g_object_unref (test->mask);
485 for (i = 0; test->addresses[i].string; i++)
486 g_object_unref (test->addresses[i].address);
487 }
488
489 static void
490 watch_network_changed (GNetworkMonitor *monitor,
491 gboolean available,
492 gpointer user_data)
493 {
494 g_print ("Network is %s\n", available ? "up" : "down");
495 }
496
497 static void
498 watch_connectivity_changed (GNetworkMonitor *monitor,
499 GParamSpec *pspec,
500 gpointer user_data)
501 {
502 g_print ("Connectivity is %d\n", g_network_monitor_get_connectivity (monitor));
503 }
504
505 static void
506 watch_metered_changed (GNetworkMonitor *monitor,
507 GParamSpec *pspec,
508 gpointer user_data)
509 {
510 g_print ("Metered is %d\n", g_network_monitor_get_network_metered (monitor));
511 }
512
513 static void
514 do_watch_network (void)
515 {
516 GNetworkMonitor *monitor = g_network_monitor_get_default ();
517 GMainLoop *loop;
518
519 g_print ("Monitoring via %s\n", g_type_name_from_instance ((GTypeInstance *) monitor));
520
521 g_signal_connect (monitor, "network-changed",
522 G_CALLBACK (watch_network_changed), NULL);
523 g_signal_connect (monitor, "notify::connectivity",
524 G_CALLBACK (watch_connectivity_changed), NULL);
525 g_signal_connect (monitor, "notify::network-metered",
526 G_CALLBACK (watch_metered_changed), NULL);
527 watch_network_changed (monitor, g_network_monitor_get_network_available (monitor), NULL);
528 watch_connectivity_changed (monitor, NULL, NULL);
529 watch_metered_changed (monitor, NULL, NULL);
530
531 loop = g_main_loop_new (NULL, FALSE);
532 g_main_loop_run (loop);
533 }
534
535 int
536 main (int argc, char **argv)
537 {
538 int ret;
539
540 if (argc == 2 && !strcmp (argv[1], "--watch"))
541 {
542 do_watch_network ();
543 return 0;
544 }
545
546 g_test_init (&argc, &argv, NULL);
547
548 /* GNetworkMonitor will resolve addresses through a proxy if one is set and a
549 * GIO module is available to handle it. In these tests we deliberately
550 * change the idea of a reachable network to exclude the proxy, which will
551 * lead to negative results. We're not trying to test the proxy-resolving
552 * functionality (that would be for e.g. glib-networking's testsuite), so
553 * let's just use the dummy proxy resolver, which always pretends the
554 * passed-in URL is directly resolvable.
555 */
556 g_setenv ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE);
557
558 init_test (&net127);
559 init_test (&net10);
560 init_test (&net192);
561 init_test (&netlocal6);
562 init_test (&netfe80);
563 ip4_default = g_inet_address_mask_new_from_string ("0.0.0.0/0", NULL);
564 ip6_default = g_inet_address_mask_new_from_string ("::/0", NULL);
565
566 g_test_add_func ("/network-monitor/default", test_default);
567 g_test_add_func ("/network-monitor/remove_default", test_remove_default);
568 g_test_add_func ("/network-monitor/add_networks", test_add_networks);
569 g_test_add_func ("/network-monitor/remove_networks", test_remove_networks);
570
571 ret = g_test_run ();
572
573 cleanup_test (&net127);
574 cleanup_test (&net10);
575 cleanup_test (&net192);
576 cleanup_test (&netlocal6);
577 cleanup_test (&netfe80);
578 g_object_unref (ip4_default);
579 g_object_unref (ip6_default);
580
581 return ret;
582 }