Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
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 : : * Authors: Christian Kellner <gicmo@gnome.org>
21 : : * Samuel Cormier-Iijima <sciyoshi@gmail.com>
22 : : */
23 : :
24 : : #include <config.h>
25 : :
26 : : #include <string.h>
27 : :
28 : : #include <glib.h>
29 : :
30 : : #include "ginetaddress.h"
31 : : #include "gioenums.h"
32 : : #include "gioenumtypes.h"
33 : : #include "glibintl.h"
34 : : #include "gnetworkingprivate.h"
35 : :
36 : : struct _GInetAddressPrivate
37 : : {
38 : : GSocketFamily family;
39 : : union {
40 : : struct in_addr ipv4;
41 : : #ifdef HAVE_IPV6
42 : : struct in6_addr ipv6;
43 : : #endif
44 : : } addr;
45 : : };
46 : :
47 : : /**
48 : : * GInetAddress:
49 : : *
50 : : * `GInetAddress` represents an IPv4 or IPv6 internet address. Use
51 : : * [method@Gio.Resolver.lookup_by_name] or
52 : : * [method@Gio.Resolver.lookup_by_name_async] to look up the `GInetAddress` for
53 : : * a hostname. Use [method@Gio.Resolver.lookup_by_address] or
54 : : * [method@Gio.Resolver.lookup_by_address_async] to look up the hostname for a
55 : : * `GInetAddress`.
56 : : *
57 : : * To actually connect to a remote host, you will need a
58 : : * [class@Gio.InetSocketAddress] (which includes a `GInetAddress` as well as a
59 : : * port number).
60 : : */
61 : :
62 : 10611 : G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT,
63 : : G_ADD_PRIVATE (GInetAddress)
64 : : g_networking_init ();)
65 : :
66 : : enum
67 : : {
68 : : PROP_0,
69 : : PROP_FAMILY,
70 : : PROP_BYTES,
71 : : PROP_IS_ANY,
72 : : PROP_IS_LOOPBACK,
73 : : PROP_IS_LINK_LOCAL,
74 : : PROP_IS_SITE_LOCAL,
75 : : PROP_IS_MULTICAST,
76 : : PROP_IS_MC_GLOBAL,
77 : : PROP_IS_MC_LINK_LOCAL,
78 : : PROP_IS_MC_NODE_LOCAL,
79 : : PROP_IS_MC_ORG_LOCAL,
80 : : PROP_IS_MC_SITE_LOCAL,
81 : : };
82 : :
83 : : static void
84 : 1630 : g_inet_address_set_property (GObject *object,
85 : : guint prop_id,
86 : : const GValue *value,
87 : : GParamSpec *pspec)
88 : : {
89 : 1630 : GInetAddress *address = G_INET_ADDRESS (object);
90 : :
91 : 1630 : switch (prop_id)
92 : : {
93 : 815 : case PROP_FAMILY:
94 : 815 : address->priv->family = g_value_get_enum (value);
95 : 815 : break;
96 : :
97 : 815 : case PROP_BYTES:
98 : : #ifdef HAVE_IPV6
99 : 815 : memcpy (&address->priv->addr, g_value_get_pointer (value),
100 : 815 : address->priv->family == AF_INET ?
101 : : sizeof (address->priv->addr.ipv4) :
102 : : sizeof (address->priv->addr.ipv6));
103 : : #else
104 : : g_assert (address->priv->family == AF_INET);
105 : : memcpy (&address->priv->addr, g_value_get_pointer (value),
106 : : sizeof (address->priv->addr.ipv4));
107 : : #endif
108 : 815 : break;
109 : :
110 : 0 : default:
111 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112 : 0 : break;
113 : : }
114 : :
115 : 1630 : }
116 : :
117 : : static void
118 : 12 : g_inet_address_get_property (GObject *object,
119 : : guint prop_id,
120 : : GValue *value,
121 : : GParamSpec *pspec)
122 : : {
123 : 12 : GInetAddress *address = G_INET_ADDRESS (object);
124 : :
125 : 12 : switch (prop_id)
126 : : {
127 : 1 : case PROP_FAMILY:
128 : 1 : g_value_set_enum (value, address->priv->family);
129 : 1 : break;
130 : :
131 : 1 : case PROP_BYTES:
132 : 1 : g_value_set_pointer (value, &address->priv->addr);
133 : 1 : break;
134 : :
135 : 1 : case PROP_IS_ANY:
136 : 1 : g_value_set_boolean (value, g_inet_address_get_is_any (address));
137 : 1 : break;
138 : :
139 : 1 : case PROP_IS_LOOPBACK:
140 : 1 : g_value_set_boolean (value, g_inet_address_get_is_loopback (address));
141 : 1 : break;
142 : :
143 : 1 : case PROP_IS_LINK_LOCAL:
144 : 1 : g_value_set_boolean (value, g_inet_address_get_is_link_local (address));
145 : 1 : break;
146 : :
147 : 1 : case PROP_IS_SITE_LOCAL:
148 : 1 : g_value_set_boolean (value, g_inet_address_get_is_site_local (address));
149 : 1 : break;
150 : :
151 : 1 : case PROP_IS_MULTICAST:
152 : 1 : g_value_set_boolean (value, g_inet_address_get_is_multicast (address));
153 : 1 : break;
154 : :
155 : 1 : case PROP_IS_MC_GLOBAL:
156 : 1 : g_value_set_boolean (value, g_inet_address_get_is_mc_global (address));
157 : 1 : break;
158 : :
159 : 1 : case PROP_IS_MC_LINK_LOCAL:
160 : 1 : g_value_set_boolean (value, g_inet_address_get_is_mc_link_local (address));
161 : 1 : break;
162 : :
163 : 1 : case PROP_IS_MC_NODE_LOCAL:
164 : 1 : g_value_set_boolean (value, g_inet_address_get_is_mc_node_local (address));
165 : 1 : break;
166 : :
167 : 1 : case PROP_IS_MC_ORG_LOCAL:
168 : 1 : g_value_set_boolean (value, g_inet_address_get_is_mc_org_local (address));
169 : 1 : break;
170 : :
171 : 1 : case PROP_IS_MC_SITE_LOCAL:
172 : 1 : g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address));
173 : 1 : break;
174 : :
175 : 0 : default:
176 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
177 : : }
178 : 12 : }
179 : :
180 : : static void
181 : 36 : g_inet_address_class_init (GInetAddressClass *klass)
182 : : {
183 : 36 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
184 : :
185 : 36 : gobject_class->set_property = g_inet_address_set_property;
186 : 36 : gobject_class->get_property = g_inet_address_get_property;
187 : :
188 : : /**
189 : : * GInetAddress:family:
190 : : *
191 : : * The address family (IPv4 or IPv6).
192 : : *
193 : : * Since: 2.22
194 : : */
195 : 36 : g_object_class_install_property (gobject_class, PROP_FAMILY,
196 : : g_param_spec_enum ("family", NULL, NULL,
197 : : G_TYPE_SOCKET_FAMILY,
198 : : G_SOCKET_FAMILY_INVALID,
199 : : G_PARAM_READWRITE |
200 : : G_PARAM_CONSTRUCT_ONLY |
201 : : G_PARAM_STATIC_STRINGS));
202 : :
203 : : /**
204 : : * GInetAddress:bytes:
205 : : *
206 : : * The raw address data.
207 : : *
208 : : * Since: 2.22
209 : : */
210 : 36 : g_object_class_install_property (gobject_class, PROP_BYTES,
211 : : g_param_spec_pointer ("bytes", NULL, NULL,
212 : : G_PARAM_READWRITE |
213 : : G_PARAM_CONSTRUCT_ONLY |
214 : : G_PARAM_STATIC_STRINGS));
215 : :
216 : : /**
217 : : * GInetAddress:is-any:
218 : : *
219 : : * Whether this is the "any" address for its family.
220 : : * See g_inet_address_get_is_any().
221 : : *
222 : : * Since: 2.22
223 : : */
224 : 36 : g_object_class_install_property (gobject_class, PROP_IS_ANY,
225 : : g_param_spec_boolean ("is-any", NULL, NULL,
226 : : FALSE,
227 : : G_PARAM_READABLE |
228 : : G_PARAM_STATIC_STRINGS));
229 : :
230 : : /**
231 : : * GInetAddress:is-link-local:
232 : : *
233 : : * Whether this is a link-local address.
234 : : * See g_inet_address_get_is_link_local().
235 : : *
236 : : * Since: 2.22
237 : : */
238 : 36 : g_object_class_install_property (gobject_class, PROP_IS_LINK_LOCAL,
239 : : g_param_spec_boolean ("is-link-local", NULL, NULL,
240 : : FALSE,
241 : : G_PARAM_READABLE |
242 : : G_PARAM_STATIC_STRINGS));
243 : :
244 : : /**
245 : : * GInetAddress:is-loopback:
246 : : *
247 : : * Whether this is the loopback address for its family.
248 : : * See g_inet_address_get_is_loopback().
249 : : *
250 : : * Since: 2.22
251 : : */
252 : 36 : g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK,
253 : : g_param_spec_boolean ("is-loopback", NULL, NULL,
254 : : FALSE,
255 : : G_PARAM_READABLE |
256 : : G_PARAM_STATIC_STRINGS));
257 : :
258 : : /**
259 : : * GInetAddress:is-site-local:
260 : : *
261 : : * Whether this is a site-local address.
262 : : * See g_inet_address_get_is_loopback().
263 : : *
264 : : * Since: 2.22
265 : : */
266 : 36 : g_object_class_install_property (gobject_class, PROP_IS_SITE_LOCAL,
267 : : g_param_spec_boolean ("is-site-local", NULL, NULL,
268 : : FALSE,
269 : : G_PARAM_READABLE |
270 : : G_PARAM_STATIC_STRINGS));
271 : :
272 : : /**
273 : : * GInetAddress:is-multicast:
274 : : *
275 : : * Whether this is a multicast address.
276 : : * See g_inet_address_get_is_multicast().
277 : : *
278 : : * Since: 2.22
279 : : */
280 : 36 : g_object_class_install_property (gobject_class, PROP_IS_MULTICAST,
281 : : g_param_spec_boolean ("is-multicast", NULL, NULL,
282 : : FALSE,
283 : : G_PARAM_READABLE |
284 : : G_PARAM_STATIC_STRINGS));
285 : :
286 : : /**
287 : : * GInetAddress:is-mc-global:
288 : : *
289 : : * Whether this is a global multicast address.
290 : : * See g_inet_address_get_is_mc_global().
291 : : *
292 : : * Since: 2.22
293 : : */
294 : 36 : g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL,
295 : : g_param_spec_boolean ("is-mc-global", NULL, NULL,
296 : : FALSE,
297 : : G_PARAM_READABLE |
298 : : G_PARAM_STATIC_STRINGS));
299 : :
300 : :
301 : : /**
302 : : * GInetAddress:is-mc-link-local:
303 : : *
304 : : * Whether this is a link-local multicast address.
305 : : * See g_inet_address_get_is_mc_link_local().
306 : : *
307 : : * Since: 2.22
308 : : */
309 : 36 : g_object_class_install_property (gobject_class, PROP_IS_MC_LINK_LOCAL,
310 : : g_param_spec_boolean ("is-mc-link-local", NULL, NULL,
311 : : FALSE,
312 : : G_PARAM_READABLE |
313 : : G_PARAM_STATIC_STRINGS));
314 : :
315 : : /**
316 : : * GInetAddress:is-mc-node-local:
317 : : *
318 : : * Whether this is a node-local multicast address.
319 : : * See g_inet_address_get_is_mc_node_local().
320 : : *
321 : : * Since: 2.22
322 : : */
323 : 36 : g_object_class_install_property (gobject_class, PROP_IS_MC_NODE_LOCAL,
324 : : g_param_spec_boolean ("is-mc-node-local", NULL, NULL,
325 : : FALSE,
326 : : G_PARAM_READABLE |
327 : : G_PARAM_STATIC_STRINGS));
328 : :
329 : : /**
330 : : * GInetAddress:is-mc-org-local:
331 : : *
332 : : * Whether this is an organization-local multicast address.
333 : : * See g_inet_address_get_is_mc_org_local().
334 : : *
335 : : * Since: 2.22
336 : : */
337 : 36 : g_object_class_install_property (gobject_class, PROP_IS_MC_ORG_LOCAL,
338 : : g_param_spec_boolean ("is-mc-org-local", NULL, NULL,
339 : : FALSE,
340 : : G_PARAM_READABLE |
341 : : G_PARAM_STATIC_STRINGS));
342 : :
343 : : /**
344 : : * GInetAddress:is-mc-site-local:
345 : : *
346 : : * Whether this is a site-local multicast address.
347 : : * See g_inet_address_get_is_mc_site_local().
348 : : *
349 : : * Since: 2.22
350 : : */
351 : 36 : g_object_class_install_property (gobject_class, PROP_IS_MC_SITE_LOCAL,
352 : : g_param_spec_boolean ("is-mc-site-local", NULL, NULL,
353 : : FALSE,
354 : : G_PARAM_READABLE |
355 : : G_PARAM_STATIC_STRINGS));
356 : 36 : }
357 : :
358 : : static void
359 : 815 : g_inet_address_init (GInetAddress *address)
360 : : {
361 : 815 : address->priv = g_inet_address_get_instance_private (address);
362 : 815 : }
363 : :
364 : : /**
365 : : * g_inet_address_new_from_string:
366 : : * @string: a string representation of an IP address
367 : : *
368 : : * Parses @string as an IP address and creates a new #GInetAddress.
369 : : *
370 : : * Returns: (nullable) (transfer full): a new #GInetAddress corresponding
371 : : * to @string, or %NULL if @string could not be parsed.
372 : : * Free the returned object with g_object_unref().
373 : : *
374 : : * Since: 2.22
375 : : */
376 : : GInetAddress *
377 : 385 : g_inet_address_new_from_string (const gchar *string)
378 : : {
379 : : struct in_addr in_addr;
380 : : #ifdef HAVE_IPV6
381 : : struct in6_addr in6_addr;
382 : : #endif
383 : :
384 : 385 : g_return_val_if_fail (string != NULL, NULL);
385 : :
386 : : /* If this GInetAddress is the first networking-related object to be
387 : : * created, then we won't have called g_networking_init() yet at
388 : : * this point.
389 : : */
390 : 385 : g_networking_init ();
391 : :
392 : 385 : if (inet_pton (AF_INET, string, &in_addr) > 0)
393 : 155 : return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
394 : : #ifdef HAVE_IPV6
395 : 230 : else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
396 : 65 : return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
397 : : #endif
398 : :
399 : 165 : return NULL;
400 : : }
401 : :
402 : : #define G_INET_ADDRESS_FAMILY_IS_VALID(family) ((family) == AF_INET || (family) == AF_INET6)
403 : :
404 : : /**
405 : : * g_inet_address_new_from_bytes:
406 : : * @bytes: (array) (element-type guint8): raw address data
407 : : * @family: the address family of @bytes
408 : : *
409 : : * Creates a new #GInetAddress from the given @family and @bytes.
410 : : * @bytes should be 4 bytes for %G_SOCKET_FAMILY_IPV4 and 16 bytes for
411 : : * %G_SOCKET_FAMILY_IPV6.
412 : : *
413 : : * Returns: a new #GInetAddress corresponding to @family and @bytes.
414 : : * Free the returned object with g_object_unref().
415 : : *
416 : : * Since: 2.22
417 : : */
418 : : GInetAddress *
419 : 815 : g_inet_address_new_from_bytes (const guint8 *bytes,
420 : : GSocketFamily family)
421 : : {
422 : 815 : g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
423 : :
424 : 815 : return g_object_new (G_TYPE_INET_ADDRESS,
425 : : "family", family,
426 : : "bytes", bytes,
427 : : NULL);
428 : : }
429 : :
430 : : /**
431 : : * g_inet_address_new_loopback:
432 : : * @family: the address family
433 : : *
434 : : * Creates a #GInetAddress for the loopback address for @family.
435 : : *
436 : : * Returns: a new #GInetAddress corresponding to the loopback address
437 : : * for @family.
438 : : * Free the returned object with g_object_unref().
439 : : *
440 : : * Since: 2.22
441 : : */
442 : : GInetAddress *
443 : 50 : g_inet_address_new_loopback (GSocketFamily family)
444 : : {
445 : 50 : g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
446 : :
447 : 50 : if (family == AF_INET)
448 : : {
449 : 36 : guint8 addr[4] = {127, 0, 0, 1};
450 : :
451 : 36 : return g_inet_address_new_from_bytes (addr, family);
452 : : }
453 : : else
454 : : #ifdef HAVE_IPV6
455 : 14 : return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
456 : : #else
457 : : g_assert_not_reached ();
458 : : #endif
459 : : }
460 : :
461 : : /**
462 : : * g_inet_address_new_any:
463 : : * @family: the address family
464 : : *
465 : : * Creates a #GInetAddress for the "any" address (unassigned/"don't
466 : : * care") for @family.
467 : : *
468 : : * Returns: a new #GInetAddress corresponding to the "any" address
469 : : * for @family.
470 : : * Free the returned object with g_object_unref().
471 : : *
472 : : * Since: 2.22
473 : : */
474 : : GInetAddress *
475 : 53 : g_inet_address_new_any (GSocketFamily family)
476 : : {
477 : 53 : g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
478 : :
479 : 53 : if (family == AF_INET)
480 : : {
481 : 47 : guint8 addr[4] = {0, 0, 0, 0};
482 : :
483 : 47 : return g_inet_address_new_from_bytes (addr, family);
484 : : }
485 : : else
486 : : #ifdef HAVE_IPV6
487 : 6 : return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
488 : : #else
489 : : g_assert_not_reached ();
490 : : #endif
491 : : }
492 : :
493 : :
494 : : /**
495 : : * g_inet_address_to_string:
496 : : * @address: a #GInetAddress
497 : : *
498 : : * Converts @address to string form.
499 : : *
500 : : * Returns: a representation of @address as a string, which should be
501 : : * freed after use.
502 : : *
503 : : * Since: 2.22
504 : : */
505 : : gchar *
506 : 462 : g_inet_address_to_string (GInetAddress *address)
507 : : {
508 : : gchar buffer[INET6_ADDRSTRLEN];
509 : :
510 : 462 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
511 : :
512 : 462 : if (address->priv->family == AF_INET)
513 : : {
514 : 361 : inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
515 : 361 : return g_strdup (buffer);
516 : : }
517 : : else
518 : : {
519 : : #ifdef HAVE_IPV6
520 : 101 : inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
521 : 101 : return g_strdup (buffer);
522 : : #else
523 : : g_assert_not_reached ();
524 : : #endif
525 : : }
526 : : }
527 : :
528 : : /**
529 : : * g_inet_address_to_bytes: (skip)
530 : : * @address: a #GInetAddress
531 : : *
532 : : * Gets the raw binary address data from @address.
533 : : *
534 : : * Returns: a pointer to an internal array of the bytes in @address,
535 : : * which should not be modified, stored, or freed. The size of this
536 : : * array can be gotten with g_inet_address_get_native_size().
537 : : *
538 : : * Since: 2.22
539 : : */
540 : : const guint8 *
541 : 2237 : g_inet_address_to_bytes (GInetAddress *address)
542 : : {
543 : 2237 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
544 : :
545 : 2237 : return (guint8 *)&address->priv->addr;
546 : : }
547 : :
548 : : /**
549 : : * g_inet_address_get_native_size:
550 : : * @address: a #GInetAddress
551 : : *
552 : : * Gets the size of the native raw binary address for @address. This
553 : : * is the size of the data that you get from g_inet_address_to_bytes().
554 : : *
555 : : * Returns: the number of bytes used for the native version of @address.
556 : : *
557 : : * Since: 2.22
558 : : */
559 : : gsize
560 : 1072 : g_inet_address_get_native_size (GInetAddress *address)
561 : : {
562 : 1072 : if (address->priv->family == AF_INET)
563 : 667 : return sizeof (address->priv->addr.ipv4);
564 : : #ifdef HAVE_IPV6
565 : 405 : return sizeof (address->priv->addr.ipv6);
566 : : #else
567 : : g_assert_not_reached ();
568 : : #endif
569 : : }
570 : :
571 : : /**
572 : : * g_inet_address_get_family:
573 : : * @address: a #GInetAddress
574 : : *
575 : : * Gets @address's family
576 : : *
577 : : * Returns: @address's family
578 : : *
579 : : * Since: 2.22
580 : : */
581 : : GSocketFamily
582 : 2590 : g_inet_address_get_family (GInetAddress *address)
583 : : {
584 : 2590 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
585 : :
586 : 2590 : return address->priv->family;
587 : : }
588 : :
589 : : /**
590 : : * g_inet_address_get_is_any:
591 : : * @address: a #GInetAddress
592 : : *
593 : : * Tests whether @address is the "any" address for its family.
594 : : *
595 : : * Returns: %TRUE if @address is the "any" address for its family.
596 : : *
597 : : * Since: 2.22
598 : : */
599 : : gboolean
600 : 3 : g_inet_address_get_is_any (GInetAddress *address)
601 : : {
602 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
603 : :
604 : 3 : if (address->priv->family == AF_INET)
605 : : {
606 : 1 : guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
607 : :
608 : 1 : return addr4 == INADDR_ANY;
609 : : }
610 : : else
611 : : #ifdef HAVE_IPV6
612 : 2 : return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6);
613 : : #else
614 : : g_assert_not_reached ();
615 : : #endif
616 : : }
617 : :
618 : : /**
619 : : * g_inet_address_get_is_loopback:
620 : : * @address: a #GInetAddress
621 : : *
622 : : * Tests whether @address is the loopback address for its family.
623 : : *
624 : : * Returns: %TRUE if @address is the loopback address for its family.
625 : : *
626 : : * Since: 2.22
627 : : */
628 : : gboolean
629 : 6 : g_inet_address_get_is_loopback (GInetAddress *address)
630 : : {
631 : 6 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
632 : :
633 : 6 : if (address->priv->family == AF_INET)
634 : : {
635 : 2 : guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
636 : :
637 : : /* 127.0.0.0/8 */
638 : 2 : return ((addr4 & 0xff000000) == 0x7f000000);
639 : : }
640 : : else
641 : : #ifdef HAVE_IPV6
642 : 4 : return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6);
643 : : #else
644 : : g_assert_not_reached ();
645 : : #endif
646 : : }
647 : :
648 : : /**
649 : : * g_inet_address_get_is_link_local:
650 : : * @address: a #GInetAddress
651 : : *
652 : : * Tests whether @address is a link-local address (that is, if it
653 : : * identifies a host on a local network that is not connected to the
654 : : * Internet).
655 : : *
656 : : * Returns: %TRUE if @address is a link-local address.
657 : : *
658 : : * Since: 2.22
659 : : */
660 : : gboolean
661 : 3 : g_inet_address_get_is_link_local (GInetAddress *address)
662 : : {
663 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
664 : :
665 : 3 : if (address->priv->family == AF_INET)
666 : : {
667 : 1 : guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
668 : :
669 : : /* 169.254.0.0/16 */
670 : 1 : return ((addr4 & 0xffff0000) == 0xa9fe0000);
671 : : }
672 : : else
673 : : #ifdef HAVE_IPV6
674 : 2 : return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6);
675 : : #else
676 : : g_assert_not_reached ();
677 : : #endif
678 : : }
679 : :
680 : : /**
681 : : * g_inet_address_get_is_site_local:
682 : : * @address: a #GInetAddress
683 : : *
684 : : * Tests whether @address is a site-local address such as 10.0.0.1
685 : : * (that is, the address identifies a host on a local network that can
686 : : * not be reached directly from the Internet, but which may have
687 : : * outgoing Internet connectivity via a NAT or firewall).
688 : : *
689 : : * Returns: %TRUE if @address is a site-local address.
690 : : *
691 : : * Since: 2.22
692 : : */
693 : : gboolean
694 : 3 : g_inet_address_get_is_site_local (GInetAddress *address)
695 : : {
696 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
697 : :
698 : 3 : if (address->priv->family == AF_INET)
699 : : {
700 : 1 : guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
701 : :
702 : : /* 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
703 : 2 : return ((addr4 & 0xff000000) == 0x0a000000 ||
704 : 2 : (addr4 & 0xfff00000) == 0xac100000 ||
705 : 1 : (addr4 & 0xffff0000) == 0xc0a80000);
706 : : }
707 : : else
708 : : #ifdef HAVE_IPV6
709 : 2 : return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6);
710 : : #else
711 : : g_assert_not_reached ();
712 : : #endif
713 : : }
714 : :
715 : : /**
716 : : * g_inet_address_get_is_multicast:
717 : : * @address: a #GInetAddress
718 : : *
719 : : * Tests whether @address is a multicast address.
720 : : *
721 : : * Returns: %TRUE if @address is a multicast address.
722 : : *
723 : : * Since: 2.22
724 : : */
725 : : gboolean
726 : 3 : g_inet_address_get_is_multicast (GInetAddress *address)
727 : : {
728 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
729 : :
730 : 3 : if (address->priv->family == AF_INET)
731 : : {
732 : 1 : guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
733 : :
734 : 1 : return IN_MULTICAST (addr4);
735 : : }
736 : : else
737 : : #ifdef HAVE_IPV6
738 : 2 : return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6);
739 : : #else
740 : : g_assert_not_reached ();
741 : : #endif
742 : : }
743 : :
744 : : /**
745 : : * g_inet_address_get_is_mc_global:
746 : : * @address: a #GInetAddress
747 : : *
748 : : * Tests whether @address is a global multicast address.
749 : : *
750 : : * Returns: %TRUE if @address is a global multicast address.
751 : : *
752 : : * Since: 2.22
753 : : */
754 : : gboolean
755 : 3 : g_inet_address_get_is_mc_global (GInetAddress *address)
756 : : {
757 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
758 : :
759 : 3 : if (address->priv->family == AF_INET)
760 : 1 : return FALSE;
761 : : else
762 : : #ifdef HAVE_IPV6
763 : 2 : return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6);
764 : : #else
765 : : g_assert_not_reached ();
766 : : #endif
767 : : }
768 : :
769 : : /**
770 : : * g_inet_address_get_is_mc_link_local:
771 : : * @address: a #GInetAddress
772 : : *
773 : : * Tests whether @address is a link-local multicast address.
774 : : *
775 : : * Returns: %TRUE if @address is a link-local multicast address.
776 : : *
777 : : * Since: 2.22
778 : : */
779 : : gboolean
780 : 483 : g_inet_address_get_is_mc_link_local (GInetAddress *address)
781 : : {
782 : 483 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
783 : :
784 : 483 : if (address->priv->family == AF_INET)
785 : 305 : return FALSE;
786 : : else
787 : : #ifdef HAVE_IPV6
788 : 178 : return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6);
789 : : #else
790 : : g_assert_not_reached ();
791 : : #endif
792 : : }
793 : :
794 : : /**
795 : : * g_inet_address_get_is_mc_node_local:
796 : : * @address: a #GInetAddress
797 : : *
798 : : * Tests whether @address is a node-local multicast address.
799 : : *
800 : : * Returns: %TRUE if @address is a node-local multicast address.
801 : : *
802 : : * Since: 2.22
803 : : */
804 : : gboolean
805 : 3 : g_inet_address_get_is_mc_node_local (GInetAddress *address)
806 : : {
807 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
808 : :
809 : 3 : if (address->priv->family == AF_INET)
810 : 1 : return FALSE;
811 : : else
812 : : #ifdef HAVE_IPV6
813 : 2 : return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6);
814 : : #else
815 : : g_assert_not_reached ();
816 : : #endif
817 : : }
818 : :
819 : : /**
820 : : * g_inet_address_get_is_mc_org_local:
821 : : * @address: a #GInetAddress
822 : : *
823 : : * Tests whether @address is an organization-local multicast address.
824 : : *
825 : : * Returns: %TRUE if @address is an organization-local multicast address.
826 : : *
827 : : * Since: 2.22
828 : : */
829 : : gboolean
830 : 3 : g_inet_address_get_is_mc_org_local (GInetAddress *address)
831 : : {
832 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
833 : :
834 : 3 : if (address->priv->family == AF_INET)
835 : 1 : return FALSE;
836 : : else
837 : : #ifdef HAVE_IPV6
838 : 2 : return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6);
839 : : #else
840 : : g_assert_not_reached ();
841 : : #endif
842 : : }
843 : :
844 : : /**
845 : : * g_inet_address_get_is_mc_site_local:
846 : : * @address: a #GInetAddress
847 : : *
848 : : * Tests whether @address is a site-local multicast address.
849 : : *
850 : : * Returns: %TRUE if @address is a site-local multicast address.
851 : : *
852 : : * Since: 2.22
853 : : */
854 : : gboolean
855 : 3 : g_inet_address_get_is_mc_site_local (GInetAddress *address)
856 : : {
857 : 3 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
858 : :
859 : 3 : if (address->priv->family == AF_INET)
860 : 1 : return FALSE;
861 : : else
862 : : #ifdef HAVE_IPV6
863 : 2 : return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6);
864 : : #else
865 : : g_assert_not_reached ();
866 : : #endif
867 : : }
868 : :
869 : : /**
870 : : * g_inet_address_equal:
871 : : * @address: A #GInetAddress.
872 : : * @other_address: Another #GInetAddress.
873 : : *
874 : : * Checks if two #GInetAddress instances are equal, e.g. the same address.
875 : : *
876 : : * Returns: %TRUE if @address and @other_address are equal, %FALSE otherwise.
877 : : *
878 : : * Since: 2.30
879 : : */
880 : : gboolean
881 : 79 : g_inet_address_equal (GInetAddress *address,
882 : : GInetAddress *other_address)
883 : : {
884 : 79 : g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
885 : 79 : g_return_val_if_fail (G_IS_INET_ADDRESS (other_address), FALSE);
886 : :
887 : 79 : if (g_inet_address_get_family (address) != g_inet_address_get_family (other_address))
888 : 4 : return FALSE;
889 : :
890 : 150 : if (memcmp (g_inet_address_to_bytes (address),
891 : 75 : g_inet_address_to_bytes (other_address),
892 : : g_inet_address_get_native_size (address)) != 0)
893 : 21 : return FALSE;
894 : :
895 : 54 : return TRUE;
896 : : }
|