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