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