device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-util / nm-setting-ip6-config.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 2007 - 2014 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include <string.h>
25 #include <dbus/dbus-glib.h>
26
27 #include "nm-setting-ip6-config.h"
28 #include "nm-param-spec-specialized.h"
29 #include "nm-utils.h"
30 #include "nm-dbus-glib-types.h"
31 #include "nm-setting-private.h"
32
33 /**
34  * SECTION:nm-setting-ip6-config
35  * @short_description: Describes IPv6 addressing, routing, and name service properties
36  * @include: nm-setting-ip6-config.h
37  *
38  * The #NMSettingIP6Config object is a #NMSetting subclass that describes
39  * properties related to IPv6 addressing, routing, and Domain Name Service
40  **/
41
42 /**
43  * nm_setting_ip6_config_error_quark:
44  *
45  * Registers an error quark for #NMSettingIP6Config if necessary.
46  *
47  * Returns: the error quark used for #NMSettingIP6Config errors.
48  **/
49 GQuark
50 nm_setting_ip6_config_error_quark (void)
51 {
52         static GQuark quark;
53
54         if (G_UNLIKELY (!quark))
55                 quark = g_quark_from_static_string ("nm-setting-ip6-config-error-quark");
56         return quark;
57 }
58
59 G_DEFINE_BOXED_TYPE (NMIP6Address, nm_ip6_address, nm_ip6_address_dup, nm_ip6_address_unref)
60 G_DEFINE_BOXED_TYPE (NMIP6Route, nm_ip6_route, nm_ip6_route_dup, nm_ip6_route_unref)
61
62 G_DEFINE_TYPE_WITH_CODE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING,
63                          _nm_register_setting (NM_SETTING_IP6_CONFIG_SETTING_NAME,
64                                                g_define_type_id,
65                                                4,
66                                                NM_SETTING_IP6_CONFIG_ERROR))
67 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG)
68
69 #define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate))
70
71 typedef struct {
72         char *method;
73         char *dhcp_hostname;
74         GSList *dns;        /* array of struct in6_addr */
75         GSList *dns_search; /* list of strings */
76         GSList *addresses;  /* array of NMIP6Address */
77         GSList *routes;     /* array of NMIP6Route */
78         gint64  route_metric;
79         gboolean ignore_auto_routes;
80         gboolean ignore_auto_dns;
81         gboolean never_default;
82         gboolean may_fail;
83         NMSettingIP6ConfigPrivacy ip6_privacy;
84 } NMSettingIP6ConfigPrivate;
85
86
87 enum {
88         PROP_0,
89         PROP_METHOD,
90         PROP_DHCP_HOSTNAME,
91         PROP_DNS,
92         PROP_DNS_SEARCH,
93         PROP_ADDRESSES,
94         PROP_ROUTES,
95         PROP_ROUTE_METRIC,
96         PROP_IGNORE_AUTO_ROUTES,
97         PROP_IGNORE_AUTO_DNS,
98         PROP_NEVER_DEFAULT,
99         PROP_MAY_FAIL,
100         PROP_IP6_PRIVACY,
101
102         LAST_PROP
103 };
104
105 /**
106  * nm_setting_ip6_config_new:
107  *
108  * Creates a new #NMSettingIP6Config object with default values.
109  *
110  * Returns: (transfer full): the new empty #NMSettingIP6Config object
111  **/
112 NMSetting *
113 nm_setting_ip6_config_new (void)
114 {
115         return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP6_CONFIG, NULL);
116 }
117
118 /**
119  * nm_setting_ip6_config_get_method:
120  * @setting: the #NMSettingIP6Config
121  *
122  * Returns: the #NMSettingIP6Config:method property of the setting
123  **/
124 const char *
125 nm_setting_ip6_config_get_method (NMSettingIP6Config *setting)
126 {
127         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
128
129         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->method;
130 }
131
132 /**
133  * nm_setting_ip6_config_get_dhcp_hostname:
134  * @setting: the #NMSettingIP6Config
135  *
136  * Returns the value contained in the #NMSettingIP6Config:dhcp-hostname
137  * property.
138  *
139  * Returns: the configured hostname to send to the DHCP server
140  *
141  * Since: 0.9.8
142  **/
143 const char *
144 nm_setting_ip6_config_get_dhcp_hostname (NMSettingIP6Config *setting)
145 {
146         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
147
148         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dhcp_hostname;
149 }
150
151 /**
152  * nm_setting_ip6_config_get_num_dns:
153  * @setting: the #NMSettingIP6Config
154  *
155  * Returns: the number of configured DNS servers
156  **/
157 guint32
158 nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting)
159 {
160         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0);
161
162         return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns);
163 }
164
165 /**
166  * nm_setting_ip6_config_get_dns:
167  * @setting: the #NMSettingIP6Config
168  * @i: index number of the DNS server to return
169  *
170  * Returns: (transfer none): the IPv6 address of the DNS server at index @i
171  **/
172 const struct in6_addr *
173 nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i)
174 {
175         NMSettingIP6ConfigPrivate *priv;
176
177
178         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
179
180         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
181         g_return_val_if_fail (i <= g_slist_length (priv->dns), NULL);
182
183         return (const struct in6_addr *) g_slist_nth_data (priv->dns, i);
184 }
185
186 /**
187  * nm_setting_ip6_config_add_dns:
188  * @setting: the #NMSettingIP6Config
189  * @dns: the IPv6 address of the DNS server to add
190  *
191  * Adds a new DNS server to the setting.
192  *
193  * Returns: %TRUE if the DNS server was added; %FALSE if the server was already
194  * known
195  **/
196 gboolean
197 nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *addr)
198 {
199         NMSettingIP6ConfigPrivate *priv;
200         struct in6_addr *copy;
201         GSList *iter;
202
203         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
204
205         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
206         for (iter = priv->dns; iter; iter = g_slist_next (iter)) {
207                 if (!memcmp (addr, (struct in6_addr *) iter->data, sizeof (struct in6_addr)))
208                         return FALSE;
209         }
210
211         copy = g_malloc0 (sizeof (struct in6_addr));
212         memcpy (copy, addr, sizeof (struct in6_addr));
213         priv->dns = g_slist_append (priv->dns, copy);
214         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
215
216         return TRUE;
217 }
218
219 /**
220  * nm_setting_ip6_config_remove_dns:
221  * @setting: the #NMSettingIP6Config
222  * @i: index number of the DNS server to remove
223  *
224  * Removes the DNS server at index @i.
225  **/
226 void
227 nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i)
228 {
229         NMSettingIP6ConfigPrivate *priv;
230         GSList *elt;
231
232         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
233
234         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
235         elt = g_slist_nth (priv->dns, i);
236         g_return_if_fail (elt != NULL);
237
238         g_free (elt->data);
239         priv->dns = g_slist_delete_link (priv->dns, elt);
240         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
241 }
242
243 /**
244  * nm_setting_ip6_config_remove_dns_by_value:
245  * @setting: the #NMSettingIP6Config
246  * @dns: the IPv6 address of the DNS server to remove
247  *
248  * Removes the DNS server at index @i.
249  *
250  * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not.
251  *
252  * Since: 0.9.10
253  **/
254 gboolean
255 nm_setting_ip6_config_remove_dns_by_value (NMSettingIP6Config *setting,
256                                            const struct in6_addr *addr)
257 {
258         NMSettingIP6ConfigPrivate *priv;
259         GSList *iter;
260
261         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
262
263         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
264         for (iter = priv->dns; iter; iter = g_slist_next (iter)) {
265                 if (!memcmp (addr, (struct in6_addr *) iter->data, sizeof (struct in6_addr))) {
266                         priv->dns = g_slist_delete_link (priv->dns, iter);
267                         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
268                         return TRUE;
269                 }
270         }
271         return FALSE;
272 }
273
274 /**
275  * nm_setting_ip6_config_clear_dns:
276  * @setting: the #NMSettingIP6Config
277  *
278  * Removes all configured DNS servers.
279  **/
280 void
281 nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting)
282 {
283         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
284
285         g_slist_free_full (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns, g_free);
286         NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns = NULL;
287         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
288 }
289
290 /**
291  * nm_setting_ip6_config_get_num_dns_searches:
292  * @setting: the #NMSettingIP6Config
293  *
294  * Returns: the number of configured DNS search domains
295  **/
296 guint32
297 nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting)
298 {
299         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0);
300
301         return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search);
302 }
303
304 /**
305  * nm_setting_ip6_config_get_dns_search:
306  * @setting: the #NMSettingIP6Config
307  * @i: index number of the DNS search domain to return
308  *
309  * Returns: the DNS search domain at index @i
310  **/
311 const char *
312 nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i)
313 {
314         NMSettingIP6ConfigPrivate *priv;
315
316         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
317
318         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
319         g_return_val_if_fail (i <= g_slist_length (priv->dns_search), NULL);
320
321         return (const char *) g_slist_nth_data (priv->dns_search, i);
322 }
323
324 /**
325  * nm_setting_ip6_config_add_dns_search:
326  * @setting: the #NMSettingIP6Config
327  * @dns_search: the search domain to add
328  *
329  * Adds a new DNS search domain to the setting.
330  *
331  * Returns: %TRUE if the DNS search domain was added; %FALSE if the search
332  * domain was already known
333  **/
334 gboolean
335 nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting,
336                                       const char *dns_search)
337 {
338         NMSettingIP6ConfigPrivate *priv;
339         GSList *iter;
340
341         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
342         g_return_val_if_fail (dns_search != NULL, FALSE);
343         g_return_val_if_fail (dns_search[0] != '\0', FALSE);
344
345         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
346         for (iter = priv->dns_search; iter; iter = g_slist_next (iter)) {
347                 if (!strcmp (dns_search, (char *) iter->data))
348                         return FALSE;
349         }
350
351         priv->dns_search = g_slist_append (priv->dns_search, g_strdup (dns_search));
352         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
353         return TRUE;
354 }
355
356 /**
357  * nm_setting_ip6_config_remove_dns_search:
358  * @setting: the #NMSettingIP6Config
359  * @i: index number of the DNS search domain
360  *
361  * Removes the DNS search domain at index @i.
362  **/
363 void
364 nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i)
365 {
366         NMSettingIP6ConfigPrivate *priv;
367         GSList *elt;
368
369         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
370
371         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
372         elt = g_slist_nth (priv->dns_search, i);
373         g_return_if_fail (elt != NULL);
374
375         g_free (elt->data);
376         priv->dns_search = g_slist_delete_link (priv->dns_search, elt);
377         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
378 }
379
380 /**
381  * nm_setting_ip6_config_remove_dns_search_by_value:
382  * @setting: the #NMSettingIP6Config
383  * @dns_search: the search domain to remove
384  *
385  * Removes the DNS search domain @dns_search.
386  *
387  * Returns: %TRUE if the DNS search domain was found and removed; %FALSE if it was not.
388  *
389  * Since 0.9.10
390  **/
391 gboolean
392 nm_setting_ip6_config_remove_dns_search_by_value (NMSettingIP6Config *setting,
393                                                   const char *dns_search)
394 {
395         NMSettingIP6ConfigPrivate *priv;
396         GSList *iter;
397
398         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
399         g_return_val_if_fail (dns_search != NULL, FALSE);
400         g_return_val_if_fail (dns_search[0] != '\0', FALSE);
401
402         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
403         for (iter = priv->dns_search; iter; iter = g_slist_next (iter)) {
404                 if (!strcmp (dns_search, (char *) iter->data)) {
405                         priv->dns_search = g_slist_delete_link (priv->dns_search, iter);
406                         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
407                         return TRUE;
408                 }
409         }
410         return FALSE;
411 }
412
413 /**
414  * nm_setting_ip6_config_clear_dns_searches:
415  * @setting: the #NMSettingIP6Config
416  *
417  * Removes all configured DNS search domains.
418  **/
419 void
420 nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting)
421 {
422         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
423
424         g_slist_free_full (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search, g_free);
425         NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search = NULL;
426         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
427 }
428
429 /**
430  * nm_setting_ip6_config_get_num_addresses:
431  * @setting: the #NMSettingIP6Config
432  *
433  * Returns: the number of configured addresses
434  **/
435 guint32
436 nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting)
437 {
438         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0);
439
440         return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->addresses);
441 }
442
443 /**
444  * nm_setting_ip6_config_get_address:
445  * @setting: the #NMSettingIP6Config
446  * @i: index number of the address to return
447  *
448  * Returns: the address at index @i
449  **/
450 NMIP6Address *
451 nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i)
452 {
453         NMSettingIP6ConfigPrivate *priv;
454
455         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
456
457         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
458         g_return_val_if_fail (i <= g_slist_length (priv->addresses), NULL);
459
460         return (NMIP6Address *) g_slist_nth_data (priv->addresses, i);
461 }
462
463 /**
464  * nm_setting_ip6_config_add_address:
465  * @setting: the #NMSettingIP6Config
466  * @address: the new address to add
467  *
468  * Adds a new IPv6 address and associated information to the setting.  The
469  * given address is duplicated internally and is not changed by this function.
470  *
471  * Returns: %TRUE if the address was added; %FALSE if the address was already
472  * known.
473  **/
474 gboolean
475 nm_setting_ip6_config_add_address (NMSettingIP6Config *setting,
476                                    NMIP6Address *address)
477 {
478         NMSettingIP6ConfigPrivate *priv;
479         NMIP6Address *copy;
480         GSList *iter;
481
482         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
483         g_return_val_if_fail (address != NULL, FALSE);
484
485         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
486         for (iter = priv->addresses; iter; iter = g_slist_next (iter)) {
487                 if (nm_ip6_address_compare ((NMIP6Address *) iter->data, address))
488                         return FALSE;
489         }
490
491         copy = nm_ip6_address_dup (address);
492         priv->addresses = g_slist_append (priv->addresses, copy);
493         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
494         return TRUE;
495 }
496
497 /**
498  * nm_setting_ip6_config_remove_address:
499  * @setting: the #NMSettingIP6Config
500  * @i: index number of the address to remove
501  *
502  * Removes the address at index @i.
503  **/
504 void
505 nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i)
506 {
507         NMSettingIP6ConfigPrivate *priv;
508         GSList *elt;
509
510         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
511
512         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
513         elt = g_slist_nth (priv->addresses, i);
514         g_return_if_fail (elt != NULL);
515
516         nm_ip6_address_unref ((NMIP6Address *) elt->data);
517         priv->addresses = g_slist_delete_link (priv->addresses, elt);
518         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
519 }
520
521 /**
522  * nm_setting_ip6_config_remove_address_by_value:
523  * @setting: the #NMSettingIP6Config
524  * @address: the address to remove
525  *
526  * Removes the address @address.
527  *
528  * Returns: %TRUE if the address was found and removed; %FALSE if it was not.
529  *
530  * Since: 0.9.10
531  **/
532 gboolean
533 nm_setting_ip6_config_remove_address_by_value (NMSettingIP6Config *setting,
534                                                NMIP6Address *address)
535 {
536         NMSettingIP6ConfigPrivate *priv;
537         GSList *iter;
538
539         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
540         g_return_val_if_fail (address != NULL, FALSE);
541
542         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
543         for (iter = priv->addresses; iter; iter = g_slist_next (iter)) {
544                 if (nm_ip6_address_compare ((NMIP6Address *) iter->data, address)) {
545                         priv->addresses = g_slist_delete_link (priv->addresses, iter);
546                         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
547                         return TRUE;
548                 }
549         }
550         return FALSE;
551 }
552
553 /**
554  * nm_setting_ip6_config_clear_addresses:
555  * @setting: the #NMSettingIP6Config
556  *
557  * Removes all configured addresses.
558  **/
559 void
560 nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting)
561 {
562         NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
563
564         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
565
566         g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip6_address_unref);
567         priv->addresses = NULL;
568         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
569 }
570
571 /**
572  * nm_setting_ip6_config_get_num_routes:
573  * @setting: the #NMSettingIP6Config
574  *
575  * Returns: the number of configured routes
576  **/
577 guint32
578 nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting)
579 {
580         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0);
581
582         return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->routes);
583 }
584
585 /**
586  * nm_setting_ip6_config_get_route:
587  * @setting: the #NMSettingIP6Config
588  * @i: index number of the route to return
589  *
590  * Returns: the route at index @i
591  **/
592 NMIP6Route *
593 nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i)
594 {
595         NMSettingIP6ConfigPrivate *priv;
596
597         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
598
599         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
600         g_return_val_if_fail (i <= g_slist_length (priv->routes), NULL);
601
602         return (NMIP6Route *) g_slist_nth_data (priv->routes, i);
603 }
604
605 /**
606  * nm_setting_ip6_config_add_route:
607  * @setting: the #NMSettingIP6Config
608  * @route: the route to add
609  *
610  * Adds a new IPv6 route and associated information to the setting.  The
611  * given route is duplicated internally and is not changed by this function.
612  *
613  * Returns: %TRUE if the route was added; %FALSE if the route was already known.
614  **/
615 gboolean
616 nm_setting_ip6_config_add_route (NMSettingIP6Config *setting,
617                                  NMIP6Route *route)
618 {
619         NMSettingIP6ConfigPrivate *priv;
620         NMIP6Route *copy;
621         GSList *iter;
622
623         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
624         g_return_val_if_fail (route != NULL, FALSE);
625
626         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
627         for (iter = priv->routes; iter; iter = g_slist_next (iter)) {
628                 if (nm_ip6_route_compare ((NMIP6Route *) iter->data, route))
629                         return FALSE;
630         }
631
632         copy = nm_ip6_route_dup (route);
633         priv->routes = g_slist_append (priv->routes, copy);
634         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
635         return TRUE;
636 }
637
638 /**
639  * nm_setting_ip6_config_remove_route:
640  * @setting: the #NMSettingIP6Config
641  * @i: index number of the route
642  *
643  * Removes the route at index @i.
644  **/
645 void
646 nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i)
647 {
648         NMSettingIP6ConfigPrivate *priv;
649         GSList *elt;
650
651         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
652
653         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
654         elt = g_slist_nth (priv->routes, i);
655         g_return_if_fail (elt != NULL);
656
657         nm_ip6_route_unref ((NMIP6Route *) elt->data);
658         priv->routes = g_slist_delete_link (priv->routes, elt);
659         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
660 }
661
662 /**
663  * nm_setting_ip6_config_remove_route_by_value:
664  * @setting: the #NMSettingIP6Config
665  * @route: the route to remove
666  *
667  * Removes the route @route.
668  *
669  * Returns: %TRUE if the route was found and removed; %FALSE if it was not.
670  *
671  * Since: 0.9.10
672  **/
673 gboolean
674 nm_setting_ip6_config_remove_route_by_value (NMSettingIP6Config *setting,
675                                              NMIP6Route *route)
676 {
677         NMSettingIP6ConfigPrivate *priv;
678         GSList *iter;
679
680         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
681         g_return_val_if_fail (route != NULL, FALSE);
682
683         priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
684         for (iter = priv->routes; iter; iter = g_slist_next (iter)) {
685                 if (nm_ip6_route_compare ((NMIP6Route *) iter->data, route)) {
686                         nm_ip6_route_unref ((NMIP6Route *) iter->data);
687                         priv->routes = g_slist_delete_link (priv->routes, iter);
688                         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
689                         return TRUE;
690                 }
691         }
692         return FALSE;
693 }
694
695 /**
696  * nm_setting_ip6_config_clear_routes:
697  * @setting: the #NMSettingIP6Config
698  *
699  * Removes all configured routes.
700  **/
701 void
702 nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting)
703 {
704         NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
705
706         g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
707
708         g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip6_route_unref);
709         priv->routes = NULL;
710         g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
711 }
712
713 /**
714  * nm_setting_ip6_config_get_route_metric:
715  * @setting: the #NMSettingIP6Config
716  *
717  * Returns the value contained in the #NMSettingIP6Config:route-metric
718  * property.
719  *
720  * Returns: the route metric that is used for IPv6 routes that don't explicitly
721  * specify a metric. See #NMSettingIP6Config:route-metric for more details.
722  *
723  * Since: 1.0
724  **/
725 gint64
726 nm_setting_ip6_config_get_route_metric (NMSettingIP6Config *setting)
727 {
728         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), -1);
729
730         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->route_metric;
731 }
732
733 /**
734  * nm_setting_ip6_config_get_ignore_auto_routes:
735  * @setting: the #NMSettingIP6Config
736  *
737  * Returns the value contained in the #NMSettingIP6Config:ignore-auto-routes
738  * property.
739  *
740  * Returns: %TRUE if automatically configured (ie via DHCP) routes should be
741  * ignored.
742  **/
743 gboolean
744 nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting)
745 {
746         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
747
748         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_auto_routes;
749 }
750
751 /**
752  * nm_setting_ip6_config_get_ignore_auto_dns:
753  * @setting: the #NMSettingIP6Config
754  *
755  * Returns the value contained in the #NMSettingIP6Config:ignore-auto-dns
756  * property.
757  *
758  * Returns: %TRUE if automatically configured (ie via DHCP or router
759  * advertisements) DNS information should be ignored.
760  **/
761 gboolean
762 nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting)
763 {
764         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
765
766         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_auto_dns;
767 }
768
769 /**
770  * nm_setting_ip6_config_get_never_default:
771  * @setting: the #NMSettingIP6Config
772  *
773  * Returns the value contained in the #NMSettingIP6Config:never-default
774  * property.
775  *
776  * Returns: %TRUE if this connection should never be the default connection
777  * for IPv6 addressing
778  **/
779 gboolean
780 nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting)
781 {
782         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
783
784         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->never_default;
785 }
786
787 /**
788  * nm_setting_ip6_config_get_may_fail:
789  * @setting: the #NMSettingIP6Config
790  *
791  * Returns the value contained in the #NMSettingIP6Config:may-fail
792  * property.
793  *
794  * Returns: %TRUE if this connection doesn't require IPv6 addressing to complete
795  * for the connection to succeed.
796  **/
797 gboolean
798 nm_setting_ip6_config_get_may_fail (NMSettingIP6Config *setting)
799 {
800         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
801
802         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->may_fail;
803 }
804
805 /**
806  * nm_setting_ip6_config_get_ip6_privacy:
807  * @setting: the #NMSettingIP6Config
808  *
809  * Returns the value contained in the #NMSettingIP6Config:ip6-privacy
810  * property.
811  *
812  * Returns: IPv6 Privacy Extensions configuration value (#NMSettingIP6ConfigPrivacy).
813  **/
814 NMSettingIP6ConfigPrivacy
815 nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting)
816 {
817         g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
818
819         return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ip6_privacy;
820 }
821
822 static gboolean
823 verify (NMSetting *setting, GSList *all_settings, GError **error)
824 {
825         NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
826         GSList *iter;
827         int i;
828
829         if (!priv->method) {
830                 g_set_error_literal (error,
831                                      NM_SETTING_IP6_CONFIG_ERROR,
832                                      NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY,
833                                      _("property is missing"));
834                 g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_METHOD);
835                 return FALSE;
836         }
837
838         if (!strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
839                 if (!priv->addresses) {
840                         g_set_error (error,
841                                      NM_SETTING_IP6_CONFIG_ERROR,
842                                      NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY,
843                                      _("this property cannot be empty for '%s=%s'"),
844                                      NM_SETTING_IP6_CONFIG_METHOD, priv->method);
845                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
846                         return FALSE;
847                 }
848         } else if (   !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)
849                    || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
850                    || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
851                 if (g_slist_length (priv->dns)) {
852                         g_set_error (error,
853                                      NM_SETTING_IP6_CONFIG_ERROR,
854                                      NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
855                                      _("this property is not allowed for '%s=%s'"),
856                                      NM_SETTING_IP6_CONFIG_METHOD, priv->method);
857                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DNS);
858                         return FALSE;
859                 }
860
861                 if (g_slist_length (priv->dns_search)) {
862                         g_set_error (error,
863                                      NM_SETTING_IP6_CONFIG_ERROR,
864                                      NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
865                                      _("this property is not allowed for '%s=%s'"),
866                                      NM_SETTING_IP6_CONFIG_METHOD, priv->method);
867                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DNS_SEARCH);
868                         return FALSE;
869                 }
870
871                 if (g_slist_length (priv->addresses)) {
872                         g_set_error (error,
873                                      NM_SETTING_IP6_CONFIG_ERROR,
874                                      NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
875                                      _("this property is not allowed for '%s=%s'"),
876                                      NM_SETTING_IP6_CONFIG_METHOD, priv->method);
877                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
878                         return FALSE;
879                 }
880         } else if (   !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
881                    || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
882                 /* nothing to do */
883         } else {
884                 g_set_error_literal (error,
885                                      NM_SETTING_IP6_CONFIG_ERROR,
886                                      NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
887                                      _("property is invalid"));
888                 g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_METHOD);
889                 return FALSE;
890         }
891
892         if (priv->dhcp_hostname && !strlen (priv->dhcp_hostname)) {
893                 g_set_error_literal (error,
894                                      NM_SETTING_IP6_CONFIG_ERROR,
895                                      NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
896                                      _("property is missing"));
897                 g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME);
898                 return FALSE;
899         }
900
901         /* Validate addresses */
902         for (iter = priv->addresses, i = 0; iter; iter = g_slist_next (iter), i++) {
903                 NMIP6Address *addr = (NMIP6Address *) iter->data;
904                 guint32 prefix = nm_ip6_address_get_prefix (addr);
905
906                 if (IN6_IS_ADDR_UNSPECIFIED (nm_ip6_address_get_address (addr))) {
907                         g_set_error (error,
908                                      NM_SETTING_IP6_CONFIG_ERROR,
909                                      NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
910                                      _("%d. IPv6 address is invalid"),
911                                      i+1);
912                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
913                         return FALSE;
914                 }
915
916                 if (!prefix || prefix > 128) {
917                         g_set_error (error,
918                                      NM_SETTING_IP6_CONFIG_ERROR,
919                                      NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
920                                      _("%d. IPv6 address has invalid prefix"),
921                                      i+1);
922                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
923                         return FALSE;
924                 }
925         }
926
927         /* Validate routes */
928         for (iter = priv->routes, i = 0; iter; iter = g_slist_next (iter), i++) {
929                 NMIP6Route *route = (NMIP6Route *) iter->data;
930                 guint32 prefix = nm_ip6_route_get_prefix (route);
931
932                 if (!prefix || prefix > 128) {
933                         g_set_error (error,
934                                      NM_SETTING_IP6_CONFIG_ERROR,
935                                      NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
936                                      _("%d. route has invalid prefix"),
937                                      i+1);
938                         g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ROUTES);
939                         return FALSE;
940                 }
941         }
942
943         return TRUE;
944 }
945
946
947 static void
948 nm_setting_ip6_config_init (NMSettingIP6Config *setting)
949 {
950 }
951
952 static void
953 finalize (GObject *object)
954 {
955         NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object);
956
957         g_free (priv->method);
958         g_free (priv->dhcp_hostname);
959
960         g_slist_free_full (priv->dns, g_free);
961         g_slist_free_full (priv->dns_search, g_free);
962         g_slist_free_full (priv->addresses, g_free);
963         g_slist_free_full (priv->routes, g_free);
964
965         G_OBJECT_CLASS (nm_setting_ip6_config_parent_class)->finalize (object);
966 }
967
968 static void
969 set_property (GObject *object, guint prop_id,
970               const GValue *value, GParamSpec *pspec)
971 {
972         NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object);
973
974         switch (prop_id) {
975         case PROP_METHOD:
976                 g_free (priv->method);
977                 priv->method = g_value_dup_string (value);
978                 break;
979         case PROP_DNS:
980                 g_slist_free_full (priv->dns, g_free);
981                 priv->dns = nm_utils_ip6_dns_from_gvalue (value);
982                 break;
983         case PROP_DNS_SEARCH:
984                 g_slist_free_full (priv->dns_search, g_free);
985                 priv->dns_search = g_value_dup_boxed (value);
986                 break;
987         case PROP_ADDRESSES:
988                 g_slist_free_full (priv->addresses, g_free);
989                 priv->addresses = nm_utils_ip6_addresses_from_gvalue (value);
990                 break;
991         case PROP_ROUTES:
992                 g_slist_free_full (priv->routes, g_free);
993                 priv->routes = nm_utils_ip6_routes_from_gvalue (value);
994                 break;
995         case PROP_ROUTE_METRIC:
996                 priv->route_metric = g_value_get_int64 (value);
997                 break;
998         case PROP_IGNORE_AUTO_ROUTES:
999                 priv->ignore_auto_routes = g_value_get_boolean (value);
1000                 break;
1001         case PROP_IGNORE_AUTO_DNS:
1002                 priv->ignore_auto_dns = g_value_get_boolean (value);
1003                 break;
1004         case PROP_DHCP_HOSTNAME:
1005                 g_free (priv->dhcp_hostname);
1006                 priv->dhcp_hostname = g_value_dup_string (value);
1007                 break;
1008         case PROP_NEVER_DEFAULT:
1009                 priv->never_default = g_value_get_boolean (value);
1010                 break;
1011         case PROP_MAY_FAIL:
1012                 priv->may_fail = g_value_get_boolean (value);
1013                 break;
1014         case PROP_IP6_PRIVACY:
1015                 priv->ip6_privacy = g_value_get_int (value);
1016                 break;
1017         default:
1018                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1019                 break;
1020         }
1021 }
1022
1023 static void
1024 get_property (GObject *object, guint prop_id,
1025               GValue *value, GParamSpec *pspec)
1026 {
1027         NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object);
1028
1029         switch (prop_id) {
1030         case PROP_METHOD:
1031                 g_value_set_string (value, priv->method);
1032                 break;
1033         case PROP_DNS:
1034                 nm_utils_ip6_dns_to_gvalue (priv->dns, value);
1035                 break;
1036         case PROP_DNS_SEARCH:
1037                 g_value_set_boxed (value, priv->dns_search);
1038                 break;
1039         case PROP_ADDRESSES:
1040                 nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
1041                 break;
1042         case PROP_ROUTES:
1043                 nm_utils_ip6_routes_to_gvalue (priv->routes, value);
1044                 break;
1045         case PROP_ROUTE_METRIC:
1046                 g_value_set_int64 (value, priv->route_metric);
1047                 break;
1048         case PROP_IGNORE_AUTO_ROUTES:
1049                 g_value_set_boolean (value, priv->ignore_auto_routes);
1050                 break;
1051         case PROP_IGNORE_AUTO_DNS:
1052                 g_value_set_boolean (value, priv->ignore_auto_dns);
1053                 break;
1054         case PROP_DHCP_HOSTNAME:
1055                 g_value_set_string (value, priv->dhcp_hostname);
1056                 break;
1057         case PROP_NEVER_DEFAULT:
1058                 g_value_set_boolean (value, priv->never_default);
1059                 break;
1060         case PROP_MAY_FAIL:
1061                 g_value_set_boolean (value, priv->may_fail);
1062                 break;
1063         case PROP_IP6_PRIVACY:
1064                 g_value_set_int (value, priv->ip6_privacy);
1065                 break;
1066         default:
1067                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1068                 break;
1069         }
1070 }
1071
1072 static void
1073 nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
1074 {
1075         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
1076         NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
1077
1078         g_type_class_add_private (setting_class, sizeof (NMSettingIP6ConfigPrivate));
1079
1080         /* virtual methods */
1081         object_class->set_property = set_property;
1082         object_class->get_property = get_property;
1083         object_class->finalize     = finalize;
1084         parent_class->verify       = verify;
1085
1086         /* Properties */
1087         /**
1088          * NMSettingIP6Config:method:
1089          *
1090          * IPv6 configuration method.  If "auto" is specified then the appropriate
1091          * automatic method (PPP, router advertisement, etc) is used for the device
1092          * and most other properties can be left unset.  To force the use of DHCP
1093          * only, specify "dhcp"; this method is only valid for Ethernet- based
1094          * hardware.  If "link-local" is specified, then an IPv6 link-local address
1095          * will be assigned to the interface.  If "manual" is specified, static IP
1096          * addressing is used and at least one IP address must be given in the
1097          * "addresses" property.  If "ignore" is specified, IPv6 configuration is
1098          * not done. This property must be set.  Note: the "shared" method is not
1099          * yet supported.
1100          **/
1101         g_object_class_install_property
1102                 (object_class, PROP_METHOD,
1103                  g_param_spec_string (NM_SETTING_IP6_CONFIG_METHOD, "", "",
1104                                       NULL,
1105                                       G_PARAM_READWRITE |
1106                                       NM_SETTING_PARAM_INFERRABLE |
1107                                       G_PARAM_STATIC_STRINGS));
1108
1109         /**
1110          * NMSettingIP6Config:dhcp-hostname:
1111          *
1112          * The specified name will be sent to the DHCP server when acquiring a
1113          * lease.
1114          *
1115          * Since: 0.9.8
1116          **/
1117         g_object_class_install_property
1118                 (object_class, PROP_DHCP_HOSTNAME,
1119                  g_param_spec_string (NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME, "", "",
1120                                       NULL,
1121                                       G_PARAM_READWRITE |
1122                                       G_PARAM_STATIC_STRINGS));
1123
1124         /**
1125          * NMSettingIP6Config:dns:
1126          *
1127          * Array of DNS servers, where each member of the array is a byte array
1128          * containing the IPv6 address of the DNS server (in network byte order).
1129          * For the "auto" method, these DNS servers are appended to those (if any)
1130          * returned by automatic configuration.  DNS servers cannot be used with the
1131          * "shared" or "link-local" methods as there is no usptream network. In all
1132          * other methods, these DNS servers are used as the only DNS servers for
1133          * this connection.
1134          **/
1135         g_object_class_install_property
1136                 (object_class, PROP_DNS,
1137                  _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_DNS, "", "",
1138                                              DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
1139                                              G_PARAM_READWRITE |
1140                                              G_PARAM_STATIC_STRINGS));
1141
1142         /**
1143          * NMSettingIP6Config:dns-search:
1144          *
1145          * List of DNS search domains.  For the "auto" method, these search domains
1146          * are appended to those returned by automatic configuration. Search domains
1147          * cannot be used with the "shared" or "link-local" methods as there is no
1148          * upstream network.  In all other methods, these search domains are used as
1149          * the only search domains for this connection.
1150          **/
1151         g_object_class_install_property
1152                 (object_class, PROP_DNS_SEARCH,
1153                  _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_DNS_SEARCH, "", "",
1154                                              DBUS_TYPE_G_LIST_OF_STRING,
1155                                              G_PARAM_READWRITE |
1156                                              G_PARAM_STATIC_STRINGS));
1157
1158         /**
1159          * NMSettingIP6Config:addresses:
1160          *
1161          * Array of IPv6 address structures.  Each IPv6 address structure is
1162          * composed of 3 members, the first being a byte array containing the IPv6
1163          * address (network byte order), the second a 32-bit integer containing the
1164          * IPv6 address prefix, and the third a byte array containing the IPv6
1165          * address (network byte order) of the gateway associated with this address,
1166          * if any.  If no gateway is given, the third element should be given as all
1167          * zeros.  For the "auto" method, given IP addresses are appended to those
1168          * returned by automatic configuration.  Addresses cannot be used with the
1169          * "shared" or "link-local" methods as the interface is automatically
1170          * assigned an address with these methods.
1171          **/
1172         g_object_class_install_property
1173                 (object_class, PROP_ADDRESSES,
1174                  _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ADDRESSES, "", "",
1175                                              DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
1176                                              G_PARAM_READWRITE |
1177                                              NM_SETTING_PARAM_INFERRABLE |
1178                                              G_PARAM_STATIC_STRINGS));
1179
1180         /**
1181          * NMSettingIP6Config:routes:
1182          *
1183          * Array of IPv6 route structures.  Each IPv6 route structure is composed of
1184          * 4 members; the first being the destination IPv6 network or address
1185          * (network byte order) as a byte array, the second the destination network
1186          * or address IPv6 prefix, the third being the next-hop IPv6 address
1187          * (network byte order) if any, and the fourth being the route metric. For
1188          * the "auto" method, given IP routes are appended to those returned by
1189          * automatic configuration.  Routes cannot be used with the "shared" or
1190          * "link-local" methods because there is no upstream network.
1191          **/
1192         g_object_class_install_property
1193                 (object_class, PROP_ROUTES,
1194                  _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ROUTES, "", "",
1195                                              DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
1196                                              G_PARAM_READWRITE |
1197                                              NM_SETTING_PARAM_INFERRABLE |
1198                                              G_PARAM_STATIC_STRINGS));
1199
1200         /**
1201          * NMSettingIP6Config:route-metric:
1202          *
1203          * The default metric for routes that don't explicitly specify a metric.
1204          * The default value -1 means that the metric is choosen automatically
1205          * based on the device type.
1206          * The metric applies to dynamic routes, manual (static) routes that
1207          * don't have an explicit metric setting, address prefix routes, and
1208          * the default route.
1209          * As the linux kernel replaces zero (0) by 1024 (user-default), setting
1210          * this property to 0 means effectively setting it to 1024.
1211          *
1212          * Since: 1.0
1213          **/
1214         g_object_class_install_property
1215             (object_class, PROP_ROUTE_METRIC,
1216              g_param_spec_int64 (NM_SETTING_IP6_CONFIG_ROUTE_METRIC, "", "",
1217                                  -1, G_MAXUINT32, -1,
1218                                  G_PARAM_READWRITE |
1219                                  G_PARAM_CONSTRUCT |
1220                                  G_PARAM_STATIC_STRINGS));
1221
1222         /**
1223          * NMSettingIP6Config:ignore-auto-routes:
1224          *
1225          * When the method is set to "auto" or "dhcp" and this property is set to
1226          * %TRUE, automatically configured routes are ignored and only routes
1227          * specified in the #NMSettingIP6Config:routes property, if any, are used.
1228          **/
1229         g_object_class_install_property
1230                 (object_class, PROP_IGNORE_AUTO_ROUTES,
1231                  g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, "", "",
1232                                        FALSE,
1233                                        G_PARAM_READWRITE |
1234                                        G_PARAM_CONSTRUCT |
1235                                        G_PARAM_STATIC_STRINGS));
1236
1237         /**
1238          * NMSettingIP6Config:ignore-auto-dns:
1239          *
1240          * When the method is set to "auto" or "dhcp" and this property is set to
1241          * %TRUE, automatically configured nameservers and search domains are
1242          * ignored and only nameservers and search domains specified in the
1243          * #NMSettingIP6Config:dns and #NMSettingIP6Config:dns-search properties, if
1244          * any, are used.
1245          **/
1246         g_object_class_install_property
1247                 (object_class, PROP_IGNORE_AUTO_DNS,
1248                  g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, "", "",
1249                                        FALSE,
1250                                        G_PARAM_READWRITE |
1251                                        G_PARAM_CONSTRUCT |
1252                                        G_PARAM_STATIC_STRINGS));
1253
1254         /**
1255          * NMSettingIP6Config:never-default:
1256          *
1257          * If %TRUE, this connection will never be the default IPv6 connection,
1258          * meaning it will never be assigned the default IPv6 route by
1259          * NetworkManager.
1260          **/
1261         g_object_class_install_property
1262                 (object_class, PROP_NEVER_DEFAULT,
1263                  g_param_spec_boolean (NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, "", "",
1264                                        FALSE,
1265                                        G_PARAM_READWRITE |
1266                                        G_PARAM_CONSTRUCT |
1267                                        G_PARAM_STATIC_STRINGS));
1268
1269         /**
1270          * NMSettingIP6Config:may-fail:
1271          *
1272          * If %TRUE, allow overall network configuration to proceed even if IPv6
1273          * configuration times out.  Note that at least one IP configuration must
1274          * succeed or overall network configuration will still fail.  For example,
1275          * in IPv4-only networks, setting this property to %TRUE allows the overall
1276          * network configuration to succeed if IPv6 configuration fails but IPv4
1277          * configuration completes successfully.
1278          **/
1279         g_object_class_install_property
1280                 (object_class, PROP_MAY_FAIL,
1281                  g_param_spec_boolean (NM_SETTING_IP6_CONFIG_MAY_FAIL, "", "",
1282                                        TRUE,
1283                                        G_PARAM_READWRITE |
1284                                        G_PARAM_CONSTRUCT |
1285                                        G_PARAM_STATIC_STRINGS));
1286
1287         /**
1288          * NMSettingIP6Config:ip6-privacy:
1289          *
1290          * Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.  If
1291          * enabled, it makes the kernel generate a temporary IPv6 address in
1292          * addition to the public one generated from MAC address via modified
1293          * EUI-64.  This enhances privacy, but could cause problems in some
1294          * applications, on the other hand.  The permitted values are: 0: disabled,
1295          * 1: enabled (prefer public address), 2: enabled (prefer temporary
1296          * addresses).
1297          **/
1298         g_object_class_install_property
1299                 (object_class, PROP_IP6_PRIVACY,
1300                  g_param_spec_int (NM_SETTING_IP6_CONFIG_IP6_PRIVACY, "", "",
1301                                    NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
1302                                    NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
1303                                    NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
1304                                    G_PARAM_READWRITE |
1305                                    G_PARAM_CONSTRUCT |
1306                                    G_PARAM_STATIC_STRINGS));
1307 }
1308
1309 /********************************************************************/
1310
1311 struct NMIP6Address {
1312         guint32 refcount;
1313         struct in6_addr address;
1314         guint32 prefix;
1315         struct in6_addr gateway;
1316 };
1317
1318 /**
1319  * nm_ip6_address_new:
1320  *
1321  * Creates and returns a new #NMIP6Address object.
1322  *
1323  * Returns: (transfer full): the new empty #NMIP6Address object
1324  **/
1325 NMIP6Address *
1326 nm_ip6_address_new (void)
1327 {
1328         NMIP6Address *address;
1329
1330         address = g_malloc0 (sizeof (NMIP6Address));
1331         address->refcount = 1;
1332         return address;
1333 }
1334
1335 /**
1336  * nm_ip6_address_dup:
1337  * @source: the #NMIP6Address object to copy
1338  *
1339  * Copies a given #NMIP6Address object and returns the copy.
1340  *
1341  * Returns: (transfer full): the copy of the given #NMIP6Address copy
1342  **/
1343 NMIP6Address *
1344 nm_ip6_address_dup (NMIP6Address *source)
1345 {
1346         NMIP6Address *address;
1347
1348         g_return_val_if_fail (source != NULL, NULL);
1349         g_return_val_if_fail (source->refcount > 0, NULL);
1350
1351         address = nm_ip6_address_new ();
1352         address->prefix = source->prefix;
1353         memcpy (&address->address, &source->address, sizeof (struct in6_addr));
1354         memcpy (&address->gateway, &source->gateway, sizeof (struct in6_addr));
1355
1356         return address;
1357 }
1358
1359 /**
1360  * nm_ip6_address_ref:
1361  * @address: the #NMIP6Address
1362  *
1363  * Increases the reference count of the object.
1364  **/
1365 void
1366 nm_ip6_address_ref (NMIP6Address *address)
1367 {
1368         g_return_if_fail (address != NULL);
1369         g_return_if_fail (address->refcount > 0);
1370
1371         address->refcount++;
1372 }
1373
1374 /**
1375  * nm_ip6_address_unref:
1376  * @address: the #NMIP6Address
1377  *
1378  * Decreases the reference count of the object.  If the reference count
1379  * reaches zero, the object will be destroyed.
1380  **/
1381 void
1382 nm_ip6_address_unref (NMIP6Address *address)
1383 {
1384         g_return_if_fail (address != NULL);
1385         g_return_if_fail (address->refcount > 0);
1386
1387         address->refcount--;
1388         if (address->refcount == 0) {
1389                 memset (address, 0, sizeof (NMIP6Address));
1390                 g_free (address);
1391         }
1392 }
1393
1394 /**
1395  * nm_ip6_address_compare:
1396  * @address: the #NMIP6Address
1397  * @other: the #NMIP6Address to compare @address to.
1398  *
1399  * Determines if two #NMIP6Address objects contain the same values.
1400  *
1401  * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
1402  **/
1403 gboolean
1404 nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other)
1405 {
1406         g_return_val_if_fail (address != NULL, FALSE);
1407         g_return_val_if_fail (address->refcount > 0, FALSE);
1408
1409         g_return_val_if_fail (other != NULL, FALSE);
1410         g_return_val_if_fail (other->refcount > 0, FALSE);
1411
1412         if (   memcmp (&address->address, &other->address, sizeof (struct in6_addr))
1413             || address->prefix != other->prefix
1414             || memcmp (&address->gateway, &other->gateway, sizeof (struct in6_addr)))
1415                 return FALSE;
1416         return TRUE;
1417 }
1418
1419 /**
1420  * nm_ip6_address_get_address:
1421  * @address: the #NMIP6Address
1422  *
1423  * Gets the IPv6 address property of this address object.
1424  *
1425  * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
1426  *          the IPv6 address
1427  **/
1428 const struct in6_addr *
1429 nm_ip6_address_get_address (NMIP6Address *address)
1430 {
1431         g_return_val_if_fail (address != NULL, NULL);
1432         g_return_val_if_fail (address->refcount > 0, NULL);
1433
1434         return &address->address;
1435 }
1436
1437 /**
1438  * nm_ip6_address_set_address:
1439  * @address: the #NMIP6Address
1440  * @addr: the IPv6 address
1441  *
1442  * Sets the IPv6 address property of this object.
1443  **/
1444 void
1445 nm_ip6_address_set_address (NMIP6Address *address, const struct in6_addr *addr)
1446 {
1447         g_return_if_fail (address != NULL);
1448         g_return_if_fail (address->refcount > 0);
1449         g_return_if_fail (addr != NULL);
1450
1451         memcpy (&address->address, addr, sizeof (struct in6_addr));
1452 }
1453
1454 /**
1455  * nm_ip6_address_get_prefix:
1456  * @address: the #NMIP6Address
1457  *
1458  * Gets the IPv6 address prefix property of this address object.
1459  *
1460  * Returns: the IPv6 address prefix
1461  **/
1462 guint32
1463 nm_ip6_address_get_prefix (NMIP6Address *address)
1464 {
1465         g_return_val_if_fail (address != NULL, 0);
1466         g_return_val_if_fail (address->refcount > 0, 0);
1467
1468         return address->prefix;
1469 }
1470
1471 /**
1472  * nm_ip6_address_set_prefix:
1473  * @address: the #NMIP6Address
1474  * @prefix: the address prefix, a number between 0 and 128 inclusive
1475  *
1476  * Sets the IPv6 address prefix.
1477  **/
1478 void
1479 nm_ip6_address_set_prefix (NMIP6Address *address, guint32 prefix)
1480 {
1481         g_return_if_fail (address != NULL);
1482         g_return_if_fail (address->refcount > 0);
1483         g_return_if_fail (prefix <= 128);
1484         g_return_if_fail (prefix > 0);
1485
1486         address->prefix = prefix;
1487 }
1488
1489 /**
1490  * nm_ip6_address_get_gateway:
1491  * @address: the #NMIP6Address
1492  *
1493  * Gets the IPv6 default gateway property of this address object.
1494  *
1495  * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
1496  *          the IPv6 gateway address
1497  **/
1498 const struct in6_addr *
1499 nm_ip6_address_get_gateway (NMIP6Address *address)
1500 {
1501         g_return_val_if_fail (address != NULL, NULL);
1502         g_return_val_if_fail (address->refcount > 0, NULL);
1503
1504         return &address->gateway;
1505 }
1506
1507 /**
1508  * nm_ip6_address_set_gateway:
1509  * @address: the #NMIP6Address
1510  * @gateway: the IPv6 default gateway
1511  *
1512  * Sets the IPv6 default gateway property of this address object.
1513  **/
1514 void
1515 nm_ip6_address_set_gateway (NMIP6Address *address, const struct in6_addr *gateway)
1516 {
1517         g_return_if_fail (address != NULL);
1518         g_return_if_fail (address->refcount > 0);
1519         g_return_if_fail (gateway != NULL);
1520
1521         memcpy (&address->gateway, gateway, sizeof (struct in6_addr));
1522 }
1523
1524 /********************************************************************/
1525
1526 struct NMIP6Route {
1527         guint32 refcount;
1528
1529         struct in6_addr dest;
1530         guint32 prefix;
1531         struct in6_addr next_hop;
1532         guint32 metric;    /* lower metric == more preferred */
1533 };
1534
1535 /**
1536  * nm_ip6_route_new:
1537  *
1538  * Creates and returns a new #NMIP6Route object.
1539  *
1540  * Returns: (transfer full): the new empty #NMIP6Route object
1541  **/
1542 NMIP6Route *
1543 nm_ip6_route_new (void)
1544 {
1545         NMIP6Route *route;
1546
1547         route = g_malloc0 (sizeof (NMIP6Route));
1548         route->refcount = 1;
1549         return route;
1550 }
1551
1552 /**
1553  * nm_ip6_route_dup:
1554  * @source: the #NMIP6Route object to copy
1555  *
1556  * Copies a given #NMIP6Route object and returns the copy.
1557  *
1558  * Returns: (transfer full): the copy of the given #NMIP6Route copy
1559  **/
1560 NMIP6Route *
1561 nm_ip6_route_dup (NMIP6Route *source)
1562 {
1563         NMIP6Route *route;
1564
1565         g_return_val_if_fail (source != NULL, NULL);
1566         g_return_val_if_fail (source->refcount > 0, NULL);
1567
1568         route = nm_ip6_route_new ();
1569         route->prefix = source->prefix;
1570         route->metric = source->metric;
1571         memcpy (&route->dest, &source->dest, sizeof (struct in6_addr));
1572         memcpy (&route->next_hop, &source->next_hop, sizeof (struct in6_addr));
1573
1574         return route;
1575 }
1576
1577 /**
1578  * nm_ip6_route_ref:
1579  * @route: the #NMIP6Route
1580  *
1581  * Increases the reference count of the object.
1582  **/
1583 void
1584 nm_ip6_route_ref (NMIP6Route *route)
1585 {
1586         g_return_if_fail (route != NULL);
1587         g_return_if_fail (route->refcount > 0);
1588
1589         route->refcount++;
1590 }
1591
1592 /**
1593  * nm_ip6_route_unref:
1594  * @route: the #NMIP6Route
1595  *
1596  * Decreases the reference count of the object.  If the reference count
1597  * reaches zero, the object will be destroyed.
1598  **/
1599 void
1600 nm_ip6_route_unref (NMIP6Route *route)
1601 {
1602         g_return_if_fail (route != NULL);
1603         g_return_if_fail (route->refcount > 0);
1604
1605         route->refcount--;
1606         if (route->refcount == 0) {
1607                 memset (route, 0, sizeof (NMIP6Route));
1608                 g_free (route);
1609         }
1610 }
1611
1612 /**
1613  * nm_ip6_route_compare:
1614  * @route: the #NMIP6Route
1615  * @other: the #NMIP6Route to compare @route to.
1616  *
1617  * Determines if two #NMIP6Route objects contain the same values.
1618  *
1619  * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
1620  **/
1621 gboolean
1622 nm_ip6_route_compare (NMIP6Route *route, NMIP6Route *other)
1623 {
1624         g_return_val_if_fail (route != NULL, FALSE);
1625         g_return_val_if_fail (route->refcount > 0, FALSE);
1626
1627         g_return_val_if_fail (other != NULL, FALSE);
1628         g_return_val_if_fail (other->refcount > 0, FALSE);
1629
1630         if (   memcmp (&route->dest, &other->dest, sizeof (struct in6_addr))
1631             || route->prefix != other->prefix
1632             || memcmp (&route->next_hop, &other->next_hop, sizeof (struct in6_addr))
1633             || route->metric != other->metric)
1634                 return FALSE;
1635         return TRUE;
1636 }
1637
1638 /**
1639  * nm_ip6_route_get_dest:
1640  * @route: the #NMIP6Route
1641  *
1642  * Gets the IPv6 destination address property of this route object.
1643  *
1644  * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
1645  *          the IPv6 address of destination
1646  **/
1647 const struct in6_addr *
1648 nm_ip6_route_get_dest (NMIP6Route *route)
1649 {
1650         g_return_val_if_fail (route != NULL, NULL);
1651         g_return_val_if_fail (route->refcount > 0, NULL);
1652
1653         return &route->dest;
1654 }
1655
1656 /**
1657  * nm_ip6_route_set_dest:
1658  * @route: the #NMIP6Route
1659  * @dest: the destination address
1660  *
1661  * Sets the IPv6 destination address property of this route object.
1662  **/
1663 void
1664 nm_ip6_route_set_dest (NMIP6Route *route, const struct in6_addr *dest)
1665 {
1666         g_return_if_fail (route != NULL);
1667         g_return_if_fail (route->refcount > 0);
1668         g_return_if_fail (dest != NULL);
1669
1670         memcpy (&route->dest, dest, sizeof (struct in6_addr));
1671 }
1672
1673 /**
1674  * nm_ip6_route_get_prefix:
1675  * @route: the #NMIP6Route
1676  *
1677  * Gets the IPv6 prefix (ie "32" or "64" etc) of this route.
1678  *
1679  * Returns: the IPv6 prefix
1680  **/
1681 guint32
1682 nm_ip6_route_get_prefix (NMIP6Route *route)
1683 {
1684         g_return_val_if_fail (route != NULL, 0);
1685         g_return_val_if_fail (route->refcount > 0, 0);
1686
1687         return route->prefix;
1688 }
1689
1690 /**
1691  * nm_ip6_route_set_prefix:
1692  * @route: the #NMIP6Route
1693  * @prefix: the prefix, a number between 1 and 128 inclusive
1694  *
1695  * Sets the IPv6 prefix of this route.
1696  **/
1697 void
1698 nm_ip6_route_set_prefix (NMIP6Route *route, guint32 prefix)
1699 {
1700         g_return_if_fail (route != NULL);
1701         g_return_if_fail (route->refcount > 0);
1702         g_return_if_fail (prefix <= 128);
1703         g_return_if_fail (prefix > 0);
1704
1705         route->prefix = prefix;
1706 }
1707
1708 /**
1709  * nm_ip6_route_get_next_hop:
1710  * @route: the #NMIP6Route
1711  *
1712  * Gets the IPv6 address of the next hop of this route.
1713  *
1714  * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
1715  *          the IPv6 address of next hop
1716  **/
1717 const struct in6_addr *
1718 nm_ip6_route_get_next_hop (NMIP6Route *route)
1719 {
1720         g_return_val_if_fail (route != NULL, NULL);
1721         g_return_val_if_fail (route->refcount > 0, NULL);
1722
1723         return &route->next_hop;
1724 }
1725
1726 /**
1727  * nm_ip6_route_set_next_hop:
1728  * @route: the #NMIP6Route
1729  * @next_hop: the IPv6 address of the next hop
1730  *
1731  * Sets the IPv6 address of the next hop of this route.
1732  **/
1733 void
1734 nm_ip6_route_set_next_hop (NMIP6Route *route, const struct in6_addr *next_hop)
1735 {
1736         g_return_if_fail (route != NULL);
1737         g_return_if_fail (route->refcount > 0);
1738         g_return_if_fail (next_hop != NULL);
1739
1740         memcpy (&route->next_hop, next_hop, sizeof (struct in6_addr));
1741 }
1742
1743 /**
1744  * nm_ip6_route_get_metric:
1745  * @route: the #NMIP6Route
1746  *
1747  * Gets the route metric property of this route object; lower values indicate
1748  * "better" or more preferred routes.
1749  *
1750  * Returns: the route metric
1751  **/
1752 guint32
1753 nm_ip6_route_get_metric (NMIP6Route *route)
1754 {
1755         g_return_val_if_fail (route != NULL, 0);
1756         g_return_val_if_fail (route->refcount > 0, 0);
1757
1758         return route->metric;
1759 }
1760
1761 /**
1762  * nm_ip6_route_set_metric:
1763  * @route: the #NMIP6Route
1764  * @metric: the route metric
1765  *
1766  * Sets the route metric property of this route object; lower values indicate
1767  * "better" or more preferred routes.
1768  **/
1769 void
1770 nm_ip6_route_set_metric (NMIP6Route *route, guint32 metric)
1771 {
1772         g_return_if_fail (route != NULL);
1773         g_return_if_fail (route->refcount > 0);
1774
1775         route->metric = metric;
1776 }