Coverage Report

Created: 2025-06-13 06:55

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