Coverage Report

Created: 2025-07-01 07:09

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