Coverage Report

Created: 2025-06-13 06:21

/src/glib/gio/ginetaddress.c
Line
Count
Source (jump to first uncovered line)
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
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
g_inet_address_set_property (GObject      *object,
85
           guint         prop_id,
86
           const GValue *value,
87
           GParamSpec   *pspec)
88
786
{
89
786
  GInetAddress *address = G_INET_ADDRESS (object);
90
91
786
  switch (prop_id)
92
786
    {
93
393
    case PROP_FAMILY:
94
393
      address->priv->family = g_value_get_enum (value);
95
393
      break;
96
97
393
    case PROP_BYTES:
98
393
#ifdef HAVE_IPV6
99
393
      memcpy (&address->priv->addr, g_value_get_pointer (value),
100
393
        address->priv->family == AF_INET ?
101
20
        sizeof (address->priv->addr.ipv4) :
102
393
        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
393
      break;
109
110
0
    default:
111
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112
0
      break;
113
786
    }
114
115
786
}
116
117
static void
118
g_inet_address_get_property (GObject    *object,
119
                             guint       prop_id,
120
                             GValue     *value,
121
                             GParamSpec *pspec)
122
0
{
123
0
  GInetAddress *address = G_INET_ADDRESS (object);
124
125
0
  switch (prop_id)
126
0
    {
127
0
    case PROP_FAMILY:
128
0
      g_value_set_enum (value, address->priv->family);
129
0
      break;
130
131
0
    case PROP_BYTES:
132
0
      g_value_set_pointer (value, &address->priv->addr);
133
0
      break;
134
135
0
    case PROP_IS_ANY:
136
0
      g_value_set_boolean (value, g_inet_address_get_is_any (address));
137
0
      break;
138
139
0
    case PROP_IS_LOOPBACK:
140
0
      g_value_set_boolean (value, g_inet_address_get_is_loopback (address));
141
0
      break;
142
143
0
    case PROP_IS_LINK_LOCAL:
144
0
      g_value_set_boolean (value, g_inet_address_get_is_link_local (address));
145
0
      break;
146
147
0
    case PROP_IS_SITE_LOCAL:
148
0
      g_value_set_boolean (value, g_inet_address_get_is_site_local (address));
149
0
      break;
150
151
0
    case PROP_IS_MULTICAST:
152
0
      g_value_set_boolean (value, g_inet_address_get_is_multicast (address));
153
0
      break;
154
155
0
    case PROP_IS_MC_GLOBAL:
156
0
      g_value_set_boolean (value, g_inet_address_get_is_mc_global (address));
157
0
      break;
158
159
0
    case PROP_IS_MC_LINK_LOCAL:
160
0
      g_value_set_boolean (value, g_inet_address_get_is_mc_link_local (address));
161
0
      break;
162
163
0
    case PROP_IS_MC_NODE_LOCAL:
164
0
      g_value_set_boolean (value, g_inet_address_get_is_mc_node_local (address));
165
0
      break;
166
167
0
    case PROP_IS_MC_ORG_LOCAL:
168
0
      g_value_set_boolean (value, g_inet_address_get_is_mc_org_local (address));
169
0
      break;
170
171
0
    case PROP_IS_MC_SITE_LOCAL:
172
0
      g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address));
173
0
      break;
174
175
0
    default:
176
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
177
0
    }
178
0
}
179
180
static void
181
g_inet_address_class_init (GInetAddressClass *klass)
182
3
{
183
3
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
184
185
3
  gobject_class->set_property = g_inet_address_set_property;
186
3
  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
3
  g_object_class_install_property (gobject_class, PROP_FAMILY,
196
3
                                   g_param_spec_enum ("family", NULL, NULL,
197
3
                  G_TYPE_SOCKET_FAMILY,
198
3
                  G_SOCKET_FAMILY_INVALID,
199
3
                  G_PARAM_READWRITE |
200
3
                                                      G_PARAM_CONSTRUCT_ONLY |
201
3
                                                      G_PARAM_STATIC_STRINGS));
202
203
  /**
204
   * GInetAddress:bytes:
205
   *
206
   * The raw address data.
207
   *
208
   * Since: 2.22
209
   */
210
3
  g_object_class_install_property (gobject_class, PROP_BYTES,
211
3
                                   g_param_spec_pointer ("bytes", NULL, NULL,
212
3
               G_PARAM_READWRITE |
213
3
                                                         G_PARAM_CONSTRUCT_ONLY |
214
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_ANY,
225
3
                                   g_param_spec_boolean ("is-any", NULL, NULL,
226
3
                                                         FALSE,
227
3
                                                         G_PARAM_READABLE |
228
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_LINK_LOCAL,
239
3
                                   g_param_spec_boolean ("is-link-local", NULL, NULL,
240
3
                                                         FALSE,
241
3
                                                         G_PARAM_READABLE |
242
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK,
253
3
                                   g_param_spec_boolean ("is-loopback", NULL, NULL,
254
3
                                                         FALSE,
255
3
                                                         G_PARAM_READABLE |
256
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_SITE_LOCAL,
267
3
                                   g_param_spec_boolean ("is-site-local", NULL, NULL,
268
3
                                                         FALSE,
269
3
                                                         G_PARAM_READABLE |
270
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_MULTICAST,
281
3
                                   g_param_spec_boolean ("is-multicast", NULL, NULL,
282
3
                                                         FALSE,
283
3
                                                         G_PARAM_READABLE |
284
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL,
295
3
                                   g_param_spec_boolean ("is-mc-global", NULL, NULL,
296
3
                                                         FALSE,
297
3
                                                         G_PARAM_READABLE |
298
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_MC_LINK_LOCAL,
310
3
                                   g_param_spec_boolean ("is-mc-link-local", NULL, NULL,
311
3
                                                         FALSE,
312
3
                                                         G_PARAM_READABLE |
313
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_MC_NODE_LOCAL,
324
3
                                   g_param_spec_boolean ("is-mc-node-local", NULL, NULL,
325
3
                                                         FALSE,
326
3
                                                         G_PARAM_READABLE |
327
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_MC_ORG_LOCAL,
338
3
                                   g_param_spec_boolean ("is-mc-org-local", NULL, NULL,
339
3
                                                         FALSE,
340
3
                                                         G_PARAM_READABLE |
341
3
                                                         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
3
  g_object_class_install_property (gobject_class, PROP_IS_MC_SITE_LOCAL,
352
3
                                   g_param_spec_boolean ("is-mc-site-local", NULL, NULL,
353
3
                                                         FALSE,
354
3
                                                         G_PARAM_READABLE |
355
3
                                                         G_PARAM_STATIC_STRINGS));
356
3
}
357
358
static void
359
g_inet_address_init (GInetAddress *address)
360
393
{
361
393
  address->priv = g_inet_address_get_instance_private (address);
362
393
}
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
g_inet_address_new_from_string (const gchar *string)
378
190
{
379
190
  struct in_addr in_addr;
380
190
#ifdef HAVE_IPV6
381
190
  struct in6_addr in6_addr;
382
190
#endif
383
384
190
  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
190
  g_networking_init ();
391
392
190
  if (inet_pton (AF_INET, string, &in_addr) > 0)
393
19
    return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
394
171
#ifdef HAVE_IPV6
395
171
  else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
396
136
    return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
397
35
#endif
398
399
35
  return NULL;
400
190
}
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
g_inet_address_new_from_bytes (const guint8         *bytes,
420
             GSocketFamily  family)
421
393
{
422
393
  g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
423
424
393
  return g_object_new (G_TYPE_INET_ADDRESS,
425
393
           "family", family,
426
393
           "bytes", bytes,
427
393
           NULL);
428
393
}
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
g_inet_address_new_loopback (GSocketFamily family)
444
0
{
445
0
  g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
446
447
0
  if (family == AF_INET)
448
0
    {    
449
0
      guint8 addr[4] = {127, 0, 0, 1};
450
451
0
      return g_inet_address_new_from_bytes (addr, family);
452
0
    }
453
0
  else
454
0
#ifdef HAVE_IPV6
455
0
    return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
456
#else
457
    g_assert_not_reached ();
458
#endif
459
0
}
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
g_inet_address_new_any (GSocketFamily family)
476
0
{
477
0
  g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
478
479
0
  if (family == AF_INET)
480
0
    {    
481
0
      guint8 addr[4] = {0, 0, 0, 0};
482
483
0
      return g_inet_address_new_from_bytes (addr, family);
484
0
    }
485
0
  else
486
0
#ifdef HAVE_IPV6
487
0
    return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
488
#else
489
    g_assert_not_reached ();
490
#endif
491
0
}
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
g_inet_address_to_string (GInetAddress *address)
507
365
{
508
365
  gchar buffer[INET6_ADDRSTRLEN];
509
510
365
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
511
512
365
  if (address->priv->family == AF_INET)
513
10
    {
514
10
      inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
515
10
      return g_strdup (buffer);
516
10
    }
517
355
  else
518
355
    {
519
355
#ifdef HAVE_IPV6
520
355
      inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
521
355
      return g_strdup (buffer);
522
#else
523
      g_assert_not_reached ();
524
#endif
525
355
    }
526
365
}
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
g_inet_address_to_bytes (GInetAddress *address)
542
132
{
543
132
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
544
545
132
  return (guint8 *)&address->priv->addr;
546
132
}
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
g_inet_address_get_native_size (GInetAddress *address)
561
259
{
562
259
  if (address->priv->family == AF_INET)
563
15
    return sizeof (address->priv->addr.ipv4);
564
244
#ifdef HAVE_IPV6
565
244
  return sizeof (address->priv->addr.ipv6);
566
#else
567
  g_assert_not_reached ();
568
#endif
569
259
}
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
g_inet_address_get_family (GInetAddress *address)
583
794
{
584
794
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
585
586
794
  return address->priv->family;
587
794
}
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
g_inet_address_get_is_any (GInetAddress *address)
601
0
{
602
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
603
604
0
  if (address->priv->family == AF_INET)
605
0
    {
606
0
      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
607
608
0
      return addr4 == INADDR_ANY;
609
0
    }
610
0
  else
611
0
#ifdef HAVE_IPV6
612
0
    return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6);
613
#else
614
    g_assert_not_reached ();
615
#endif
616
0
}
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
g_inet_address_get_is_loopback (GInetAddress *address)
630
0
{
631
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
632
633
0
  if (address->priv->family == AF_INET)
634
0
    {
635
0
      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
636
637
      /* 127.0.0.0/8 */
638
0
      return ((addr4 & 0xff000000) == 0x7f000000);
639
0
    }
640
0
  else
641
0
#ifdef HAVE_IPV6
642
0
    return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6);
643
#else
644
    g_assert_not_reached ();
645
#endif
646
0
}
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
g_inet_address_get_is_link_local (GInetAddress *address)
662
0
{
663
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
664
665
0
  if (address->priv->family == AF_INET)
666
0
    {
667
0
      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
668
669
      /* 169.254.0.0/16 */
670
0
      return ((addr4 & 0xffff0000) == 0xa9fe0000);
671
0
    }
672
0
  else
673
0
#ifdef HAVE_IPV6
674
0
    return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6);
675
#else
676
    g_assert_not_reached ();
677
#endif
678
0
}
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
g_inet_address_get_is_site_local (GInetAddress *address)
695
0
{
696
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
697
698
0
  if (address->priv->family == AF_INET)
699
0
    {
700
0
      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
0
      return ((addr4 & 0xff000000) == 0x0a000000 ||
704
0
        (addr4 & 0xfff00000) == 0xac100000 ||
705
0
        (addr4 & 0xffff0000) == 0xc0a80000);
706
0
    }
707
0
  else
708
0
#ifdef HAVE_IPV6
709
0
    return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6);
710
#else
711
    g_assert_not_reached ();
712
#endif
713
0
}
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
g_inet_address_get_is_multicast (GInetAddress *address)
727
0
{
728
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
729
730
0
  if (address->priv->family == AF_INET)
731
0
    {
732
0
      guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
733
734
0
      return IN_MULTICAST (addr4);
735
0
    }
736
0
  else
737
0
#ifdef HAVE_IPV6
738
0
    return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6);
739
#else
740
    g_assert_not_reached ();
741
#endif
742
0
}
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
g_inet_address_get_is_mc_global (GInetAddress *address)
756
0
{
757
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
758
759
0
  if (address->priv->family == AF_INET)
760
0
    return FALSE;
761
0
  else
762
0
#ifdef HAVE_IPV6
763
0
    return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6);
764
#else
765
    g_assert_not_reached ();
766
#endif
767
0
}
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
g_inet_address_get_is_mc_link_local (GInetAddress *address)
781
0
{
782
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
783
784
0
  if (address->priv->family == AF_INET)
785
0
    return FALSE;
786
0
  else
787
0
#ifdef HAVE_IPV6
788
0
    return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6);
789
#else
790
    g_assert_not_reached ();
791
#endif
792
0
}
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
g_inet_address_get_is_mc_node_local (GInetAddress *address)
806
0
{
807
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
808
809
0
  if (address->priv->family == AF_INET)
810
0
    return FALSE;
811
0
  else
812
0
#ifdef HAVE_IPV6
813
0
    return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6);
814
#else
815
    g_assert_not_reached ();
816
#endif
817
0
}
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
g_inet_address_get_is_mc_org_local  (GInetAddress *address)
831
0
{
832
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
833
834
0
  if (address->priv->family == AF_INET)
835
0
    return FALSE;
836
0
  else
837
0
#ifdef HAVE_IPV6
838
0
    return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6);
839
#else
840
    g_assert_not_reached ();
841
#endif
842
0
}
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
g_inet_address_get_is_mc_site_local (GInetAddress *address)
856
0
{
857
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
858
859
0
  if (address->priv->family == AF_INET)
860
0
    return FALSE;
861
0
  else
862
0
#ifdef HAVE_IPV6
863
0
    return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6);
864
#else
865
    g_assert_not_reached ();
866
#endif
867
0
}
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
g_inet_address_equal (GInetAddress *address,
882
                      GInetAddress *other_address)
883
0
{
884
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
885
0
  g_return_val_if_fail (G_IS_INET_ADDRESS (other_address), FALSE);
886
887
0
  if (g_inet_address_get_family (address) != g_inet_address_get_family (other_address))
888
0
    return FALSE;
889
890
0
  if (memcmp (g_inet_address_to_bytes (address),
891
0
              g_inet_address_to_bytes (other_address),
892
0
              g_inet_address_get_native_size (address)) != 0)
893
0
    return FALSE;
894
895
0
  return TRUE;
896
0
}