1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program 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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Copyright (C) 2005 - 2014 Red Hat, Inc.
19 * Copyright (C) 2006 - 2008 Novell, Inc.
22 #include "nm-default.h"
24 #include "nm-ip4-config.h"
27 #include <arpa/inet.h>
30 #include "nm-platform.h"
31 #include "nm-platform-utils.h"
32 #include "NetworkManagerUtils.h"
33 #include "nm-route-manager.h"
34 #include "nm-core-internal.h"
36 #include "nmdbus-ip4-config.h"
38 G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT)
40 #define NM_IP4_CONFIG_GET_PRIVATE(o) ((o)->priv)
42 typedef struct _NMIP4ConfigPrivate {
43 gboolean never_default;
51 GPtrArray *dns_options;
57 NMIPConfigSource mtu_source;
63 /* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
64 G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32));
65 G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
67 NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
82 nm_ip4_config_new (int ifindex)
84 g_return_val_if_fail (ifindex >= -1, NULL);
85 return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG,
86 NM_IP4_CONFIG_IFINDEX, ifindex,
91 nm_ip4_config_get_ifindex (const NMIP4Config *config)
93 return NM_IP4_CONFIG_GET_PRIVATE (config)->ifindex;
96 /******************************************************************/
99 _ipv4_is_zeronet (in_addr_t network)
101 /* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */
102 return (network & htonl(0xff000000)) == htonl(0x00000000);
105 /******************************************************************/
108 * nm_ip4_config_capture_resolv_conf():
109 * @nameservers: array of guint32
110 * @rc_contents: the contents of a resolv.conf or %NULL to read /etc/resolv.conf
112 * Reads all resolv.conf IPv4 nameservers and adds them to @nameservers.
114 * Returns: %TRUE if nameservers were added, %FALSE if @nameservers is unchanged
117 nm_ip4_config_capture_resolv_conf (GArray *nameservers,
118 GPtrArray *dns_options,
119 const char *rc_contents)
121 GPtrArray *read_ns, *read_options;
123 gboolean changed = FALSE;
125 g_return_val_if_fail (nameservers != NULL, FALSE);
127 read_ns = nm_utils_read_resolv_conf_nameservers (rc_contents);
131 for (i = 0; i < read_ns->len; i++) {
132 const char *s = g_ptr_array_index (read_ns, i);
135 if (!inet_pton (AF_INET, s, (void *) &ns) || !ns)
138 /* Ignore duplicates */
139 for (j = 0; j < nameservers->len; j++) {
140 if (g_array_index (nameservers, guint32, j) == ns)
144 if (j == nameservers->len) {
145 g_array_append_val (nameservers, ns);
149 g_ptr_array_unref (read_ns);
152 read_options = nm_utils_read_resolv_conf_dns_options (rc_contents);
156 for (i = 0; i < read_options->len; i++) {
157 const char *s = g_ptr_array_index (read_options, i);
159 if (_nm_utils_dns_option_validate (s, NULL, NULL, FALSE, _nm_utils_dns_option_descs) &&
160 _nm_utils_dns_option_find_idx (dns_options, s) < 0) {
161 g_ptr_array_add (dns_options, g_strdup (s));
165 g_ptr_array_unref (read_options);
172 addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
174 return a->address == b->address
175 && a->plen == b->plen
176 && ((a->peer_address ^ b->peer_address) & nm_utils_ip4_prefix_to_netmask (a->plen)) == 0;
180 routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gboolean consider_gateway_and_metric)
182 return a->network == b->network && a->plen == b->plen &&
183 (!consider_gateway_and_metric || (a->gateway == b->gateway && a->metric == b->metric));
186 /*****************************************************************************/
189 _addresses_sort_cmp_get_prio (in_addr_t addr)
191 if (nm_utils_ip4_address_is_link_local (addr))
197 _addresses_sort_cmp (gconstpointer a, gconstpointer b)
200 const NMPlatformIP4Address *a1 = a, *a2 = b;
202 /* Sort by address type. For example link local will
203 * be sorted *after* a global address. */
204 p1 = _addresses_sort_cmp_get_prio (a1->address);
205 p2 = _addresses_sort_cmp_get_prio (a2->address);
207 return p1 > p2 ? -1 : 1;
209 /* Sort the addresses based on their source. */
210 if (a1->source != a2->source)
211 return a1->source > a2->source ? -1 : 1;
213 if ((a1->label[0] == '\0') != (a2->label[0] == '\0'))
214 return (a1->label[0] == '\0') ? -1 : 1;
216 /* finally sort addresses lexically */
217 c = memcmp (&a1->address, &a2->address, sizeof (a2->address));
218 return c != 0 ? c : memcmp (a1, a2, sizeof (*a1));
222 nm_ip4_config_addresses_sort (NMIP4Config *self)
224 NMIP4ConfigPrivate *priv;
226 char *data_pre = NULL;
229 g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
231 priv = NM_IP4_CONFIG_GET_PRIVATE (self);
232 if (priv->addresses->len > 1) {
233 data_len = priv->addresses->len * g_array_get_element_size (priv->addresses);
234 data_pre = g_new (char, data_len);
235 memcpy (data_pre, priv->addresses->data, data_len);
237 g_array_sort (priv->addresses, _addresses_sort_cmp);
239 changed = memcmp (data_pre, priv->addresses->data, data_len) != 0;
243 _notify (self, PROP_ADDRESS_DATA);
244 _notify (self, PROP_ADDRESSES);
251 /*****************************************************************************/
254 nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
257 NMIP4ConfigPrivate *priv;
259 guint32 lowest_metric = G_MAXUINT32;
260 guint32 old_gateway = 0;
261 gboolean old_has_gateway = FALSE;
263 /* Slaves have no IP configuration */
264 if (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex) > 0)
267 config = nm_ip4_config_new (ifindex);
268 priv = NM_IP4_CONFIG_GET_PRIVATE (config);
270 g_array_unref (priv->addresses);
271 g_array_unref (priv->routes);
273 priv->addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
274 priv->routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
276 /* Extract gateway from default route */
277 old_gateway = priv->gateway;
278 old_has_gateway = priv->has_gateway;
279 for (i = 0; i < priv->routes->len; ) {
280 const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i);
282 if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
283 if (route->metric < lowest_metric) {
284 priv->gateway = route->gateway;
285 lowest_metric = route->metric;
287 priv->has_gateway = TRUE;
288 /* Remove the default route from the list */
289 g_array_remove_index_fast (priv->routes, i);
295 /* we detect the route metric based on the default route. All non-default
296 * routes have their route metrics explicitly set. */
297 priv->route_metric = priv->has_gateway ? (gint64) lowest_metric : (gint64) -1;
299 /* If there is a host route to the gateway, ignore that route. It is
300 * automatically added by NetworkManager when needed.
302 if (priv->has_gateway) {
303 for (i = 0; i < priv->routes->len; i++) {
304 const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i);
306 if ( (route->plen == 32)
307 && (route->network == priv->gateway)
308 && (route->gateway == 0)) {
309 g_array_remove_index (priv->routes, i);
315 /* If the interface has the default route, and has IPv4 addresses, capture
316 * nameservers from /etc/resolv.conf.
318 if (priv->addresses->len && priv->has_gateway && capture_resolv_conf) {
319 if (nm_ip4_config_capture_resolv_conf (priv->nameservers, priv->dns_options, NULL))
320 _notify (config, PROP_NAMESERVERS);
323 /* actually, nobody should be connected to the signal, just to be sure, notify */
324 _notify (config, PROP_ADDRESS_DATA);
325 _notify (config, PROP_ROUTE_DATA);
326 _notify (config, PROP_ADDRESSES);
327 _notify (config, PROP_ROUTES);
328 if ( priv->gateway != old_gateway
329 || priv->has_gateway != old_has_gateway)
330 _notify (config, PROP_GATEWAY);
336 nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric)
338 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
340 gs_unref_ptrarray GPtrArray *added_addresses = NULL;
342 g_return_val_if_fail (ifindex > 0, FALSE);
343 g_return_val_if_fail (config != NULL, FALSE);
346 nm_platform_ip4_address_sync (NM_PLATFORM_GET, ifindex, priv->addresses,
347 default_route_metric >= 0 ? &added_addresses : NULL);
351 int count = nm_ip4_config_get_num_routes (config);
352 GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count);
354 gs_unref_array GArray *device_route_purge_list = NULL;
356 if ( default_route_metric >= 0
357 && added_addresses) {
358 /* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
359 * As we don't do that for IPv4, add it here shortly before syncing
360 * the routes. For NMRouteManager these routes are very much important. */
361 for (i = 0; i < added_addresses->len; i++) {
362 const NMPlatformIP4Address *addr = added_addresses->pdata[i];
363 NMPlatformIP4Route route = { 0 };
368 route.ifindex = ifindex;
369 route.source = NM_IP_CONFIG_SOURCE_KERNEL;
371 /* The destination network depends on the peer-address. */
372 route.network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
374 if (_ipv4_is_zeronet (route.network)) {
375 /* Kernel doesn't add device-routes for destinations that
376 * start with 0.x.y.z. Skip them. */
380 route.plen = addr->plen;
381 route.pref_src = addr->address;
382 route.metric = default_route_metric;
384 g_array_append_val (routes, route);
386 if (default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
387 if (!device_route_purge_list)
388 device_route_purge_list = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
389 route.metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
390 g_array_append_val (device_route_purge_list, route);
395 for (i = 0; i < count; i++) {
396 const NMPlatformIP4Route *route;
398 route = nm_ip4_config_get_route (config, i);
400 /* Don't add the route if it's more specific than one of the subnets
401 * the device already has an IP address on.
403 if ( route->gateway == 0
404 && nm_ip4_config_destination_is_direct (config, route->network, route->plen))
407 /* duplicates in @routes are no problem as route-manager handles them
408 * gracefully (by ignoring them). */
409 g_array_append_vals (routes, route, 1);
412 nm_route_manager_ip4_route_register_device_route_purge_list (nm_route_manager_get (), device_route_purge_list);
414 success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0, routes_full_sync);
415 g_array_unref (routes);
424 nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric)
426 NMIP4ConfigPrivate *priv;
427 guint naddresses, nroutes, nnameservers, nsearches;
433 g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
435 priv = NM_IP4_CONFIG_GET_PRIVATE (config);
437 g_object_freeze_notify (G_OBJECT (config));
439 naddresses = nm_setting_ip_config_get_num_addresses (setting);
440 nroutes = nm_setting_ip_config_get_num_routes (setting);
441 nnameservers = nm_setting_ip_config_get_num_dns (setting);
442 nsearches = nm_setting_ip_config_get_num_dns_searches (setting);
445 if (nm_setting_ip_config_get_never_default (setting))
446 nm_ip4_config_set_never_default (config, TRUE);
447 else if (nm_setting_ip_config_get_ignore_auto_routes (setting))
448 nm_ip4_config_set_never_default (config, FALSE);
449 if (nm_setting_ip_config_get_gateway (setting)) {
452 inet_pton (AF_INET, nm_setting_ip_config_get_gateway (setting), &gateway);
453 nm_ip4_config_set_gateway (config, gateway);
456 if (priv->route_metric == -1)
457 priv->route_metric = nm_setting_ip_config_get_route_metric (setting);
460 for (i = 0; i < naddresses; i++) {
461 NMIPAddress *s_addr = nm_setting_ip_config_get_address (setting, i);
463 NMPlatformIP4Address address;
465 memset (&address, 0, sizeof (address));
466 nm_ip_address_get_address_binary (s_addr, &address.address);
467 address.peer_address = address.address;
468 address.plen = nm_ip_address_get_prefix (s_addr);
469 address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
470 address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
471 address.source = NM_IP_CONFIG_SOURCE_USER;
473 label = nm_ip_address_get_attribute (s_addr, "label");
475 g_strlcpy (address.label, g_variant_get_string (label, NULL), sizeof (address.label));
477 nm_ip4_config_add_address (config, &address);
481 if (nm_setting_ip_config_get_ignore_auto_routes (setting))
482 nm_ip4_config_reset_routes (config);
483 for (i = 0; i < nroutes; i++) {
484 NMIPRoute *s_route = nm_setting_ip_config_get_route (setting, i);
485 NMPlatformIP4Route route;
487 memset (&route, 0, sizeof (route));
488 nm_ip_route_get_dest_binary (s_route, &route.network);
489 route.plen = nm_ip_route_get_prefix (s_route);
490 nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
491 if (nm_ip_route_get_metric (s_route) == -1)
492 route.metric = default_route_metric;
494 route.metric = nm_ip_route_get_metric (s_route);
495 route.source = NM_IP_CONFIG_SOURCE_USER;
497 g_assert (route.plen > 0);
499 nm_ip4_config_add_route (config, &route);
503 if (nm_setting_ip_config_get_ignore_auto_dns (setting)) {
504 nm_ip4_config_reset_nameservers (config);
505 nm_ip4_config_reset_domains (config);
506 nm_ip4_config_reset_searches (config);
508 for (i = 0; i < nnameservers; i++) {
511 if (inet_pton (AF_INET, nm_setting_ip_config_get_dns (setting, i), &ip) == 1)
512 nm_ip4_config_add_nameserver (config, ip);
514 for (i = 0; i < nsearches; i++)
515 nm_ip4_config_add_search (config, nm_setting_ip_config_get_dns_search (setting, i));
518 while ((i = nm_setting_ip_config_next_valid_dns_option (setting, i)) >= 0) {
519 nm_ip4_config_add_dns_option (config, nm_setting_ip_config_get_dns_option (setting, i));
523 g_object_thaw_notify (G_OBJECT (config));
527 nm_ip4_config_create_setting (const NMIP4Config *config)
529 NMSettingIPConfig *s_ip4;
531 guint naddresses, nroutes, nnameservers, nsearches, noptions;
532 const char *method = NULL;
536 s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
540 NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
542 return NM_SETTING (s_ip4);
545 gateway = nm_ip4_config_get_gateway (config);
546 naddresses = nm_ip4_config_get_num_addresses (config);
547 nroutes = nm_ip4_config_get_num_routes (config);
548 nnameservers = nm_ip4_config_get_num_nameservers (config);
549 nsearches = nm_ip4_config_get_num_searches (config);
550 noptions = nm_ip4_config_get_num_dns_options (config);
551 route_metric = nm_ip4_config_get_route_metric (config);
554 for (i = 0; i < naddresses; i++) {
555 const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
558 /* Detect dynamic address */
559 if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
560 method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
564 /* Static address found. */
566 method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
568 s_addr = nm_ip_address_new_binary (AF_INET, &address->address, address->plen, NULL);
570 nm_ip_address_set_attribute (s_addr, "label", g_variant_new_string (address->label));
572 nm_setting_ip_config_add_address (s_ip4, s_addr);
573 nm_ip_address_unref (s_addr);
577 if ( nm_ip4_config_has_gateway (config)
578 && nm_setting_ip_config_get_num_addresses (s_ip4) > 0) {
580 NM_SETTING_IP_CONFIG_GATEWAY, nm_utils_inet4_ntop (gateway, NULL),
584 /* Use 'disabled' if the method wasn't previously set */
586 method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
589 NM_SETTING_IP_CONFIG_METHOD, method,
590 NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) route_metric,
594 for (i = 0; i < nroutes; i++) {
595 const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
598 /* Ignore default route. */
602 /* Ignore routes provided by external sources */
603 if (route->source != NM_IP_CONFIG_SOURCE_USER)
606 s_route = nm_ip_route_new_binary (AF_INET,
607 &route->network, route->plen,
608 &route->gateway, route->metric,
610 nm_setting_ip_config_add_route (s_ip4, s_route);
611 nm_ip_route_unref (s_route);
615 for (i = 0; i < nnameservers; i++) {
616 guint32 nameserver = nm_ip4_config_get_nameserver (config, i);
618 nm_setting_ip_config_add_dns (s_ip4, nm_utils_inet4_ntop (nameserver, NULL));
620 for (i = 0; i < nsearches; i++) {
621 const char *search = nm_ip4_config_get_search (config, i);
623 nm_setting_ip_config_add_dns_search (s_ip4, search);
626 for (i = 0; i < noptions; i++) {
627 const char *option = nm_ip4_config_get_dns_option (config, i);
629 nm_setting_ip_config_add_dns_option (s_ip4, option);
632 return NM_SETTING (s_ip4);
635 /******************************************************************/
638 nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags)
640 NMIP4ConfigPrivate *dst_priv, *src_priv;
643 g_return_if_fail (src != NULL);
644 g_return_if_fail (dst != NULL);
646 dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
647 src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
649 g_object_freeze_notify (G_OBJECT (dst));
652 for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++)
653 nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i));
656 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
657 for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++)
658 nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
661 /* default gateway */
662 if (nm_ip4_config_has_gateway (src))
663 nm_ip4_config_set_gateway (dst, nm_ip4_config_get_gateway (src));
666 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
667 for (i = 0; i < nm_ip4_config_get_num_routes (src); i++)
668 nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i));
671 if (dst_priv->route_metric == -1)
672 dst_priv->route_metric = src_priv->route_metric;
673 else if (src_priv->route_metric != -1)
674 dst_priv->route_metric = MIN (dst_priv->route_metric, src_priv->route_metric);
677 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
678 for (i = 0; i < nm_ip4_config_get_num_domains (src); i++)
679 nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
683 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
684 for (i = 0; i < nm_ip4_config_get_num_searches (src); i++)
685 nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
689 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
690 for (i = 0; i < nm_ip4_config_get_num_dns_options (src); i++)
691 nm_ip4_config_add_dns_option (dst, nm_ip4_config_get_dns_option (src, i));
695 if (nm_ip4_config_get_mss (src))
696 nm_ip4_config_set_mss (dst, nm_ip4_config_get_mss (src));
699 if (nm_ip4_config_get_mtu (src))
700 nm_ip4_config_set_mtu (dst, nm_ip4_config_get_mtu (src),
701 nm_ip4_config_get_mtu_source (src));
704 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
705 for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++)
706 nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i));
708 if (nm_ip4_config_get_nis_domain (src))
709 nm_ip4_config_set_nis_domain (dst, nm_ip4_config_get_nis_domain (src));
713 if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
714 for (i = 0; i < nm_ip4_config_get_num_wins (src); i++)
715 nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
719 nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) ||
720 nm_ip4_config_get_metered (src));
722 g_object_thaw_notify (G_OBJECT (dst));
725 /*******************************************************************************/
728 _addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr)
730 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
733 for (i = 0; i < priv->addresses->len; i++) {
734 const NMPlatformIP4Address *a = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
736 if (addresses_are_duplicate (addr, a))
743 _nameservers_get_index (const NMIP4Config *self, guint32 ns)
745 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
748 for (i = 0; i < priv->nameservers->len; i++) {
749 guint32 n = g_array_index (priv->nameservers, guint32, i);
758 _routes_get_index (const NMIP4Config *self, const NMPlatformIP4Route *route)
760 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
763 for (i = 0; i < priv->routes->len; i++) {
764 const NMPlatformIP4Route *r = &g_array_index (priv->routes, NMPlatformIP4Route, i);
766 if ( route->network == r->network
767 && route->plen == r->plen)
774 _domains_get_index (const NMIP4Config *self, const char *domain)
776 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
779 for (i = 0; i < priv->domains->len; i++) {
780 const char *d = g_ptr_array_index (priv->domains, i);
782 if (g_strcmp0 (domain, d) == 0)
789 _searches_get_index (const NMIP4Config *self, const char *search)
791 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
794 for (i = 0; i < priv->searches->len; i++) {
795 const char *s = g_ptr_array_index (priv->searches, i);
797 if (g_strcmp0 (search, s) == 0)
804 _dns_options_get_index (const NMIP4Config *self, const char *option)
806 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
809 for (i = 0; i < priv->dns_options->len; i++) {
810 const char *s = g_ptr_array_index (priv->dns_options, i);
812 if (g_strcmp0 (option, s) == 0)
819 _nis_servers_get_index (const NMIP4Config *self, guint32 nis_server)
821 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
824 for (i = 0; i < priv->nis->len; i++) {
825 guint32 n = g_array_index (priv->nis, guint32, i);
834 _wins_get_index (const NMIP4Config *self, guint32 wins_server)
836 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
839 for (i = 0; i < priv->wins->len; i++) {
840 guint32 n = g_array_index (priv->wins, guint32, i);
842 if (n == wins_server)
848 /*******************************************************************************/
851 * nm_ip4_config_subtract:
852 * @dst: config from which to remove everything in @src
853 * @src: config to remove from @dst
855 * Removes everything in @src from @dst.
858 nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
863 g_return_if_fail (src != NULL);
864 g_return_if_fail (dst != NULL);
866 g_object_freeze_notify (G_OBJECT (dst));
869 for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) {
870 idx = _addresses_get_index (dst, nm_ip4_config_get_address (src, i));
872 nm_ip4_config_del_address (dst, idx);
876 for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
877 idx = _nameservers_get_index (dst, nm_ip4_config_get_nameserver (src, i));
879 nm_ip4_config_del_nameserver (dst, idx);
882 /* default gateway */
883 if ( (nm_ip4_config_has_gateway (src) == nm_ip4_config_has_gateway (dst))
884 && (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst)))
885 nm_ip4_config_unset_gateway (dst);
887 if (!nm_ip4_config_get_num_addresses (dst))
888 nm_ip4_config_unset_gateway (dst);
890 /* ignore route_metric */
893 for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) {
894 idx = _routes_get_index (dst, nm_ip4_config_get_route (src, i));
896 nm_ip4_config_del_route (dst, idx);
900 for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) {
901 idx = _domains_get_index (dst, nm_ip4_config_get_domain (src, i));
903 nm_ip4_config_del_domain (dst, idx);
907 for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) {
908 idx = _searches_get_index (dst, nm_ip4_config_get_search (src, i));
910 nm_ip4_config_del_search (dst, idx);
914 for (i = 0; i < nm_ip4_config_get_num_dns_options (src); i++) {
915 idx = _dns_options_get_index (dst, nm_ip4_config_get_dns_option (src, i));
917 nm_ip4_config_del_dns_option (dst, idx);
921 if (nm_ip4_config_get_mss (src) == nm_ip4_config_get_mss (dst))
922 nm_ip4_config_set_mss (dst, 0);
925 if (nm_ip4_config_get_mtu (src) == nm_ip4_config_get_mtu (dst))
926 nm_ip4_config_set_mtu (dst, 0, NM_IP_CONFIG_SOURCE_UNKNOWN);
929 for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) {
930 idx = _nis_servers_get_index (dst, nm_ip4_config_get_nis_server (src, i));
932 nm_ip4_config_del_nis_server (dst, idx);
935 if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0)
936 nm_ip4_config_set_nis_domain (dst, NULL);
939 for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) {
940 idx = _wins_get_index (dst, nm_ip4_config_get_wins (src, i));
942 nm_ip4_config_del_wins (dst, idx);
945 g_object_thaw_notify (G_OBJECT (dst));
949 nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src)
954 g_return_if_fail (src != NULL);
955 g_return_if_fail (dst != NULL);
957 g_object_freeze_notify (G_OBJECT (dst));
960 for (i = 0; i < nm_ip4_config_get_num_addresses (dst); ) {
961 idx = _addresses_get_index (src, nm_ip4_config_get_address (dst, i));
963 nm_ip4_config_del_address (dst, i);
968 /* ignore route_metric */
969 /* ignore nameservers */
971 /* default gateway */
972 if ( !nm_ip4_config_get_num_addresses (dst)
973 || (nm_ip4_config_has_gateway (src) != nm_ip4_config_has_gateway (dst))
974 || (nm_ip4_config_get_gateway (src) != nm_ip4_config_get_gateway (dst))) {
975 nm_ip4_config_unset_gateway (dst);
979 for (i = 0; i < nm_ip4_config_get_num_routes (dst); ) {
980 idx = _routes_get_index (src, nm_ip4_config_get_route (dst, i));
982 nm_ip4_config_del_route (dst, i);
988 /* ignore dns searches */
989 /* ignore dns options */
993 g_object_thaw_notify (G_OBJECT (dst));
998 * nm_ip4_config_replace:
999 * @dst: config to replace with @src content
1000 * @src: source config to copy
1001 * @relevant_changes: return whether there are changes to the
1002 * destination object that are relevant. This is equal to
1003 * nm_ip4_config_equal() showing any difference.
1005 * Replaces everything in @dst with @src so that the two configurations
1006 * contain the same content -- with the exception of the dbus path.
1008 * Returns: whether the @dst instance changed in any way (including minor changes,
1009 * that are not signaled by the output parameter @relevant_changes).
1012 nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes)
1015 gboolean config_equal;
1017 gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
1019 NMIP4ConfigPrivate *dst_priv, *src_priv;
1020 const NMPlatformIP4Address *dst_addr, *src_addr;
1021 const NMPlatformIP4Route *dst_route, *src_route;
1023 g_return_val_if_fail (src != NULL, FALSE);
1024 g_return_val_if_fail (dst != NULL, FALSE);
1025 g_return_val_if_fail (src != dst, FALSE);
1028 config_equal = nm_ip4_config_equal (dst, src);
1031 dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
1032 src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
1034 g_object_freeze_notify (G_OBJECT (dst));
1037 if (src_priv->ifindex != dst_priv->ifindex) {
1038 dst_priv->ifindex = src_priv->ifindex;
1039 has_minor_changes = TRUE;
1043 if (src_priv->never_default != dst_priv->never_default) {
1044 dst_priv->never_default = src_priv->never_default;
1045 has_minor_changes = TRUE;
1048 /* default gateway */
1049 if ( src_priv->gateway != dst_priv->gateway
1050 || src_priv->has_gateway != dst_priv->has_gateway) {
1051 if (src_priv->has_gateway)
1052 nm_ip4_config_set_gateway (dst, src_priv->gateway);
1054 nm_ip4_config_unset_gateway (dst);
1055 has_relevant_changes = TRUE;
1058 if (src_priv->route_metric != dst_priv->route_metric) {
1059 dst_priv->route_metric = src_priv->route_metric;
1060 has_minor_changes = TRUE;
1064 num = nm_ip4_config_get_num_addresses (src);
1065 are_equal = num == nm_ip4_config_get_num_addresses (dst);
1067 for (i = 0; i < num; i++ ) {
1068 if (nm_platform_ip4_address_cmp (src_addr = nm_ip4_config_get_address (src, i),
1069 dst_addr = nm_ip4_config_get_address (dst, i))) {
1071 if ( !addresses_are_duplicate (src_addr, dst_addr)
1072 || src_addr->peer_address != dst_addr->peer_address) {
1073 has_relevant_changes = TRUE;
1079 has_relevant_changes = TRUE;
1081 nm_ip4_config_reset_addresses (dst);
1082 for (i = 0; i < num; i++)
1083 nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i));
1084 has_minor_changes = TRUE;
1088 num = nm_ip4_config_get_num_routes (src);
1089 are_equal = num == nm_ip4_config_get_num_routes (dst);
1091 for (i = 0; i < num; i++ ) {
1092 if (nm_platform_ip4_route_cmp (src_route = nm_ip4_config_get_route (src, i),
1093 dst_route = nm_ip4_config_get_route (dst, i))) {
1095 if (!routes_are_duplicate (src_route, dst_route, TRUE)) {
1096 has_relevant_changes = TRUE;
1102 has_relevant_changes = TRUE;
1104 nm_ip4_config_reset_routes (dst);
1105 for (i = 0; i < num; i++)
1106 nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i));
1107 has_minor_changes = TRUE;
1111 num = nm_ip4_config_get_num_nameservers (src);
1112 are_equal = num == nm_ip4_config_get_num_nameservers (dst);
1114 for (i = 0; i < num; i++ ) {
1115 if (nm_ip4_config_get_nameserver (src, i) != nm_ip4_config_get_nameserver (dst, i)) {
1122 nm_ip4_config_reset_nameservers (dst);
1123 for (i = 0; i < num; i++)
1124 nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
1125 has_relevant_changes = TRUE;
1129 num = nm_ip4_config_get_num_domains (src);
1130 are_equal = num == nm_ip4_config_get_num_domains (dst);
1132 for (i = 0; i < num; i++ ) {
1133 if (g_strcmp0 (nm_ip4_config_get_domain (src, i),
1134 nm_ip4_config_get_domain (dst, i))) {
1141 nm_ip4_config_reset_domains (dst);
1142 for (i = 0; i < num; i++)
1143 nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
1144 has_relevant_changes = TRUE;
1148 num = nm_ip4_config_get_num_searches (src);
1149 are_equal = num == nm_ip4_config_get_num_searches (dst);
1151 for (i = 0; i < num; i++ ) {
1152 if (g_strcmp0 (nm_ip4_config_get_search (src, i),
1153 nm_ip4_config_get_search (dst, i))) {
1160 nm_ip4_config_reset_searches (dst);
1161 for (i = 0; i < num; i++)
1162 nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
1163 has_relevant_changes = TRUE;
1167 num = nm_ip4_config_get_num_dns_options (src);
1168 are_equal = num == nm_ip4_config_get_num_dns_options (dst);
1170 for (i = 0; i < num; i++ ) {
1171 if (g_strcmp0 (nm_ip4_config_get_dns_option (src, i),
1172 nm_ip4_config_get_dns_option (dst, i))) {
1179 nm_ip4_config_reset_dns_options (dst);
1180 for (i = 0; i < num; i++)
1181 nm_ip4_config_add_dns_option (dst, nm_ip4_config_get_dns_option (src, i));
1182 has_relevant_changes = TRUE;
1186 if (src_priv->mss != dst_priv->mss) {
1187 nm_ip4_config_set_mss (dst, src_priv->mss);
1188 has_minor_changes = TRUE;
1192 num = nm_ip4_config_get_num_nis_servers (src);
1193 are_equal = num == nm_ip4_config_get_num_nis_servers (dst);
1195 for (i = 0; i < num; i++ ) {
1196 if (nm_ip4_config_get_nis_server (src, i) != nm_ip4_config_get_nis_server (dst, i)) {
1203 nm_ip4_config_reset_nis_servers (dst);
1204 for (i = 0; i < num; i++)
1205 nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i));
1206 has_relevant_changes = TRUE;
1210 if (g_strcmp0 (src_priv->nis_domain, dst_priv->nis_domain)) {
1211 nm_ip4_config_set_nis_domain (dst, src_priv->nis_domain);
1212 has_relevant_changes = TRUE;
1216 num = nm_ip4_config_get_num_wins (src);
1217 are_equal = num == nm_ip4_config_get_num_wins (dst);
1219 for (i = 0; i < num; i++ ) {
1220 if (nm_ip4_config_get_wins (src, i) != nm_ip4_config_get_wins (dst, i)) {
1227 nm_ip4_config_reset_wins (dst);
1228 for (i = 0; i < num; i++)
1229 nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
1230 has_relevant_changes = TRUE;
1234 if (src_priv->mtu != dst_priv->mtu) {
1235 nm_ip4_config_set_mtu (dst, src_priv->mtu, src_priv->mtu_source);
1236 has_minor_changes = TRUE;
1240 if (src_priv->metered != dst_priv->metered) {
1241 dst_priv->metered = src_priv->metered;
1242 has_minor_changes = TRUE;
1246 /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
1247 * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
1248 nm_assert (config_equal == !has_relevant_changes);
1251 g_object_thaw_notify (G_OBJECT (dst));
1253 if (relevant_changes)
1254 *relevant_changes = has_relevant_changes;
1256 return has_relevant_changes || has_minor_changes;
1260 nm_ip4_config_dump (const NMIP4Config *config, const char *detail)
1265 g_message ("--------- NMIP4Config %p (%s)", config, detail);
1267 if (config == NULL) {
1268 g_message (" (null)");
1272 str = nm_exported_object_get_path (NM_EXPORTED_OBJECT (config));
1274 g_message (" path: %s", str);
1277 for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++)
1278 g_message (" a: %s", nm_platform_ip4_address_to_string (nm_ip4_config_get_address (config, i), NULL, 0));
1280 /* default gateway */
1281 if (nm_ip4_config_has_gateway (config)) {
1282 tmp = nm_ip4_config_get_gateway (config);
1283 g_message (" gw: %s", nm_utils_inet4_ntop (tmp, NULL));
1287 for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++) {
1288 tmp = nm_ip4_config_get_nameserver (config, i);
1289 g_message (" ns: %s", nm_utils_inet4_ntop (tmp, NULL));
1293 for (i = 0; i < nm_ip4_config_get_num_routes (config); i++)
1294 g_message (" rt: %s", nm_platform_ip4_route_to_string (nm_ip4_config_get_route (config, i), NULL, 0));
1297 for (i = 0; i < nm_ip4_config_get_num_domains (config); i++)
1298 g_message (" domain: %s", nm_ip4_config_get_domain (config, i));
1301 for (i = 0; i < nm_ip4_config_get_num_searches (config); i++)
1302 g_message (" search: %s", nm_ip4_config_get_search (config, i));
1305 for (i = 0; i < nm_ip4_config_get_num_dns_options (config); i++)
1306 g_message (" dnsopt: %s", nm_ip4_config_get_dns_option (config, i));
1309 g_message (" mss: %"G_GUINT32_FORMAT, nm_ip4_config_get_mss (config));
1310 g_message (" mtu: %"G_GUINT32_FORMAT, nm_ip4_config_get_mtu (config));
1313 for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++) {
1314 tmp = nm_ip4_config_get_nis_server (config, i);
1315 g_message (" nis: %s", nm_utils_inet4_ntop (tmp, NULL));
1318 g_message (" nisdmn: %s", nm_ip4_config_get_nis_domain (config) ?: "(none)");
1321 for (i = 0; i < nm_ip4_config_get_num_wins (config); i++) {
1322 tmp = nm_ip4_config_get_wins (config, i);
1323 g_message (" wins: %s", nm_utils_inet4_ntop (tmp, NULL));
1326 g_message (" n-dflt: %d", nm_ip4_config_get_never_default (config));
1327 g_message (" mtrd: %d", (int) nm_ip4_config_get_metered (config));
1331 nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, int plen)
1333 guint naddresses = nm_ip4_config_get_num_addresses (config);
1335 in_addr_t peer_network;
1337 for (i = 0; i < naddresses; i++) {
1338 const NMPlatformIP4Address *item = nm_ip4_config_get_address (config, i);
1340 if (item->plen > plen)
1343 peer_network = nm_utils_ip4_address_clear_host_address (item->peer_address, item->plen);
1344 if (_ipv4_is_zeronet (peer_network))
1347 if (peer_network != nm_utils_ip4_address_clear_host_address (network, item->plen))
1356 /******************************************************************/
1359 nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default)
1361 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1363 priv->never_default = !!never_default;
1367 nm_ip4_config_get_never_default (const NMIP4Config *config)
1369 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1371 return priv->never_default;
1375 nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway)
1377 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1379 if (priv->gateway != gateway || !priv->has_gateway) {
1380 priv->gateway = gateway;
1381 priv->has_gateway = TRUE;
1382 _notify (config, PROP_GATEWAY);
1387 nm_ip4_config_unset_gateway (NMIP4Config *config)
1389 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1391 if (priv->has_gateway) {
1393 priv->has_gateway = FALSE;
1394 _notify (config, PROP_GATEWAY);
1399 * nm_ip4_config_has_gateway:
1400 * @config: the #NMIP4Config object
1402 * NetworkManager's handling of default-routes is limited and usually a default-route
1403 * cannot have gateway 0.0.0.0. For peer-to-peer routes, we still want to
1404 * support that, so we need to differenciate between no-default-route and a
1405 * on-link-default route. Hence nm_ip4_config_has_gateway().
1407 * Returns: whether the object has a gateway explicitly set. */
1409 nm_ip4_config_has_gateway (const NMIP4Config *config)
1411 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1413 return priv->has_gateway;
1417 nm_ip4_config_get_gateway (const NMIP4Config *config)
1419 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1421 return priv->gateway;
1425 nm_ip4_config_get_route_metric (const NMIP4Config *config)
1427 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1429 return priv->route_metric;
1432 /******************************************************************/
1435 nm_ip4_config_reset_addresses (NMIP4Config *config)
1437 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1439 if (priv->addresses->len != 0) {
1440 g_array_set_size (priv->addresses, 0);
1441 _notify (config, PROP_ADDRESS_DATA);
1442 _notify (config, PROP_ADDRESSES);
1447 * nm_ip4_config_add_address:
1448 * @config: the #NMIP4Config
1449 * @new: the new address to add to @config
1451 * Adds the new address to @config. If an address with the same basic properties
1452 * (address, prefix) already exists in @config, it is overwritten with the
1453 * lifetime and preferred of @new. The source is also overwritten by the source
1454 * from @new if that source is higher priority.
1457 nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
1459 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1460 NMPlatformIP4Address item_old;
1463 g_return_if_fail (new != NULL);
1465 for (i = 0; i < priv->addresses->len; i++ ) {
1466 NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
1468 if (addresses_are_duplicate (item, new)) {
1469 if (nm_platform_ip4_address_cmp (item, new) == 0)
1472 /* remember the old values. */
1474 /* Copy over old item to get new lifetime, timestamp, preferred */
1477 /* But restore highest priority source */
1478 item->source = MAX (item_old.source, new->source);
1480 /* for addresses that we read from the kernel, we keep the timestamps as defined
1481 * by the previous source (item_old). The reason is, that the other source configured the lifetimes
1482 * with "what should be" and the kernel values are "what turned out after configuring it".
1484 * For other sources, the longer lifetime wins. */
1485 if ( (new->source == NM_IP_CONFIG_SOURCE_KERNEL && new->source != item_old.source)
1486 || nm_platform_ip_address_cmp_expiry ((const NMPlatformIPAddress *) &item_old, (const NMPlatformIPAddress *) new) > 0) {
1487 item->timestamp = item_old.timestamp;
1488 item->lifetime = item_old.lifetime;
1489 item->preferred = item_old.preferred;
1491 if (nm_platform_ip4_address_cmp (&item_old, item) == 0)
1497 g_array_append_val (priv->addresses, *new);
1499 _notify (config, PROP_ADDRESS_DATA);
1500 _notify (config, PROP_ADDRESSES);
1504 nm_ip4_config_del_address (NMIP4Config *config, guint i)
1506 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1508 g_return_if_fail (i < priv->addresses->len);
1510 g_array_remove_index (priv->addresses, i);
1511 _notify (config, PROP_ADDRESS_DATA);
1512 _notify (config, PROP_ADDRESSES);
1516 nm_ip4_config_get_num_addresses (const NMIP4Config *config)
1518 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1520 return priv->addresses->len;
1523 const NMPlatformIP4Address *
1524 nm_ip4_config_get_address (const NMIP4Config *config, guint i)
1526 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1528 return &g_array_index (priv->addresses, NMPlatformIP4Address, i);
1532 nm_ip4_config_address_exists (const NMIP4Config *config,
1533 const NMPlatformIP4Address *needle)
1535 return _addresses_get_index (config, needle) >= 0;
1538 /******************************************************************/
1541 nm_ip4_config_reset_routes (NMIP4Config *config)
1543 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1545 if (priv->routes->len != 0) {
1546 g_array_set_size (priv->routes, 0);
1547 _notify (config, PROP_ROUTE_DATA);
1548 _notify (config, PROP_ROUTES);
1553 * nm_ip4_config_add_route:
1554 * @config: the #NMIP4Config
1555 * @new: the new route to add to @config
1557 * Adds the new route to @config. If a route with the same basic properties
1558 * (network, prefix) already exists in @config, it is overwritten including the
1559 * gateway and metric of @new. The source is also overwritten by the source
1560 * from @new if that source is higher priority.
1563 nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
1565 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1566 NMIPConfigSource old_source;
1569 g_return_if_fail (new != NULL);
1570 g_return_if_fail (new->plen > 0);
1571 g_assert (priv->ifindex);
1573 for (i = 0; i < priv->routes->len; i++ ) {
1574 NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i);
1576 if (routes_are_duplicate (item, new, FALSE)) {
1577 if (nm_platform_ip4_route_cmp (item, new) == 0)
1579 old_source = item->source;
1580 memcpy (item, new, sizeof (*item));
1581 /* Restore highest priority source */
1582 item->source = MAX (old_source, new->source);
1583 item->ifindex = priv->ifindex;
1588 g_array_append_val (priv->routes, *new);
1589 g_array_index (priv->routes, NMPlatformIP4Route, priv->routes->len - 1).ifindex = priv->ifindex;
1591 _notify (config, PROP_ROUTE_DATA);
1592 _notify (config, PROP_ROUTES);
1596 nm_ip4_config_del_route (NMIP4Config *config, guint i)
1598 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1600 g_return_if_fail (i < priv->routes->len);
1602 g_array_remove_index (priv->routes, i);
1603 _notify (config, PROP_ROUTE_DATA);
1604 _notify (config, PROP_ROUTES);
1608 nm_ip4_config_get_num_routes (const NMIP4Config *config)
1610 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1612 return priv->routes->len;
1615 const NMPlatformIP4Route *
1616 nm_ip4_config_get_route (const NMIP4Config *config, guint i)
1618 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1620 return &g_array_index (priv->routes, NMPlatformIP4Route, i);
1623 const NMPlatformIP4Route *
1624 nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host)
1626 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1628 NMPlatformIP4Route *best_route = NULL;
1630 g_return_val_if_fail (host, NULL);
1632 for (i = 0; i < priv->routes->len; i++) {
1633 NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i);
1635 if (item->gateway != 0)
1638 if (best_route && best_route->plen > item->plen)
1641 if (nm_utils_ip4_address_clear_host_address (host, item->plen) != nm_utils_ip4_address_clear_host_address (item->network, item->plen))
1644 if (best_route && best_route->metric <= item->metric)
1653 /******************************************************************/
1656 nm_ip4_config_reset_nameservers (NMIP4Config *config)
1658 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1660 if (priv->nameservers->len != 0) {
1661 g_array_set_size (priv->nameservers, 0);
1662 _notify (config, PROP_NAMESERVERS);
1667 nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 new)
1669 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1672 g_return_if_fail (new != 0);
1674 for (i = 0; i < priv->nameservers->len; i++)
1675 if (new == g_array_index (priv->nameservers, guint32, i))
1678 g_array_append_val (priv->nameservers, new);
1679 _notify (config, PROP_NAMESERVERS);
1683 nm_ip4_config_del_nameserver (NMIP4Config *config, guint i)
1685 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1687 g_return_if_fail (i < priv->nameservers->len);
1689 g_array_remove_index (priv->nameservers, i);
1690 _notify (config, PROP_NAMESERVERS);
1694 nm_ip4_config_get_num_nameservers (const NMIP4Config *config)
1696 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1698 return priv->nameservers->len;
1702 nm_ip4_config_get_nameserver (const NMIP4Config *config, guint i)
1704 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1706 return g_array_index (priv->nameservers, guint32, i);
1709 /******************************************************************/
1712 nm_ip4_config_reset_domains (NMIP4Config *config)
1714 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1716 if (priv->domains->len != 0) {
1717 g_ptr_array_set_size (priv->domains, 0);
1718 _notify (config, PROP_DOMAINS);
1723 nm_ip4_config_add_domain (NMIP4Config *config, const char *domain)
1725 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1728 g_return_if_fail (domain != NULL);
1729 g_return_if_fail (domain[0] != '\0');
1731 for (i = 0; i < priv->domains->len; i++)
1732 if (!g_strcmp0 (g_ptr_array_index (priv->domains, i), domain))
1735 g_ptr_array_add (priv->domains, g_strdup (domain));
1736 _notify (config, PROP_DOMAINS);
1740 nm_ip4_config_del_domain (NMIP4Config *config, guint i)
1742 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1744 g_return_if_fail (i < priv->domains->len);
1746 g_ptr_array_remove_index (priv->domains, i);
1747 _notify (config, PROP_DOMAINS);
1751 nm_ip4_config_get_num_domains (const NMIP4Config *config)
1753 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1755 return priv->domains->len;
1759 nm_ip4_config_get_domain (const NMIP4Config *config, guint i)
1761 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1763 return g_ptr_array_index (priv->domains, i);
1766 /******************************************************************/
1769 nm_ip4_config_reset_searches (NMIP4Config *config)
1771 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1773 if (priv->searches->len != 0) {
1774 g_ptr_array_set_size (priv->searches, 0);
1775 _notify (config, PROP_SEARCHES);
1780 nm_ip4_config_add_search (NMIP4Config *config, const char *new)
1782 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1786 g_return_if_fail (new != NULL);
1787 g_return_if_fail (new[0] != '\0');
1789 search = g_strdup (new);
1791 /* Remove trailing dot as it has no effect */
1792 len = strlen (search);
1793 if (search[len - 1] == '.')
1794 search[len - 1] = 0;
1801 if (_nm_utils_strv_find_first ((char **) priv->searches->pdata,
1802 priv->searches->len, search) >= 0) {
1807 g_ptr_array_add (priv->searches, search);
1808 _notify (config, PROP_SEARCHES);
1812 nm_ip4_config_del_search (NMIP4Config *config, guint i)
1814 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1816 g_return_if_fail (i < priv->searches->len);
1818 g_ptr_array_remove_index (priv->searches, i);
1819 _notify (config, PROP_SEARCHES);
1823 nm_ip4_config_get_num_searches (const NMIP4Config *config)
1825 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1827 return priv->searches->len;
1831 nm_ip4_config_get_search (const NMIP4Config *config, guint i)
1833 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1835 return g_ptr_array_index (priv->searches, i);
1838 /******************************************************************/
1841 nm_ip4_config_reset_dns_options (NMIP4Config *config)
1843 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1845 if (priv->dns_options->len != 0) {
1846 g_ptr_array_set_size (priv->dns_options, 0);
1847 _notify (config, PROP_DNS_OPTIONS);
1852 nm_ip4_config_add_dns_option (NMIP4Config *config, const char *new)
1854 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1857 g_return_if_fail (new != NULL);
1858 g_return_if_fail (new[0] != '\0');
1860 for (i = 0; i < priv->dns_options->len; i++)
1861 if (!g_strcmp0 (g_ptr_array_index (priv->dns_options, i), new))
1864 g_ptr_array_add (priv->dns_options, g_strdup (new));
1865 _notify (config, PROP_DNS_OPTIONS);
1869 nm_ip4_config_del_dns_option(NMIP4Config *config, guint i)
1871 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1873 g_return_if_fail (i < priv->dns_options->len);
1875 g_ptr_array_remove_index (priv->dns_options, i);
1876 _notify (config, PROP_DNS_OPTIONS);
1880 nm_ip4_config_get_num_dns_options (const NMIP4Config *config)
1882 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1884 return priv->dns_options->len;
1888 nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i)
1890 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1892 return g_ptr_array_index (priv->dns_options, i);
1895 /******************************************************************/
1898 nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss)
1900 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1906 nm_ip4_config_get_mss (const NMIP4Config *config)
1908 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1913 /******************************************************************/
1916 nm_ip4_config_reset_nis_servers (NMIP4Config *config)
1918 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1920 g_array_set_size (priv->nis, 0);
1924 nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis)
1926 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1929 for (i = 0; i < priv->nis->len; i++)
1930 if (nis == g_array_index (priv->nis, guint32, i))
1933 g_array_append_val (priv->nis, nis);
1937 nm_ip4_config_del_nis_server (NMIP4Config *config, guint i)
1939 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1941 g_return_if_fail (i < priv->nis->len);
1943 g_array_remove_index (priv->nis, i);
1947 nm_ip4_config_get_num_nis_servers (const NMIP4Config *config)
1949 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1951 return priv->nis->len;
1955 nm_ip4_config_get_nis_server (const NMIP4Config *config, guint i)
1957 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1959 return g_array_index (priv->nis, guint32, i);
1963 nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain)
1965 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1967 g_free (priv->nis_domain);
1968 priv->nis_domain = g_strdup (domain);
1972 nm_ip4_config_get_nis_domain (const NMIP4Config *config)
1974 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1976 return priv->nis_domain;
1979 /******************************************************************/
1982 nm_ip4_config_reset_wins (NMIP4Config *config)
1984 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1986 if (priv->wins->len != 0) {
1987 g_array_set_size (priv->wins, 0);
1988 _notify (config, PROP_WINS_SERVERS);
1993 nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins)
1995 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
1998 g_return_if_fail (wins != 0);
2000 for (i = 0; i < priv->wins->len; i++)
2001 if (wins == g_array_index (priv->wins, guint32, i))
2004 g_array_append_val (priv->wins, wins);
2005 _notify (config, PROP_WINS_SERVERS);
2009 nm_ip4_config_del_wins (NMIP4Config *config, guint i)
2011 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2013 g_return_if_fail (i < priv->wins->len);
2015 g_array_remove_index (priv->wins, i);
2016 _notify (config, PROP_WINS_SERVERS);
2020 nm_ip4_config_get_num_wins (const NMIP4Config *config)
2022 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2024 return priv->wins->len;
2028 nm_ip4_config_get_wins (const NMIP4Config *config, guint i)
2030 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2032 return g_array_index (priv->wins, guint32, i);
2035 /******************************************************************/
2038 nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu, NMIPConfigSource source)
2040 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2042 if (source > priv->mtu_source) {
2044 priv->mtu_source = source;
2045 } else if (source == priv->mtu_source && (!priv->mtu || priv->mtu > mtu))
2050 nm_ip4_config_get_mtu (const NMIP4Config *config)
2052 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2058 nm_ip4_config_get_mtu_source (const NMIP4Config *config)
2060 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2062 return priv->mtu_source;
2065 /******************************************************************/
2068 nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered)
2070 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2072 priv->metered = !!metered;
2076 nm_ip4_config_get_metered (const NMIP4Config *config)
2078 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2080 return priv->metered;
2083 /******************************************************************/
2086 hash_u32 (GChecksum *sum, guint32 n)
2088 g_checksum_update (sum, (const guint8 *) &n, sizeof (n));
2092 nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only)
2097 g_return_if_fail (config);
2098 g_return_if_fail (sum);
2101 hash_u32 (sum, nm_ip4_config_has_gateway (config));
2102 hash_u32 (sum, nm_ip4_config_get_gateway (config));
2104 for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) {
2105 const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
2106 hash_u32 (sum, address->address);
2107 hash_u32 (sum, address->plen);
2108 hash_u32 (sum, address->peer_address & nm_utils_ip4_prefix_to_netmask (address->plen));
2111 for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
2112 const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
2114 hash_u32 (sum, route->network);
2115 hash_u32 (sum, route->plen);
2116 hash_u32 (sum, route->gateway);
2117 hash_u32 (sum, route->metric);
2120 for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++)
2121 hash_u32 (sum, nm_ip4_config_get_nis_server (config, i));
2123 s = nm_ip4_config_get_nis_domain (config);
2125 g_checksum_update (sum, (const guint8 *) s, strlen (s));
2128 for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++)
2129 hash_u32 (sum, nm_ip4_config_get_nameserver (config, i));
2131 for (i = 0; i < nm_ip4_config_get_num_wins (config); i++)
2132 hash_u32 (sum, nm_ip4_config_get_wins (config, i));
2134 for (i = 0; i < nm_ip4_config_get_num_domains (config); i++) {
2135 s = nm_ip4_config_get_domain (config, i);
2136 g_checksum_update (sum, (const guint8 *) s, strlen (s));
2139 for (i = 0; i < nm_ip4_config_get_num_searches (config); i++) {
2140 s = nm_ip4_config_get_search (config, i);
2141 g_checksum_update (sum, (const guint8 *) s, strlen (s));
2144 for (i = 0; i < nm_ip4_config_get_num_dns_options (config); i++) {
2145 s = nm_ip4_config_get_dns_option (config, i);
2146 g_checksum_update (sum, (const guint8 *) s, strlen (s));
2152 * nm_ip4_config_equal:
2153 * @a: first config to compare
2154 * @b: second config to compare
2156 * Compares two #NMIP4Configs for basic equality. This means that all
2157 * attributes must exist in the same order in both configs (addresses, routes,
2158 * domains, DNS servers, etc) but some attributes (address lifetimes, and address
2159 * and route sources) are ignored.
2161 * Returns: %TRUE if the configurations are basically equal to each other,
2165 nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b)
2167 GChecksum *a_checksum = g_checksum_new (G_CHECKSUM_SHA1);
2168 GChecksum *b_checksum = g_checksum_new (G_CHECKSUM_SHA1);
2169 gsize a_len = g_checksum_type_get_length (G_CHECKSUM_SHA1);
2170 gsize b_len = g_checksum_type_get_length (G_CHECKSUM_SHA1);
2171 guchar a_data[a_len], b_data[b_len];
2175 nm_ip4_config_hash (a, a_checksum, FALSE);
2177 nm_ip4_config_hash (b, b_checksum, FALSE);
2179 g_checksum_get_digest (a_checksum, a_data, &a_len);
2180 g_checksum_get_digest (b_checksum, b_data, &b_len);
2182 g_assert (a_len == b_len);
2183 equal = !memcmp (a_data, b_data, a_len);
2185 g_checksum_free (a_checksum);
2186 g_checksum_free (b_checksum);
2191 /******************************************************************/
2194 nm_ip4_config_init (NMIP4Config *config)
2196 NMIP4ConfigPrivate *priv;
2198 priv = G_TYPE_INSTANCE_GET_PRIVATE (config, NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate);
2199 config->priv = priv;
2201 priv->addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Address));
2202 priv->routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
2203 priv->nameservers = g_array_new (FALSE, FALSE, sizeof (guint32));
2204 priv->domains = g_ptr_array_new_with_free_func (g_free);
2205 priv->searches = g_ptr_array_new_with_free_func (g_free);
2206 priv->dns_options = g_ptr_array_new_with_free_func (g_free);
2207 priv->nis = g_array_new (FALSE, TRUE, sizeof (guint32));
2208 priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32));
2209 priv->route_metric = -1;
2213 finalize (GObject *object)
2215 NMIP4Config *self = NM_IP4_CONFIG (object);
2216 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
2218 g_array_unref (priv->addresses);
2219 g_array_unref (priv->routes);
2220 g_array_unref (priv->nameservers);
2221 g_ptr_array_unref (priv->domains);
2222 g_ptr_array_unref (priv->searches);
2223 g_ptr_array_unref (priv->dns_options);
2224 g_array_unref (priv->nis);
2225 g_free (priv->nis_domain);
2226 g_array_unref (priv->wins);
2228 G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object);
2232 get_property (GObject *object, guint prop_id,
2233 GValue *value, GParamSpec *pspec)
2235 NMIP4Config *config = NM_IP4_CONFIG (object);
2236 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
2240 g_value_set_int (value, priv->ifindex);
2242 case PROP_ADDRESS_DATA:
2244 GVariantBuilder array_builder, addr_builder;
2245 int naddr = nm_ip4_config_get_num_addresses (config);
2248 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
2249 for (i = 0; i < naddr; i++) {
2250 const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
2252 g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
2253 g_variant_builder_add (&addr_builder, "{sv}",
2255 g_variant_new_string (nm_utils_inet4_ntop (address->address, NULL)));
2256 g_variant_builder_add (&addr_builder, "{sv}",
2258 g_variant_new_uint32 (address->plen));
2259 if (address->peer_address != address->address) {
2260 g_variant_builder_add (&addr_builder, "{sv}",
2262 g_variant_new_string (nm_utils_inet4_ntop (address->peer_address, NULL)));
2265 if (*address->label) {
2266 g_variant_builder_add (&addr_builder, "{sv}",
2268 g_variant_new_string (address->label));
2271 g_variant_builder_add (&array_builder, "a{sv}", &addr_builder);
2274 g_value_take_variant (value, g_variant_builder_end (&array_builder));
2277 case PROP_ADDRESSES:
2279 GVariantBuilder array_builder;
2280 int naddr = nm_ip4_config_get_num_addresses (config);
2283 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau"));
2284 for (i = 0; i < naddr; i++) {
2285 const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
2286 guint32 dbus_addr[3];
2288 dbus_addr[0] = address->address;
2289 dbus_addr[1] = address->plen;
2290 dbus_addr[2] = i == 0 ? priv->gateway : 0;
2292 g_variant_builder_add (&array_builder, "@au",
2293 g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
2294 dbus_addr, 3, sizeof (guint32)));
2297 g_value_take_variant (value, g_variant_builder_end (&array_builder));
2300 case PROP_ROUTE_DATA:
2302 GVariantBuilder array_builder, route_builder;
2303 guint nroutes = nm_ip4_config_get_num_routes (config);
2306 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
2307 for (i = 0; i < nroutes; i++) {
2308 const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
2310 g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
2311 g_variant_builder_add (&route_builder, "{sv}",
2313 g_variant_new_string (nm_utils_inet4_ntop (route->network, NULL)));
2314 g_variant_builder_add (&route_builder, "{sv}",
2316 g_variant_new_uint32 (route->plen));
2317 if (route->gateway) {
2318 g_variant_builder_add (&route_builder, "{sv}",
2320 g_variant_new_string (nm_utils_inet4_ntop (route->gateway, NULL)));
2322 g_variant_builder_add (&route_builder, "{sv}",
2324 g_variant_new_uint32 (route->metric));
2326 g_variant_builder_add (&array_builder, "a{sv}", &route_builder);
2329 g_value_take_variant (value, g_variant_builder_end (&array_builder));
2334 GVariantBuilder array_builder;
2335 guint nroutes = nm_ip4_config_get_num_routes (config);
2338 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau"));
2339 for (i = 0; i < nroutes; i++) {
2340 const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
2341 guint32 dbus_route[4];
2343 /* legacy versions of nm_ip4_route_set_prefix() in libnm-util assert that the
2344 * plen is positive. Skip the default routes not to break older clients. */
2345 if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
2348 dbus_route[0] = route->network;
2349 dbus_route[1] = route->plen;
2350 dbus_route[2] = route->gateway;
2351 dbus_route[3] = route->metric;
2353 g_variant_builder_add (&array_builder, "@au",
2354 g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
2355 dbus_route, 4, sizeof (guint32)));
2358 g_value_take_variant (value, g_variant_builder_end (&array_builder));
2362 if (priv->has_gateway)
2363 g_value_set_string (value, nm_utils_inet4_ntop (priv->gateway, NULL));
2365 g_value_set_string (value, NULL);
2367 case PROP_NAMESERVERS:
2368 g_value_take_variant (value,
2369 g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
2370 priv->nameservers->data,
2371 priv->nameservers->len,
2375 nm_utils_g_value_set_strv (value, priv->domains);
2378 nm_utils_g_value_set_strv (value, priv->searches);
2380 case PROP_DNS_OPTIONS:
2381 nm_utils_g_value_set_strv (value, priv->dns_options);
2383 case PROP_WINS_SERVERS:
2384 g_value_take_variant (value,
2385 g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
2391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2397 set_property (GObject *object,
2399 const GValue *value,
2402 NMIP4Config *self = NM_IP4_CONFIG (object);
2403 NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
2407 priv->ifindex = g_value_get_int (value);
2410 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2416 nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
2418 GObjectClass *object_class = G_OBJECT_CLASS (config_class);
2419 NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (config_class);
2421 g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate));
2423 exported_object_class->export_path = NM_DBUS_PATH "/IP4Config/%u";
2425 object_class->get_property = get_property;
2426 object_class->set_property = set_property;
2427 object_class->finalize = finalize;
2429 obj_properties[PROP_IFINDEX] =
2430 g_param_spec_int (NM_IP4_CONFIG_IFINDEX, "", "",
2433 G_PARAM_CONSTRUCT_ONLY |
2434 G_PARAM_STATIC_STRINGS);
2435 obj_properties[PROP_ADDRESS_DATA] =
2436 g_param_spec_variant (NM_IP4_CONFIG_ADDRESS_DATA, "", "",
2437 G_VARIANT_TYPE ("aa{sv}"),
2440 G_PARAM_STATIC_STRINGS);
2441 obj_properties[PROP_ADDRESSES] =
2442 g_param_spec_variant (NM_IP4_CONFIG_ADDRESSES, "", "",
2443 G_VARIANT_TYPE ("aau"),
2446 G_PARAM_STATIC_STRINGS);
2447 obj_properties[PROP_ROUTE_DATA] =
2448 g_param_spec_variant (NM_IP4_CONFIG_ROUTE_DATA, "", "",
2449 G_VARIANT_TYPE ("aa{sv}"),
2452 G_PARAM_STATIC_STRINGS);
2453 obj_properties[PROP_ROUTES] =
2454 g_param_spec_variant (NM_IP4_CONFIG_ROUTES, "", "",
2455 G_VARIANT_TYPE ("aau"),
2458 G_PARAM_STATIC_STRINGS);
2459 obj_properties[PROP_GATEWAY] =
2460 g_param_spec_string (NM_IP4_CONFIG_GATEWAY, "", "",
2463 G_PARAM_STATIC_STRINGS);
2464 obj_properties[PROP_NAMESERVERS] =
2465 g_param_spec_variant (NM_IP4_CONFIG_NAMESERVERS, "", "",
2466 G_VARIANT_TYPE ("au"),
2469 G_PARAM_STATIC_STRINGS);
2470 obj_properties[PROP_DOMAINS] =
2471 g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS, "", "",
2474 G_PARAM_STATIC_STRINGS);
2475 obj_properties[PROP_SEARCHES] =
2476 g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES, "", "",
2479 G_PARAM_STATIC_STRINGS);
2480 obj_properties[PROP_DNS_OPTIONS] =
2481 g_param_spec_boxed (NM_IP4_CONFIG_DNS_OPTIONS, "", "",
2484 G_PARAM_STATIC_STRINGS);
2486 obj_properties[PROP_WINS_SERVERS] =
2487 g_param_spec_variant (NM_IP4_CONFIG_WINS_SERVERS, "", "",
2488 G_VARIANT_TYPE ("au"),
2491 G_PARAM_STATIC_STRINGS);
2493 g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
2495 nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (config_class),
2496 NMDBUS_TYPE_IP4_CONFIG_SKELETON,