Add network address and socket types
[platform/upstream/glib.git] / gio / ginetaddress.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Christian Kellner <gicmo@gnome.org>
21  *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
22  */
23
24 #include <config.h>
25 #include <glib.h>
26
27 #include "ginetaddress.h"
28 #include "gioenums.h"
29 #include "gioenumtypes.h"
30 #include "glibintl.h"
31 #include "gnetworkingprivate.h"
32
33 #include "gioalias.h"
34
35 /**
36  * SECTION:ginetaddress
37  * @short_description: An IPv4/IPv6 address
38  *
39  * #GInetAddress represents an IPv4 or IPv6 internet address.
40  *
41  * To actually connect to a remote host, you will need a
42  * #GInetSocketAddress (which includes a #GInetAddress as well as a
43  * port number).
44  **/
45
46 /**
47  * GInetAddress:
48  *
49  * An IPv4 or IPv6 internet address.
50  **/
51
52 /* Networking initialization function, called from inside the g_once of
53  * g_inet_address_get_type()
54  */
55 static void
56 _g_networking_init (void)
57 {
58 #ifdef G_OS_WIN32
59   WSADATA wsadata;
60   if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0)
61     g_error ("Windows Sockets could not be initialized");
62 #endif
63 }
64
65 G_DEFINE_TYPE_WITH_CODE (GInetAddress, g_inet_address, G_TYPE_OBJECT,
66                          _g_networking_init ();)
67
68 struct _GInetAddressPrivate
69 {
70   GSocketFamily family;
71   union {
72     struct in_addr ipv4;
73     struct in6_addr ipv6;
74   } addr;
75 };
76
77 enum
78 {
79   PROP_0,
80   PROP_FAMILY,
81   PROP_BYTES,
82   PROP_IS_ANY,
83   PROP_IS_LOOPBACK,
84   PROP_IS_LINK_LOCAL,
85   PROP_IS_SITE_LOCAL,
86   PROP_IS_MULTICAST,
87   PROP_IS_MC_GLOBAL,
88   PROP_IS_MC_LINK_LOCAL,
89   PROP_IS_MC_NODE_LOCAL,
90   PROP_IS_MC_ORG_LOCAL,
91   PROP_IS_MC_SITE_LOCAL,
92 };
93
94 static void
95 g_inet_address_set_property (GObject      *object,
96                              guint         prop_id,
97                              const GValue *value,
98                              GParamSpec   *pspec)
99 {
100   GInetAddress *address = G_INET_ADDRESS (object);
101
102   switch (prop_id) 
103     {
104     case PROP_FAMILY:
105       address->priv->family = g_value_get_enum (value);
106       break;
107
108     case PROP_BYTES:
109       memcpy (&address->priv->addr, g_value_get_pointer (value),
110               address->priv->family == AF_INET ?
111               sizeof (address->priv->addr.ipv4) :
112               sizeof (address->priv->addr.ipv6));
113       break;
114
115     default:
116       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117       break;
118     }
119
120 }
121
122 static void
123 g_inet_address_get_property (GObject    *object,
124                              guint       prop_id,
125                              GValue     *value,
126                              GParamSpec *pspec)
127 {
128   GInetAddress *address = G_INET_ADDRESS (object);
129
130   switch (prop_id)
131     {
132     case PROP_FAMILY:
133       g_value_set_enum (value, address->priv->family);
134       break;
135
136     case PROP_BYTES:
137       g_value_set_pointer (value, &address->priv->addr);
138       break;
139
140     case PROP_IS_ANY:
141       g_value_set_boolean (value, g_inet_address_get_is_any (address));
142       break;
143
144     case PROP_IS_LOOPBACK:
145       g_value_set_boolean (value, g_inet_address_get_is_loopback (address));
146       break;
147
148     case PROP_IS_LINK_LOCAL:
149       g_value_set_boolean (value, g_inet_address_get_is_link_local (address));
150       break;
151
152     case PROP_IS_SITE_LOCAL:
153       g_value_set_boolean (value, g_inet_address_get_is_site_local (address));
154       break;
155
156     case PROP_IS_MULTICAST:
157       g_value_set_boolean (value, g_inet_address_get_is_multicast (address));
158       break;
159
160     case PROP_IS_MC_GLOBAL:
161       g_value_set_boolean (value, g_inet_address_get_is_mc_global (address));
162       break;
163
164     case PROP_IS_MC_LINK_LOCAL:
165       g_value_set_boolean (value, g_inet_address_get_is_mc_link_local (address));
166       break;
167
168     case PROP_IS_MC_NODE_LOCAL:
169       g_value_set_boolean (value, g_inet_address_get_is_mc_node_local (address));
170       break;
171
172     case PROP_IS_MC_ORG_LOCAL:
173       g_value_set_boolean (value, g_inet_address_get_is_mc_org_local (address));
174       break;
175
176     case PROP_IS_MC_SITE_LOCAL:
177       g_value_set_boolean (value, g_inet_address_get_is_mc_site_local (address));
178       break;
179
180     default:
181       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
182     }
183 }
184
185 static void
186 g_inet_address_class_init (GInetAddressClass *klass)
187 {
188   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
189
190   g_type_class_add_private (klass, sizeof (GInetAddressPrivate));
191
192   gobject_class->set_property = g_inet_address_set_property;
193   gobject_class->get_property = g_inet_address_get_property;
194
195   g_object_class_install_property (gobject_class, PROP_FAMILY,
196                                    g_param_spec_enum ("family",
197                                                       _("Address family"),
198                                                       _("The address family (IPv4 or IPv6)"),
199                                                       G_TYPE_SOCKET_FAMILY,
200                                                       G_SOCKET_FAMILY_INVALID,
201                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
202
203   g_object_class_install_property (gobject_class, PROP_BYTES,
204                                    g_param_spec_pointer ("bytes",
205                                                          _("Bytes"),
206                                                          _("The raw address data"),
207                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
208
209   g_object_class_install_property (gobject_class, PROP_IS_ANY,
210                                    g_param_spec_boolean ("is-any",
211                                                          _("Is any"),
212                                                          _("See g_inet_address_get_is_any()"),
213                                                          FALSE,
214                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
215
216   g_object_class_install_property (gobject_class, PROP_IS_LINK_LOCAL,
217                                    g_param_spec_boolean ("is-link-local",
218                                                          _("Is link-local"),
219                                                          _("See g_inet_address_get_is_link_local()"),
220                                                          FALSE,
221                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
222
223   g_object_class_install_property (gobject_class, PROP_IS_LOOPBACK,
224                                    g_param_spec_boolean ("is-loopback",
225                                                          _("Is loopback"),
226                                                          _("See g_inet_address_get_is_loopback()"),
227                                                          FALSE,
228                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
229
230   g_object_class_install_property (gobject_class, PROP_IS_SITE_LOCAL,
231                                    g_param_spec_boolean ("is-site-local",
232                                                          _("Is site-local"),
233                                                          _("See g_inet_address_get_is_site_local()"),
234                                                          FALSE,
235                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
236
237   g_object_class_install_property (gobject_class, PROP_IS_MULTICAST,
238                                    g_param_spec_boolean ("is-multicast",
239                                                          _("Is multicast"),
240                                                          _("See g_inet_address_get_is_multicast()"),
241                                                          FALSE,
242                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
243
244   g_object_class_install_property (gobject_class, PROP_IS_MC_GLOBAL,
245                                    g_param_spec_boolean ("is-mc-global",
246                                                          _("Is multicast global"),
247                                                          _("See g_inet_address_get_is_mc_global()"),
248                                                          FALSE,
249                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
250
251   g_object_class_install_property (gobject_class, PROP_IS_MC_LINK_LOCAL,
252                                    g_param_spec_boolean ("is-mc-link-local",
253                                                          _("Is multicast link-local"),
254                                                          _("See g_inet_address_get_is_mc_link_local()"),
255                                                          FALSE,
256                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
257
258   g_object_class_install_property (gobject_class, PROP_IS_MC_NODE_LOCAL,
259                                    g_param_spec_boolean ("is-mc-node-local",
260                                                          _("Is multicast node-local"),
261                                                          _("See g_inet_address_get_is_mc_node_local()"),
262                                                          FALSE,
263                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
264
265   g_object_class_install_property (gobject_class, PROP_IS_MC_ORG_LOCAL,
266                                    g_param_spec_boolean ("is-mc-org-local",
267                                                          _("Is multicast org-local"),
268                                                          _("See g_inet_address_get_is_mc_org_local()"),
269                                                          FALSE,
270                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
271
272   g_object_class_install_property (gobject_class, PROP_IS_MC_SITE_LOCAL,
273                                    g_param_spec_boolean ("is-mc-site-local",
274                                                          _("Is multicast site-local"),
275                                                          _("See g_inet_address_get_is_mc_site_local()"),
276                                                          FALSE,
277                                                          G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME));
278 }
279
280 static void
281 g_inet_address_init (GInetAddress *address)
282 {
283   address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
284                                                G_TYPE_INET_ADDRESS,
285                                                GInetAddressPrivate);
286 }
287
288 /**
289  * g_inet_address_new_from_string:
290  * @string: a string representation of an IP address
291  *
292  * Parses @string as an IP address and creates a new #GInetAddress.
293  *
294  * Returns: a new #GInetAddress corresponding to @string, or %NULL if
295  * @string could not be parsed.
296  *
297  * Since: 2.22
298  */
299 GInetAddress *
300 g_inet_address_new_from_string (const gchar *string)
301 {
302 #ifdef G_OS_WIN32
303   struct sockaddr_storage sa;
304   struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
305   struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
306   gint len;
307 #else /* !G_OS_WIN32 */
308   struct in_addr in_addr;
309   struct in6_addr in6_addr;
310 #endif
311
312   /* Make sure _g_networking_init() has been called */
313   (void) g_inet_address_get_type ();
314
315 #ifdef G_OS_WIN32
316   memset (&sa, 0, sizeof (sa));
317   len = sizeof (sa);
318   if (WSAStringToAddress ((LPTSTR) string, AF_INET, NULL, (LPSOCKADDR) &sa, &len) == 0)
319     return g_inet_address_new_from_bytes ((guint8 *)&sin->sin_addr, AF_INET);
320   else if (WSAStringToAddress ((LPTSTR) string, AF_INET6, NULL, (LPSOCKADDR) &sa, &len) == 0)
321     return g_inet_address_new_from_bytes ((guint8 *)&sin6->sin6_addr, AF_INET6);
322
323 #else /* !G_OS_WIN32 */
324
325   if (inet_pton (AF_INET, string, &in_addr) > 0)
326     return g_inet_address_new_from_bytes ((guint8 *)&in_addr, AF_INET);
327   else if (inet_pton (AF_INET6, string, &in6_addr) > 0)
328     return g_inet_address_new_from_bytes ((guint8 *)&in6_addr, AF_INET6);
329 #endif
330
331   return NULL;
332 }
333
334 #define G_INET_ADDRESS_FAMILY_IS_VALID(family) ((family) == AF_INET || (family) == AF_INET6)
335
336 /**
337  * g_inet_address_new_from_bytes:
338  * @bytes: raw address data
339  * @family: the address family of @bytes
340  *
341  * Creates a new #GInetAddress from the given @family and @bytes.
342  * @bytes should be 4 bytes for %G_INET_ADDRESS_IPV4 and 16 bytes for
343  * %G_INET_ADDRESS_IPV6.
344  *
345  * Returns: a new #GInetAddress corresponding to @family and @bytes.
346  *
347  * Since: 2.22
348  */
349 GInetAddress *
350 g_inet_address_new_from_bytes (const guint8         *bytes,
351                                GSocketFamily  family)
352 {
353   g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
354
355   return g_object_new (G_TYPE_INET_ADDRESS,
356                        "family", family,
357                        "bytes", bytes,
358                        NULL);
359 }
360
361 /**
362  * g_inet_address_new_loopback:
363  * @family: the address family
364  *
365  * Creates a #GInetAddress for the loopback address for @family.
366  *
367  * Returns: a new #GInetAddress corresponding to the loopback address
368  * for @family.
369  *
370  * Since: 2.22
371  */
372 GInetAddress *
373 g_inet_address_new_loopback (GSocketFamily family)
374 {
375   g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
376
377   if (family == AF_INET)
378     {    
379       guint8 addr[4] = {127, 0, 0, 1};
380
381       return g_inet_address_new_from_bytes (addr, family);
382     }
383   else
384     return g_inet_address_new_from_bytes (in6addr_loopback.s6_addr, family);
385 }
386
387 /**
388  * g_inet_address_new_any:
389  * @family: the address family
390  *
391  * Creates a #GInetAddress for the "any" address (unassigned/"don't
392  * care") for @family.
393  *
394  * Returns: a new #GInetAddress corresponding to the "any" address
395  * for @family.
396  *
397  * Since: 2.22
398  */
399 GInetAddress *
400 g_inet_address_new_any (GSocketFamily family)
401 {
402   g_return_val_if_fail (G_INET_ADDRESS_FAMILY_IS_VALID (family), NULL);
403
404   if (family == AF_INET)
405     {    
406       guint8 addr[4] = {0, 0, 0, 0};
407
408       return g_inet_address_new_from_bytes (addr, family);
409     }
410   else
411     return g_inet_address_new_from_bytes (in6addr_any.s6_addr, family);
412 }
413
414
415 /**
416  * g_inet_address_to_string:
417  * @address: a #GInetAddress
418  *
419  * Converts @address to string form.
420  *
421  * Returns: a representation of @address as a string, which should be
422  * freed after use.
423  *
424  * Since: 2.22
425  */
426 gchar *
427 g_inet_address_to_string (GInetAddress *address)
428 {
429   gchar buffer[INET6_ADDRSTRLEN];
430 #ifdef G_OS_WIN32
431   DWORD buflen = sizeof (buffer), addrlen;
432   struct sockaddr_storage sa;
433   struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
434   struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
435 #endif
436
437   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
438
439 #ifdef G_OS_WIN32
440   sa.ss_family = address->priv->family;
441   if (address->priv->family == AF_INET)
442     {
443       addrlen = sizeof (*sin);
444       memcpy (&sin->sin_addr, &address->priv->addr.ipv4,
445               sizeof (sin->sin_addr));
446       sin->sin_port = 0;
447     }
448   else
449     {
450       addrlen = sizeof (*sin6);
451       memcpy (&sin6->sin6_addr, &address->priv->addr.ipv6,
452               sizeof (sin6->sin6_addr));
453       sin6->sin6_port = 0;
454     }
455   if (WSAAddressToString ((LPSOCKADDR) &sa, addrlen, NULL, buffer, &buflen) != 0)
456     return NULL;
457
458 #else /* !G_OS_WIN32 */
459
460   if (address->priv->family == AF_INET)
461     inet_ntop (AF_INET, &address->priv->addr.ipv4, buffer, sizeof (buffer));
462   else
463     inet_ntop (AF_INET6, &address->priv->addr.ipv6, buffer, sizeof (buffer));
464 #endif
465
466   return g_strdup (buffer);
467 }
468
469 /**
470  * g_inet_address_to_bytes:
471  * @address: a #GInetAddress
472  *
473  * Gets the raw binary address data from @address.
474  *
475  * Returns: a pointer to an internal array of the bytes in @address,
476  * which should not be modified, stored, or freed.
477  *
478  * Since: 2.22
479  */
480 const guint8 *
481 g_inet_address_to_bytes (GInetAddress *address)
482 {
483   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
484
485   return (guint8 *)&address->priv->addr;
486 }
487
488 /**
489  * g_inet_address_get_family:
490  * @address: a #GInetAddress
491  *
492  * Gets @address's family
493  *
494  * Returns: @address's family
495  *
496  * Since: 2.22
497  */
498 GSocketFamily
499 g_inet_address_get_family (GInetAddress *address)
500 {
501   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
502
503   return address->priv->family;
504 }
505
506 /**
507  * g_inet_address_get_is_any:
508  * @address: a #GInetAddress
509  *
510  * Tests whether @address is the "any" address for its family.
511  *
512  * Returns: %TRUE if @address is the "any" address for its family.
513  *
514  * Since: 2.22
515  */
516 gboolean
517 g_inet_address_get_is_any (GInetAddress *address)
518 {
519   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
520
521   if (address->priv->family == AF_INET)
522     {
523       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
524
525       return addr4 == INADDR_ANY;
526     }
527   else
528     return IN6_IS_ADDR_UNSPECIFIED (&address->priv->addr.ipv6.s6_addr);
529 }
530
531 /**
532  * g_inet_address_get_is_loopback:
533  * @address: a #GInetAddress
534  *
535  * Tests whether @address is the loopback address for its family.
536  *
537  * Returns: %TRUE if @address is the loopback address for its family.
538  *
539  * Since: 2.22
540  */
541 gboolean
542 g_inet_address_get_is_loopback (GInetAddress *address)
543 {
544   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
545
546   if (address->priv->family == AF_INET)
547     {
548       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
549
550       /* 127.0.0.0/8 */
551       return ((addr4 & 0xff000000) == 0x7f000000);
552     }
553   else
554     return IN6_IS_ADDR_LOOPBACK (&address->priv->addr.ipv6.s6_addr);
555 }
556
557 /**
558  * g_inet_address_get_is_link_local:
559  * @address: a #GInetAddress
560  *
561  * Tests whether @address is a link-local address (that is, if it
562  * identifies a host on a local network that is not connected to the
563  * Internet).
564  *
565  * Returns: %TRUE if @address is a link-local address.
566  *
567  * Since: 2.22
568  */
569 gboolean
570 g_inet_address_get_is_link_local (GInetAddress *address)
571 {
572   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
573
574   if (address->priv->family == AF_INET)
575     {
576       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
577
578       /* 169.254.0.0/16 */
579       return ((addr4 & 0xffff0000) == 0xa9fe0000);
580     }
581   else
582     return IN6_IS_ADDR_LINKLOCAL (&address->priv->addr.ipv6.s6_addr);
583 }
584
585 /**
586  * g_inet_address_get_is_site_local:
587  * @address: a #GInetAddress
588  *
589  * Tests whether @address is a site-local address such as 10.0.0.1
590  * (that is, the address identifies a host on a local network that can
591  * not be reached directly from the Internet, but which may have
592  * outgoing Internet connectivity via a NAT or firewall).
593  *
594  * Returns: %TRUE if @address is a site-local address.
595  *
596  * Since: 2.22
597  */
598 gboolean
599 g_inet_address_get_is_site_local (GInetAddress *address)
600 {
601   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
602
603   if (address->priv->family == AF_INET)
604     {
605       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
606
607       /* 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
608       return ((addr4 & 0xff000000) == 0x0a000000 ||
609               (addr4 & 0xfff00000) == 0xac100000 ||
610               (addr4 & 0xffff0000) == 0xc0a80000);
611     }
612   else
613     return IN6_IS_ADDR_SITELOCAL (&address->priv->addr.ipv6.s6_addr);
614 }
615
616 /**
617  * g_inet_address_get_is_multicast:
618  * @address: a #GInetAddress
619  *
620  * Tests whether @address is a multicast address.
621  *
622  * Returns: %TRUE if @address is a multicast address.
623  *
624  * Since: 2.22
625  */
626 gboolean
627 g_inet_address_get_is_multicast (GInetAddress *address)
628 {
629   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
630
631   if (address->priv->family == AF_INET)
632     {
633       guint32 addr4 = g_ntohl (address->priv->addr.ipv4.s_addr);
634
635       return IN_MULTICAST (addr4);
636     }
637   else
638     return IN6_IS_ADDR_MULTICAST (&address->priv->addr.ipv6.s6_addr);
639 }
640
641 /**
642  * g_inet_address_get_is_mc_global:
643  * @address: a #GInetAddress
644  *
645  * Tests whether @address is a global multicast address.
646  *
647  * Returns: %TRUE if @address is a global multicast address.
648  *
649  * Since: 2.22
650  */
651 gboolean
652 g_inet_address_get_is_mc_global (GInetAddress *address)
653 {
654   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
655
656   if (address->priv->family == AF_INET)
657     return FALSE;
658   else
659     return IN6_IS_ADDR_MC_GLOBAL (&address->priv->addr.ipv6.s6_addr);
660 }
661
662 /**
663  * g_inet_address_get_is_mc_link_local:
664  * @address: a #GInetAddress
665  *
666  * Tests whether @address is a link-local multicast address.
667  *
668  * Returns: %TRUE if @address is a link-local multicast address.
669  *
670  * Since: 2.22
671  */
672 gboolean
673 g_inet_address_get_is_mc_link_local (GInetAddress *address)
674 {
675   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
676
677   if (address->priv->family == AF_INET)
678     return FALSE;
679   else
680     return IN6_IS_ADDR_MC_LINKLOCAL (&address->priv->addr.ipv6.s6_addr);
681 }
682
683 /**
684  * g_inet_address_get_is_mc_node_local:
685  * @address: a #GInetAddress
686  *
687  * Tests whether @address is a node-local multicast address.
688  *
689  * Returns: %TRUE if @address is a node-local multicast address.
690  *
691  * Since: 2.22
692  */
693 gboolean
694 g_inet_address_get_is_mc_node_local (GInetAddress *address)
695 {
696   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
697
698   if (address->priv->family == AF_INET)
699     return FALSE;
700   else
701     return IN6_IS_ADDR_MC_NODELOCAL (&address->priv->addr.ipv6.s6_addr);
702 }
703
704 /**
705  * g_inet_address_get_is_mc_org_local:
706  * @address: a #GInetAddress
707  *
708  * Tests whether @address is an organization-local multicast address.
709  *
710  * Returns: %TRUE if @address is an organization-local multicast address.
711  *
712  * Since: 2.22
713  */
714 gboolean
715 g_inet_address_get_is_mc_org_local  (GInetAddress *address)
716 {
717   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
718
719   if (address->priv->family == AF_INET)
720     return FALSE;
721   else
722     return IN6_IS_ADDR_MC_ORGLOCAL (&address->priv->addr.ipv6.s6_addr);
723 }
724
725 /**
726  * g_inet_address_get_is_mc_site_local:
727  * @address: a #GInetAddress
728  *
729  * Tests whether @address is a site-local multicast address.
730  *
731  * Returns: %TRUE if @address is a site-local multicast address.
732  *
733  * Since: 2.22
734  */
735 gboolean
736 g_inet_address_get_is_mc_site_local (GInetAddress *address)
737 {
738   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
739
740   if (address->priv->family == AF_INET)
741     return FALSE;
742   else
743     return IN6_IS_ADDR_MC_SITELOCAL (&address->priv->addr.ipv6.s6_addr);
744 }
745
746 #define __G_INET_ADDRESS_C__
747 #include "gioaliasdef.c"