device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-util / nm-value-transforms.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
3 /*
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301 USA.
18  *
19  * Copyright 2005 - 2014 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include <string.h>
25
26 #include "nm-gvaluearray-compat.h"
27 #include "nm-utils.h"
28 #include "nm-utils-private.h"
29 #include "nm-dbus-glib-types.h"
30
31 static void
32 _nm_utils_convert_op_to_string (const GValue *src_value, GValue *dest_value)
33 {
34         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_OBJECT_PATH));
35
36         g_value_set_string (dest_value, (const char *) g_value_get_boxed (src_value));
37 }
38
39 static void
40 _nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value)
41 {
42         char **str;
43         GSList *list = NULL;
44         guint i = 0;
45
46         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
47
48         str = (char **) g_value_get_boxed (src_value);
49
50         while (str && str[i])
51                 list = g_slist_prepend (list, g_strdup (str[i++]));
52
53         g_value_take_boxed (dest_value, g_slist_reverse (list));
54 }
55
56 static void
57 _nm_utils_convert_slist_to_strv (const GValue *src_value, GValue *dest_value)
58 {
59         GSList *slist;
60         char **strv;
61         int len, i = 0;
62
63         slist = g_value_get_boxed (src_value);
64         len = g_slist_length (slist);
65
66         strv = g_new (char *, len + 1);
67         for (i = 0; slist; slist = slist->next, i++)
68                 strv[i] = g_strdup (slist->data);
69         strv[i] = NULL;
70
71         g_value_take_boxed (dest_value, strv);
72 }
73
74 static void
75 _nm_utils_convert_strv_to_ptrarray (const GValue *src_value, GValue *dest_value)
76 {
77         char **str;
78         GPtrArray *array = NULL;
79         guint i = 0;
80
81         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
82
83         str = (char **) g_value_get_boxed (src_value);
84
85         array = g_ptr_array_sized_new (3);
86         while (str && str[i])
87                 g_ptr_array_add (array, g_strdup (str[i++]));
88
89         g_value_take_boxed (dest_value, array);
90 }
91
92 static void
93 _nm_utils_convert_string_list_to_string (const GValue *src_value, GValue *dest_value)
94 {
95         GSList *strings;
96         GString *printable;
97         GSList *iter;
98
99         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_LIST_OF_STRING));
100
101         strings = (GSList *) g_value_get_boxed (src_value);
102
103         printable = g_string_new (NULL);
104         for (iter = strings; iter; iter = iter->next) {
105                 if (iter != strings)
106                         g_string_append_c (printable, ',');
107                 g_string_append (printable, iter->data ? iter->data : "(null)");
108         }
109
110         g_value_take_string (dest_value, g_string_free (printable, FALSE));
111 }
112
113 static void
114 _string_array_to_string (const GPtrArray *strings, GValue *dest_value)
115 {
116         GString *printable;
117         guint i;
118
119         printable = g_string_new (NULL);
120         for (i = 0; strings && i < strings->len; i++) {
121                 if (i > 0)
122                         g_string_append_c (printable, ',');
123                 g_string_append (printable, strings->pdata[i]);
124         }
125
126         g_value_take_string (dest_value, g_string_free (printable, FALSE));
127 }
128
129 static void
130 _nm_utils_convert_string_array_to_string (const GValue *src_value, GValue *dest_value)
131 {
132         const GPtrArray *strings;
133
134         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_STRING));
135
136         strings = (const GPtrArray *) g_value_get_boxed (src_value);
137         _string_array_to_string (strings, dest_value);
138 }
139
140 static void
141 _nm_utils_convert_op_array_to_string (const GValue *src_value, GValue *dest_value)
142 {
143         const GPtrArray *strings;
144
145         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH));
146
147         strings = (const GPtrArray *) g_value_get_boxed (src_value);
148         _string_array_to_string (strings, dest_value);
149 }
150
151 static void
152 _nm_utils_convert_uint_array_to_string (const GValue *src_value, GValue *dest_value)
153 {
154         GArray *array;
155         GString *printable;
156         guint i = 0;
157
158         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UINT_ARRAY));
159
160         array = (GArray *) g_value_get_boxed (src_value);
161
162         printable = g_string_new (NULL);
163         while (array && (i < array->len)) {
164                 guint32 addr;
165
166                 if (i > 0)
167                         g_string_append (printable, ", ");
168
169                 addr = g_array_index (array, guint32, i++);
170                 g_string_append (printable, nm_utils_inet4_ntop (addr, NULL));
171         }
172
173         g_value_take_string (dest_value, g_string_free (printable, FALSE));
174 }
175
176 static void
177 _nm_utils_convert_ip4_addr_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
178 {
179         GPtrArray *ptr_array;
180         GString *printable;
181         guint i = 0;
182         char buf[INET_ADDRSTRLEN];
183
184         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
185
186         ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
187
188         printable = g_string_new (NULL);
189         while (ptr_array && (i < ptr_array->len)) {
190                 GArray *array;
191                 gboolean is_addr; /* array contains address x route */
192
193                 if (i > 0)
194                         g_string_append (printable, "; ");
195
196                 g_string_append (printable, "{ ");
197                 array = (GArray *) g_ptr_array_index (ptr_array, i++);
198                 if (array->len < 2) {
199                         g_string_append (printable, "invalid");
200                         continue;
201                 }
202                 is_addr = (array->len < 4);
203
204                 nm_utils_inet4_ntop (g_array_index (array, guint32, 0), buf);
205                 if (is_addr)
206                         g_string_append_printf (printable, "ip = %s", buf);
207                 else
208                         g_string_append_printf (printable, "dst = %s", buf);
209
210                 g_string_append_printf (printable, "/%u",
211                                         g_array_index (array, guint32, 1));
212
213                 if (array->len > 2) {
214                         nm_utils_inet4_ntop (g_array_index (array, guint32, 2), buf);
215                         if (is_addr)
216                                 g_string_append_printf (printable, ", gw = %s", buf);
217                         else
218                                 g_string_append_printf (printable, ", nh = %s", buf);
219                 }
220
221                 if (array->len > 3) {
222                         g_string_append_printf (printable, ", mt = %u",
223                                                 g_array_index (array, guint32, 3));
224                 }
225
226                 g_string_append (printable, " }");
227         }
228
229         g_value_take_string (dest_value, g_string_free (printable, FALSE));
230 }
231
232 static void
233 convert_one_gvalue_hash_entry (gpointer key, gpointer value, gpointer user_data)
234 {
235         GString *printable = (GString *) user_data;
236         char *value_as_string;
237
238         value_as_string = g_strdup_value_contents ((GValue *) value);
239         g_string_append_printf (printable, " { '%s': %s },", (const char *) key, value_as_string);
240         g_free (value_as_string);
241 }
242
243 static void
244 _nm_utils_convert_gvalue_hash_to_string (const GValue *src_value, GValue *dest_value)
245 {
246         GHashTable *hash;
247         GString *printable;
248
249         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_VARIANT));
250
251         hash = (GHashTable *) g_value_get_boxed (src_value);
252
253         printable = g_string_new ("[");
254         g_hash_table_foreach (hash, convert_one_gvalue_hash_entry, printable);
255         g_string_append (printable, " ]");
256
257         g_value_take_string (dest_value, printable->str);
258         g_string_free (printable, FALSE);
259 }
260
261 static void
262 convert_one_string_hash_entry (gpointer key, gpointer value, gpointer user_data)
263 {
264         GString *printable = (GString *) user_data;
265
266         if (printable->len)
267                 g_string_append_c (printable, ',');
268         g_string_append_printf (printable, "%s=%s", (const char *) key, (const char *) value);
269 }
270
271 static void
272 _nm_utils_convert_string_hash_to_string (const GValue *src_value, GValue *dest_value)
273 {
274         GHashTable *hash;
275         GString *printable;
276
277         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_STRING));
278
279         hash = (GHashTable *) g_value_get_boxed (src_value);
280
281         printable = g_string_new (NULL);
282         if (hash)
283                 g_hash_table_foreach (hash, convert_one_string_hash_entry, printable);
284
285         g_value_take_string (dest_value, g_string_free (printable, FALSE));
286 }
287
288 static void
289 _nm_utils_convert_byte_array_to_string (const GValue *src_value, GValue *dest_value)
290 {
291         GArray *array;
292         GString *printable;
293         guint i = 0;
294
295         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UCHAR_ARRAY));
296
297         array = (GArray *) g_value_get_boxed (src_value);
298
299         printable = g_string_new ("[");
300         if (array) {
301                 while (i < MIN (array->len, 35)) {
302                         if (i > 0)
303                                 g_string_append_c (printable, ' ');
304                         g_string_append_printf (printable, "0x%02X",
305                                                 g_array_index (array, unsigned char, i++));
306                 }
307                 if (i < array->len)
308                         g_string_append (printable, " ... ");
309         }
310         g_string_append_c (printable, ']');
311
312         g_value_take_string (dest_value, g_string_free (printable, FALSE));
313 }
314
315 static void
316 _nm_utils_convert_ip6_dns_array_to_string (const GValue *src_value, GValue *dest_value)
317 {
318         GPtrArray *ptr_array;
319         GString *printable;
320         guint i = 0;
321
322         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR));
323
324         ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
325
326         printable = g_string_new (NULL);
327         while (ptr_array && (i < ptr_array->len)) {
328                 GByteArray *bytearray;
329                 struct in6_addr *addr;
330
331                 if (i > 0)
332                         g_string_append (printable, ", ");
333
334                 bytearray = (GByteArray *) g_ptr_array_index (ptr_array, i++);
335                 if (bytearray->len != 16) {
336                         g_string_append (printable, "invalid");
337                         continue;
338                 }
339                 addr = (struct in6_addr *) bytearray->data;
340                 g_string_append (printable, nm_utils_inet6_ntop (addr, NULL));
341         }
342
343         g_value_take_string (dest_value, g_string_free (printable, FALSE));
344 }
345
346 static void
347 _nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValue *dest_value)
348 {
349         GPtrArray *ptr_array;
350         GString *printable;
351         guint i = 0;
352
353         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
354
355         ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
356
357         printable = g_string_new (NULL);
358         while (ptr_array && (i < ptr_array->len)) {
359                 GValueArray *elements;
360                 GValue *tmp;
361                 GByteArray *ba_addr;
362                 struct in6_addr *addr;
363                 guint32 prefix;
364
365                 if (i > 0)
366                         g_string_append (printable, "; ");
367
368                 g_string_append (printable, "{ ");
369                 elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
370                 if (!_nm_utils_gvalue_array_validate (elements, 3,
371                                                       DBUS_TYPE_G_UCHAR_ARRAY,
372                                                       G_TYPE_UINT,
373                                                       DBUS_TYPE_G_UCHAR_ARRAY)) {
374                         g_string_append (printable, "invalid }");
375                         continue;
376                 }
377
378                 /* IPv6 address */
379                 tmp = g_value_array_get_nth (elements, 0);
380                 ba_addr = g_value_get_boxed (tmp);
381                 if (ba_addr->len != 16) {
382                         g_string_append (printable, "invalid }");
383                         continue;
384                 }
385                 addr = (struct in6_addr *) ba_addr->data;
386                 g_string_append_printf (printable, "ip = %s", nm_utils_inet6_ntop (addr, NULL));
387
388                 /* Prefix */
389                 tmp = g_value_array_get_nth (elements, 1);
390                 prefix = g_value_get_uint (tmp);
391                 if (prefix > 128) {
392                         g_string_append (printable, "/invalid }");
393                         continue;
394                 }
395                 g_string_append_printf (printable, "/%u", prefix);
396                 g_string_append (printable, ", ");
397
398                 /* IPv6 Gateway */
399                 tmp = g_value_array_get_nth (elements, 2);
400                 ba_addr = g_value_get_boxed (tmp);
401                 if (ba_addr->len != 16) {
402                         g_string_append (printable, "invalid }");
403                         continue;
404                 }
405                 addr = (struct in6_addr *) ba_addr->data;
406                 g_string_append_printf (printable, "gw = %s", nm_utils_inet6_ntop (addr, NULL));
407                 g_string_append (printable, " }");
408         }
409
410         g_value_take_string (dest_value, g_string_free (printable, FALSE));
411 }
412
413 static void
414 _nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
415 {
416         GPtrArray *ptr_array;
417         GString *printable;
418         guint i = 0;
419
420         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE));
421
422         ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
423
424         printable = g_string_new (NULL);
425         while (ptr_array && (i < ptr_array->len)) {
426                 GValueArray *elements;
427                 GValue *tmp;
428                 GByteArray *ba_addr;
429                 struct in6_addr *addr;
430                 guint32 prefix, metric;
431
432                 if (i > 0)
433                         g_string_append (printable, "; ");
434
435                 g_string_append (printable, "{ ");
436                 elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
437                 if (!_nm_utils_gvalue_array_validate (elements, 4,
438                                                       DBUS_TYPE_G_UCHAR_ARRAY,
439                                                       G_TYPE_UINT,
440                                                       DBUS_TYPE_G_UCHAR_ARRAY,
441                                                       G_TYPE_UINT)) {
442                         g_string_append (printable, "invalid");
443                         continue;
444                 }
445
446                 /* Destination address */
447                 tmp = g_value_array_get_nth (elements, 0);
448                 ba_addr = g_value_get_boxed (tmp);
449                 if (ba_addr->len != 16) {
450                         g_string_append (printable, "invalid");
451                         continue;
452                 }
453                 addr = (struct in6_addr *) ba_addr->data;
454                 g_string_append_printf (printable, "dst = %s", nm_utils_inet6_ntop (addr, NULL));
455
456                 /* Prefix */
457                 tmp = g_value_array_get_nth (elements, 1);
458                 prefix = g_value_get_uint (tmp);
459                 if (prefix > 128) {
460                         g_string_append (printable, "/invalid");
461                         continue;
462                 }
463                 g_string_append_printf (printable, "/%u", prefix);
464                 g_string_append (printable, ", ");
465
466                 /* Next hop addresses */
467                 tmp = g_value_array_get_nth (elements, 2);
468                 ba_addr = g_value_get_boxed (tmp);
469                 if (ba_addr->len != 16) {
470                         g_string_append (printable, "invalid");
471                         continue;
472                 }
473                 addr = (struct in6_addr *) ba_addr->data;
474                 g_string_append_printf (printable, "nh = %s", nm_utils_inet6_ntop (addr, NULL));
475                 g_string_append (printable, ", ");
476
477                 /* Metric */
478                 tmp = g_value_array_get_nth (elements, 3);
479                 metric = g_value_get_uint (tmp);
480                 g_string_append_printf (printable, "mt = %u", metric);
481
482                 g_string_append (printable, " }");
483         }
484
485         g_value_take_string (dest_value, g_string_free (printable, FALSE));
486 }
487
488 #define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
489 #define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
490
491 static void
492 _nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value)
493 {
494         GPtrArray *src_outer_array;
495         GPtrArray *dst_outer_array;
496         guint i;
497
498         g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
499
500         src_outer_array = (GPtrArray *) g_value_get_boxed (src_value);
501         dst_outer_array = g_ptr_array_new ();
502
503         for (i = 0; src_outer_array && (i < src_outer_array->len); i++) {
504                 GValueArray *src_addr_array;
505                 GValueArray *dst_addr_array;
506                 GValue element = G_VALUE_INIT;
507                 GValue *src_addr, *src_prefix;
508                 GByteArray *ba;
509
510                 src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i);
511                 if (!_nm_utils_gvalue_array_validate (src_addr_array, 2, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT)) {
512                         g_warning ("%s: invalid old IPv6 address type", __func__);
513                         return;
514                 }
515
516                 dst_addr_array = g_value_array_new (3);
517
518                 src_addr = g_value_array_get_nth (src_addr_array, 0);
519                 g_value_array_append (dst_addr_array, src_addr);
520                 src_prefix = g_value_array_get_nth (src_addr_array, 1);
521                 g_value_array_append (dst_addr_array, src_prefix);
522
523                 /* Blank Gateway */
524                 g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
525                 ba = g_byte_array_new ();
526                 g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
527                 g_value_take_boxed (&element, ba);
528                 g_value_array_append (dst_addr_array, &element);
529                 g_value_unset (&element);
530
531                 g_ptr_array_add (dst_outer_array, dst_addr_array);
532         }
533
534         g_value_take_boxed (dst_value, dst_outer_array);
535 }
536
537 void
538 _nm_value_transforms_register (void)
539 {
540         static gboolean registered = FALSE;
541
542         if (G_UNLIKELY (!registered)) {
543                 g_value_register_transform_func (DBUS_TYPE_G_OBJECT_PATH,
544                                                  G_TYPE_STRING,
545                                                  _nm_utils_convert_op_to_string);
546                 g_value_register_transform_func (G_TYPE_STRV,
547                                                  DBUS_TYPE_G_LIST_OF_STRING,
548                                                  _nm_utils_convert_strv_to_slist);
549                 g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
550                                                  G_TYPE_STRV,
551                                                  _nm_utils_convert_slist_to_strv);
552                 g_value_register_transform_func (G_TYPE_STRV,
553                                                  DBUS_TYPE_G_ARRAY_OF_STRING,
554                                                  _nm_utils_convert_strv_to_ptrarray);
555                 g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
556                                                  G_TYPE_STRING,
557                                                  _nm_utils_convert_string_list_to_string);
558                 g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_STRING,
559                                                  G_TYPE_STRING,
560                                                  _nm_utils_convert_string_array_to_string);
561                 g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
562                                                  G_TYPE_STRING,
563                                                  _nm_utils_convert_op_array_to_string);
564                 g_value_register_transform_func (DBUS_TYPE_G_UINT_ARRAY,
565                                                  G_TYPE_STRING,
566                                                  _nm_utils_convert_uint_array_to_string);
567                 g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
568                                                  G_TYPE_STRING,
569                                                  _nm_utils_convert_ip4_addr_route_struct_array_to_string);
570                 g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_VARIANT,
571                                                  G_TYPE_STRING,
572                                                  _nm_utils_convert_gvalue_hash_to_string);
573                 g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_STRING,
574                                                  G_TYPE_STRING,
575                                                  _nm_utils_convert_string_hash_to_string);
576                 g_value_register_transform_func (DBUS_TYPE_G_UCHAR_ARRAY,
577                                                  G_TYPE_STRING,
578                                                  _nm_utils_convert_byte_array_to_string);
579                 g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
580                                                  G_TYPE_STRING,
581                                                  _nm_utils_convert_ip6_dns_array_to_string);
582                 g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
583                                                  G_TYPE_STRING,
584                                                  _nm_utils_convert_ip6_addr_struct_array_to_string);
585                 g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
586                                                  G_TYPE_STRING,
587                                                  _nm_utils_convert_ip6_route_struct_array_to_string);
588                 g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
589                                                  DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
590                                                  _nm_utils_convert_old_ip6_addr_array);
591                 registered = TRUE;
592         }
593 }