spec: Remove kdbus-extension packages for _with_da_profile
[platform/upstream/glib.git] / gio / ginetaddressmask.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright 2011 Red Hat, Inc.
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
21 #include <config.h>
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "ginetaddressmask.h"
27 #include "ginetaddress.h"
28 #include "ginitable.h"
29 #include "gioerror.h"
30 #include "gioenumtypes.h"
31 #include "glibintl.h"
32
33 /**
34  * GInetAddressMask:
35  *
36  * `GInetAddressMask` represents a range of IPv4 or IPv6 addresses
37  * described by a base address and a length indicating how many bits
38  * of the base address are relevant for matching purposes. These are
39  * often given in string form. For example, `10.0.0.0/8`, or `fe80::/10`.
40  *
41  * Since: 2.32
42  */
43
44 struct _GInetAddressMaskPrivate
45 {
46   GInetAddress *addr;
47   guint         length;
48 };
49
50 static void     g_inet_address_mask_initable_iface_init (GInitableIface  *iface);
51
52 G_DEFINE_TYPE_WITH_CODE (GInetAddressMask, g_inet_address_mask, G_TYPE_OBJECT,
53                          G_ADD_PRIVATE (GInetAddressMask)
54                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
55                                                 g_inet_address_mask_initable_iface_init))
56
57 enum
58 {
59   PROP_0,
60   PROP_FAMILY,
61   PROP_ADDRESS,
62   PROP_LENGTH
63 };
64
65 static void
66 g_inet_address_mask_set_property (GObject      *object,
67                                   guint         prop_id,
68                                   const GValue *value,
69                                   GParamSpec   *pspec)
70 {
71   GInetAddressMask *mask = G_INET_ADDRESS_MASK (object);
72
73   switch (prop_id)
74     {
75     case PROP_ADDRESS:
76       if (mask->priv->addr)
77         g_object_unref (mask->priv->addr);
78       mask->priv->addr = g_value_dup_object (value);
79       break;
80
81     case PROP_LENGTH:
82       mask->priv->length = g_value_get_uint (value);
83       break;
84
85     default:
86       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
87       break;
88     }
89
90 }
91
92 static void
93 g_inet_address_mask_get_property (GObject    *object,
94                                   guint       prop_id,
95                                   GValue     *value,
96                                   GParamSpec *pspec)
97 {
98   GInetAddressMask *mask = G_INET_ADDRESS_MASK (object);
99
100   switch (prop_id)
101     {
102     case PROP_FAMILY:
103       g_value_set_enum (value, g_inet_address_get_family (mask->priv->addr));
104       break;
105
106     case PROP_ADDRESS:
107       g_value_set_object (value, mask->priv->addr);
108       break;
109
110     case PROP_LENGTH:
111       g_value_set_uint (value, mask->priv->length);
112       break;
113
114     default:
115       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
116     }
117 }
118
119 static void
120 g_inet_address_mask_dispose (GObject *object)
121 {
122   GInetAddressMask *mask = G_INET_ADDRESS_MASK (object);
123
124   g_clear_object (&mask->priv->addr);
125
126   G_OBJECT_CLASS (g_inet_address_mask_parent_class)->dispose (object);
127 }
128
129 static void
130 g_inet_address_mask_class_init (GInetAddressMaskClass *klass)
131 {
132   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
133
134   gobject_class->set_property = g_inet_address_mask_set_property;
135   gobject_class->get_property = g_inet_address_mask_get_property;
136   gobject_class->dispose = g_inet_address_mask_dispose;
137
138   /**
139    * GInetAddressMask:family:
140    *
141    * The address family (IPv4 or IPv6).
142    *
143    * Since: 2.32
144    */
145   g_object_class_install_property (gobject_class, PROP_FAMILY,
146                                    g_param_spec_enum ("family", NULL, NULL,
147                                                       G_TYPE_SOCKET_FAMILY,
148                                                       G_SOCKET_FAMILY_INVALID,
149                                                       G_PARAM_READABLE |
150                                                       G_PARAM_STATIC_STRINGS));
151
152   /**
153    * GInetAddressMask:address:
154    *
155    * The base address.
156    *
157    * Since: 2.32
158    */
159   g_object_class_install_property (gobject_class, PROP_ADDRESS,
160                                    g_param_spec_object ("address", NULL, NULL,
161                                                         G_TYPE_INET_ADDRESS,
162                                                         G_PARAM_READWRITE |
163                                                         G_PARAM_STATIC_STRINGS));
164
165   /**
166    * GInetAddressMask:length:
167    *
168    * The prefix length, in bytes.
169    *
170    * Since: 2.32
171    */
172   g_object_class_install_property (gobject_class, PROP_LENGTH,
173                                    g_param_spec_uint ("length", NULL, NULL,
174                                                       0, 128, 0,
175                                                       G_PARAM_READWRITE |
176                                                       G_PARAM_STATIC_STRINGS));
177 }
178
179 static gboolean
180 g_inet_address_mask_initable_init (GInitable     *initable,
181                                    GCancellable  *cancellable,
182                                    GError       **error)
183 {
184   GInetAddressMask *mask = G_INET_ADDRESS_MASK (initable);
185   guint addrlen, nbytes, nbits;
186   const guint8 *bytes;
187   gboolean ok;
188
189   if (!mask->priv->addr)
190     {
191       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
192                            _("No address specified"));
193       return FALSE;
194     }
195
196   addrlen = g_inet_address_get_native_size (mask->priv->addr);
197   if (mask->priv->length > addrlen * 8)
198     {
199       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
200                    _("Length %u is too long for address"),
201                    mask->priv->length);
202       return FALSE;
203     }
204
205   /* Make sure all the bits after @length are 0 */
206   bytes = g_inet_address_to_bytes (mask->priv->addr);
207   ok = TRUE;
208
209   nbytes = mask->priv->length / 8;
210   bytes += nbytes;
211   addrlen -= nbytes;
212
213   nbits = mask->priv->length % 8;
214   if (nbits)
215     {
216       if (bytes[0] & (0xFF >> nbits))
217         ok = FALSE;
218       bytes++;
219       addrlen--;
220     }
221
222   while (addrlen)
223     {
224       if (bytes[0])
225         ok = FALSE;
226       bytes++;
227       addrlen--;
228     }
229
230   if (!ok)
231     {
232       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
233                            _("Address has bits set beyond prefix length"));
234       return FALSE;
235     }
236
237   return TRUE;
238 }
239
240 static void
241 g_inet_address_mask_initable_iface_init (GInitableIface  *iface)
242 {
243   iface->init = g_inet_address_mask_initable_init;
244 }
245
246 static void
247 g_inet_address_mask_init (GInetAddressMask *mask)
248 {
249   mask->priv = g_inet_address_mask_get_instance_private (mask);
250 }
251
252 /**
253  * g_inet_address_mask_new:
254  * @addr: a #GInetAddress
255  * @length: number of bits of @addr to use
256  * @error: return location for #GError, or %NULL
257  *
258  * Creates a new #GInetAddressMask representing all addresses whose
259  * first @length bits match @addr.
260  *
261  * Returns: a new #GInetAddressMask, or %NULL on error
262  *
263  * Since: 2.32
264  */
265 GInetAddressMask *
266 g_inet_address_mask_new (GInetAddress  *addr,
267                          guint          length,
268                          GError       **error)
269 {
270   return g_initable_new (G_TYPE_INET_ADDRESS_MASK, NULL, error,
271                          "address", addr,
272                          "length", length,
273                          NULL);
274 }
275
276 /**
277  * g_inet_address_mask_new_from_string:
278  * @mask_string: an IP address or address/length string
279  * @error: return location for #GError, or %NULL
280  *
281  * Parses @mask_string as an IP address and (optional) length, and
282  * creates a new #GInetAddressMask. The length, if present, is
283  * delimited by a "/". If it is not present, then the length is
284  * assumed to be the full length of the address.
285  *
286  * Returns: a new #GInetAddressMask corresponding to @string, or %NULL
287  * on error.
288  *
289  * Since: 2.32
290  */
291 GInetAddressMask *
292 g_inet_address_mask_new_from_string (const gchar  *mask_string,
293                                      GError      **error)
294 {
295   GInetAddressMask *mask;
296   GInetAddress *addr;
297   gchar *slash;
298   guint length;
299
300   slash = strchr (mask_string, '/');
301   if (slash)
302     {
303       gchar *address, *end;
304
305       length = strtoul (slash + 1, &end, 10);
306       if (*end || !*(slash + 1))
307         {
308         parse_error:
309           g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
310                        _("Could not parse ā€œ%sā€ as IP address mask"),
311                        mask_string);
312           return NULL;
313         }
314
315       address = g_strndup (mask_string, slash - mask_string);
316       addr = g_inet_address_new_from_string (address);
317       g_free (address);
318
319       if (!addr)
320         goto parse_error;
321     }
322   else
323     {
324       addr = g_inet_address_new_from_string (mask_string);
325       if (!addr)
326         goto parse_error;
327
328       length = g_inet_address_get_native_size (addr) * 8;
329     }
330
331   mask = g_inet_address_mask_new (addr, length, error);
332   g_object_unref (addr);
333
334   return mask;
335 }
336
337 /**
338  * g_inet_address_mask_to_string:
339  * @mask: a #GInetAddressMask
340  *
341  * Converts @mask back to its corresponding string form.
342  *
343  * Returns: a string corresponding to @mask.
344  *
345  * Since: 2.32
346  */
347 gchar *
348 g_inet_address_mask_to_string (GInetAddressMask *mask)
349 {
350   gchar *addr_string, *mask_string;
351
352   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask), NULL);
353
354   addr_string = g_inet_address_to_string (mask->priv->addr);
355
356   if (mask->priv->length == (g_inet_address_get_native_size (mask->priv->addr) * 8))
357     return addr_string;
358
359   mask_string = g_strdup_printf ("%s/%u", addr_string, mask->priv->length);
360   g_free (addr_string);
361
362   return mask_string;
363 }
364
365 /**
366  * g_inet_address_mask_get_family:
367  * @mask: a #GInetAddressMask
368  *
369  * Gets the #GSocketFamily of @mask's address
370  *
371  * Returns: the #GSocketFamily of @mask's address
372  *
373  * Since: 2.32
374  */
375 GSocketFamily
376 g_inet_address_mask_get_family (GInetAddressMask *mask)
377 {
378   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask), G_SOCKET_FAMILY_INVALID);
379
380   return g_inet_address_get_family (mask->priv->addr);
381 }
382
383 /**
384  * g_inet_address_mask_get_address:
385  * @mask: a #GInetAddressMask
386  *
387  * Gets @mask's base address
388  *
389  * Returns: (transfer none): @mask's base address
390  *
391  * Since: 2.32
392  */
393 GInetAddress *
394 g_inet_address_mask_get_address (GInetAddressMask *mask)
395 {
396   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask), NULL);
397
398   return mask->priv->addr;
399 }
400
401 /**
402  * g_inet_address_mask_get_length:
403  * @mask: a #GInetAddressMask
404  *
405  * Gets @mask's length
406  *
407  * Returns: @mask's length
408  *
409  * Since: 2.32
410  */
411 guint
412 g_inet_address_mask_get_length (GInetAddressMask *mask)
413 {
414   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask), 0);
415
416   return mask->priv->length;
417 }
418
419 /**
420  * g_inet_address_mask_matches:
421  * @mask: a #GInetAddressMask
422  * @address: a #GInetAddress
423  *
424  * Tests if @address falls within the range described by @mask.
425  *
426  * Returns: whether @address falls within the range described by
427  * @mask.
428  *
429  * Since: 2.32
430  */
431 gboolean
432 g_inet_address_mask_matches (GInetAddressMask *mask,
433                              GInetAddress     *address)
434 {
435   const guint8 *maskbytes, *addrbytes;
436   int nbytes, nbits;
437
438   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask), FALSE);
439   g_return_val_if_fail (G_IS_INET_ADDRESS (address), FALSE);
440
441   if (g_inet_address_get_family (mask->priv->addr) !=
442       g_inet_address_get_family (address))
443     return FALSE;
444
445   if (mask->priv->length == 0)
446     return TRUE;
447
448   maskbytes = g_inet_address_to_bytes (mask->priv->addr);
449   addrbytes = g_inet_address_to_bytes (address);
450
451   nbytes = mask->priv->length / 8;
452   if (nbytes != 0 && memcmp (maskbytes, addrbytes, nbytes) != 0)
453     return FALSE;
454
455   nbits = mask->priv->length % 8;
456   if (nbits == 0)
457     return TRUE;
458
459   return maskbytes[nbytes] == (addrbytes[nbytes] & (0xFF << (8 - nbits)));
460 }
461
462
463 /**
464  * g_inet_address_mask_equal:
465  * @mask: a #GInetAddressMask
466  * @mask2: another #GInetAddressMask
467  *
468  * Tests if @mask and @mask2 are the same mask.
469  *
470  * Returns: whether @mask and @mask2 are the same mask
471  *
472  * Since: 2.32
473  */
474 gboolean
475 g_inet_address_mask_equal (GInetAddressMask  *mask,
476                            GInetAddressMask  *mask2)
477 {
478   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask), FALSE);
479   g_return_val_if_fail (G_IS_INET_ADDRESS_MASK (mask2), FALSE);
480
481   return ((mask->priv->length == mask2->priv->length) &&
482           g_inet_address_equal (mask->priv->addr, mask2->priv->addr));
483 }