diff options
Diffstat (limited to 'src/nm-ip4-config.c')
| -rw-r--r-- | src/nm-ip4-config.c | 598 |
1 files changed, 397 insertions, 201 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index f625d350..78e7fb78 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -26,24 +26,22 @@ #include "nm-ip4-config.h" +#include "nm-default.h" #include "nm-utils.h" #include "nm-platform.h" -#include "nm-dbus-manager.h" -#include "nm-dbus-glib-types.h" -#include "nm-ip4-config-glue.h" #include "NetworkManagerUtils.h" #include "nm-core-internal.h" #include "nm-route-manager.h" -#include "gsystem-local-alloc.h" +#include "nm-core-internal.h" #include "nm-macros-internal.h" -G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT) +#include "nmdbus-ip4-config.h" -#define NM_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate)) +G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT) -typedef struct { - char *path; +#define NM_IP4_CONFIG_GET_PRIVATE(o) ((o)->priv) +typedef struct _NMIP4ConfigPrivate { gboolean never_default; guint32 gateway; gboolean has_gateway; @@ -52,12 +50,14 @@ typedef struct { GArray *nameservers; GPtrArray *domains; GPtrArray *searches; + GPtrArray *dns_options; guint32 mss; GArray *nis; char *nis_domain; GArray *wins; guint32 mtu; NMIPConfigSource mtu_source; + int ifindex; gint64 route_metric; gboolean metered; } NMIP4ConfigPrivate; @@ -68,6 +68,7 @@ G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF); enum { PROP_0, + PROP_IFINDEX, PROP_ADDRESS_DATA, PROP_ADDRESSES, PROP_ROUTE_DATA, @@ -76,6 +77,7 @@ enum { PROP_NAMESERVERS, PROP_DOMAINS, PROP_SEARCHES, + PROP_DNS_OPTIONS, PROP_WINS_SERVERS, LAST_PROP @@ -83,41 +85,28 @@ enum { static GParamSpec *obj_properties[LAST_PROP] = { NULL, }; #define _NOTIFY(config, prop) G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END - NMIP4Config * -nm_ip4_config_new (void) +nm_ip4_config_new (int ifindex) { - return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG, NULL); + g_return_val_if_fail (ifindex >= -1, NULL); + return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG, + NM_IP4_CONFIG_IFINDEX, ifindex, + NULL); } - -void -nm_ip4_config_export (NMIP4Config *config) +int +nm_ip4_config_get_ifindex (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - static guint32 counter = 0; - - if (!priv->path) { - priv->path = g_strdup_printf (NM_DBUS_PATH "/IP4Config/%d", counter++); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); - } + return NM_IP4_CONFIG_GET_PRIVATE (config)->ifindex; } -const char * -nm_ip4_config_get_dbus_path (const NMIP4Config *config) -{ - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - - return priv->path; -} +/******************************************************************/ static gboolean -same_prefix (guint32 address1, guint32 address2, int plen) +_ipv4_is_zeronet (in_addr_t network) { - guint32 masked1 = ntohl (address1) >> (32 - plen); - guint32 masked2 = ntohl (address2) >> (32 - plen); - - return masked1 == masked2; + /* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */ + return (network & htonl(0xff000000)) == htonl(0x00000000); } /******************************************************************/ @@ -133,9 +122,10 @@ same_prefix (guint32 address1, guint32 address2, int plen) */ gboolean nm_ip4_config_capture_resolv_conf (GArray *nameservers, + GPtrArray *dns_options, const char *rc_contents) { - GPtrArray *read_ns; + GPtrArray *read_ns, *read_options; guint i, j; gboolean changed = FALSE; @@ -163,15 +153,34 @@ nm_ip4_config_capture_resolv_conf (GArray *nameservers, changed = TRUE; } } - g_ptr_array_unref (read_ns); + + if (dns_options) { + read_options = nm_utils_read_resolv_conf_dns_options (rc_contents); + if (!read_options) + return changed; + + for (i = 0; i < read_options->len; i++) { + const char *s = g_ptr_array_index (read_options, i); + + if (_nm_utils_dns_option_validate (s, NULL, NULL, FALSE, _nm_utils_dns_option_descs) && + _nm_utils_dns_option_find_idx (dns_options, s) < 0) { + g_ptr_array_add (dns_options, g_strdup (s)); + changed = TRUE; + } + } + g_ptr_array_unref (read_options); + } + return changed; } static gboolean -addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b, gboolean consider_plen) +addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) { - return a->address == b->address && (!consider_plen || a->plen == b->plen); + return a->address == b->address + && a->plen == b->plen + && ((a->peer_address ^ b->peer_address) & nm_utils_ip4_prefix_to_netmask (a->plen)) == 0; } static gboolean @@ -195,7 +204,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) if (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex) > 0) return NULL; - config = nm_ip4_config_new (); + config = nm_ip4_config_new (ifindex); priv = NM_IP4_CONFIG_GET_PRIVATE (config); g_array_unref (priv->addresses); @@ -247,7 +256,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) * nameservers from /etc/resolv.conf. */ if (priv->addresses->len && priv->has_gateway && capture_resolv_conf) { - if (nm_ip4_config_capture_resolv_conf (priv->nameservers, NULL)) + if (nm_ip4_config_capture_resolv_conf (priv->nameservers, priv->dns_options, NULL)) _NOTIFY (config, PROP_NAMESERVERS); } @@ -298,7 +307,16 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu route.ifindex = ifindex; route.source = NM_IP_CONFIG_SOURCE_KERNEL; - route.network = nm_utils_ip4_address_clear_host_address (addr->address, addr->plen); + + /* The destination network depends on the peer-address. */ + route.network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen); + + if (_ipv4_is_zeronet (route.network)) { + /* Kernel doesn't add device-routes for destinations that + * start with 0.x.y.z. Skip them. */ + continue; + } + route.plen = addr->plen; route.pref_src = addr->address; route.metric = default_route_metric; @@ -386,6 +404,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu memset (&address, 0, sizeof (address)); nm_ip_address_get_address_binary (s_addr, &address.address); + address.peer_address = address.address; address.plen = nm_ip_address_get_prefix (s_addr); address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT; address.preferred = NM_PLATFORM_LIFETIME_PERMANENT; @@ -435,6 +454,12 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu for (i = 0; i < nsearches; i++) nm_ip4_config_add_search (config, nm_setting_ip_config_get_dns_search (setting, i)); + i = 0; + while ((i = nm_setting_ip_config_next_valid_dns_option (setting, i)) >= 0) { + nm_ip4_config_add_dns_option (config, nm_setting_ip_config_get_dns_option (setting, i)); + i++; + } + g_object_thaw_notify (G_OBJECT (config)); } @@ -443,7 +468,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) { NMSettingIPConfig *s_ip4; guint32 gateway; - guint naddresses, nroutes, nnameservers, nsearches; + guint naddresses, nroutes, nnameservers, nsearches, noptions; const char *method = NULL; int i; gint64 route_metric; @@ -462,6 +487,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) nroutes = nm_ip4_config_get_num_routes (config); nnameservers = nm_ip4_config_get_num_nameservers (config); nsearches = nm_ip4_config_get_num_searches (config); + noptions = nm_ip4_config_get_num_dns_options (config); route_metric = nm_ip4_config_get_route_metric (config); /* Addresses */ @@ -537,6 +563,12 @@ nm_ip4_config_create_setting (const NMIP4Config *config) nm_setting_ip_config_add_dns_search (s_ip4, search); } + for (i = 0; i < noptions; i++) { + const char *option = nm_ip4_config_get_dns_option (config, i); + + nm_setting_ip_config_add_dns_option (s_ip4, option); + } + return NM_SETTING (s_ip4); } @@ -593,6 +625,12 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); } + /* dns options */ + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip4_config_get_num_dns_options (src); i++) + nm_ip4_config_add_dns_option (dst, nm_ip4_config_get_dns_option (src, i)); + } + /* MSS */ if (nm_ip4_config_get_mss (src)) nm_ip4_config_set_mss (dst, nm_ip4_config_get_mss (src)); @@ -635,8 +673,7 @@ _addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr) for (i = 0; i < priv->addresses->len; i++) { const NMPlatformIP4Address *a = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - if (addr->address == a->address && - addr->plen == a->plen) + if (addresses_are_duplicate (addr, a)) return (int) i; } return -1; @@ -704,6 +741,21 @@ _searches_get_index (const NMIP4Config *self, const char *search) } static int +_dns_options_get_index (const NMIP4Config *self, const char *option) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->dns_options->len; i++) { + const char *s = g_ptr_array_index (priv->dns_options, i); + + if (g_strcmp0 (option, s) == 0) + return (int) i; + } + return -1; +} + +static int _nis_servers_get_index (const NMIP4Config *self, guint32 nis_server) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); @@ -798,6 +850,13 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) nm_ip4_config_del_search (dst, idx); } + /* dns options */ + for (i = 0; i < nm_ip4_config_get_num_dns_options (src); i++) { + idx = _dns_options_get_index (dst, nm_ip4_config_get_dns_option (src, i)); + if (idx >= 0) + nm_ip4_config_del_dns_option (dst, idx); + } + /* MSS */ if (nm_ip4_config_get_mss (src) == nm_ip4_config_get_mss (dst)) nm_ip4_config_set_mss (dst, 0); @@ -867,6 +926,7 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src) /* ignore domains */ /* ignore dns searches */ + /* ignore dns options */ /* ignore NIS */ /* ignore WINS */ @@ -891,7 +951,7 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src) gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes) { -#ifndef G_DISABLE_ASSERT +#if NM_MORE_ASSERTS gboolean config_equal; #endif gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; @@ -904,7 +964,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev g_return_val_if_fail (dst != NULL, FALSE); g_return_val_if_fail (src != dst, FALSE); -#ifndef G_DISABLE_ASSERT +#if NM_MORE_ASSERTS config_equal = nm_ip4_config_equal (dst, src); #endif @@ -913,6 +973,12 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev g_object_freeze_notify (G_OBJECT (dst)); + /* ifindex */ + if (src_priv->ifindex != dst_priv->ifindex) { + dst_priv->ifindex = src_priv->ifindex; + has_minor_changes = TRUE; + } + /* never_default */ if (src_priv->never_default != dst_priv->never_default) { dst_priv->never_default = src_priv->never_default; @@ -942,7 +1008,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev if (nm_platform_ip4_address_cmp (src_addr = nm_ip4_config_get_address (src, i), dst_addr = nm_ip4_config_get_address (dst, i))) { are_equal = FALSE; - if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) { + if ( !addresses_are_duplicate (src_addr, dst_addr) + || src_addr->peer_address != dst_addr->peer_address) { has_relevant_changes = TRUE; break; } @@ -1036,6 +1103,25 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev has_relevant_changes = TRUE; } + /* dns options */ + num = nm_ip4_config_get_num_dns_options (src); + are_equal = num == nm_ip4_config_get_num_dns_options (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip4_config_get_dns_option (src, i), + nm_ip4_config_get_dns_option (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip4_config_reset_dns_options (dst); + for (i = 0; i < num; i++) + nm_ip4_config_add_dns_option (dst, nm_ip4_config_get_dns_option (src, i)); + has_relevant_changes = TRUE; + } + /* mss */ if (src_priv->mss != dst_priv->mss) { nm_ip4_config_set_mss (dst, src_priv->mss); @@ -1096,9 +1182,11 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev has_minor_changes = TRUE; } +#if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ - g_assert (config_equal == !has_relevant_changes); + nm_assert (config_equal == !has_relevant_changes); +#endif g_object_thaw_notify (G_OBJECT (dst)); @@ -1114,17 +1202,20 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) guint32 i, tmp; const char *str; - g_return_if_fail (config != NULL); - g_message ("--------- NMIP4Config %p (%s)", config, detail); - str = nm_ip4_config_get_dbus_path (config); + if (config == NULL) { + g_message (" (null)"); + return; + } + + str = nm_exported_object_get_path (NM_EXPORTED_OBJECT (config)); if (str) g_message (" path: %s", str); /* addresses */ for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) - g_message (" a: %s", nm_platform_ip4_address_to_string (nm_ip4_config_get_address (config, i))); + g_message (" a: %s", nm_platform_ip4_address_to_string (nm_ip4_config_get_address (config, i), NULL, 0)); /* default gateway */ if (nm_ip4_config_has_gateway (config)) { @@ -1140,7 +1231,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) /* routes */ for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) - g_message (" rt: %s", nm_platform_ip4_route_to_string (nm_ip4_config_get_route (config, i))); + g_message (" rt: %s", nm_platform_ip4_route_to_string (nm_ip4_config_get_route (config, i), NULL, 0)); /* domains */ for (i = 0; i < nm_ip4_config_get_num_domains (config); i++) @@ -1150,6 +1241,11 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) for (i = 0; i < nm_ip4_config_get_num_searches (config); i++) g_message (" search: %s", nm_ip4_config_get_search (config, i)); + /* dns options */ + for (i = 0; i < nm_ip4_config_get_num_dns_options (config); i++) + g_message (" dnsopt: %s", nm_ip4_config_get_dns_option (config, i)); + + g_message (" mss: %"G_GUINT32_FORMAT, nm_ip4_config_get_mss (config)); g_message (" mtu: %"G_GUINT32_FORMAT, nm_ip4_config_get_mtu (config)); @@ -1176,12 +1272,22 @@ nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, { guint naddresses = nm_ip4_config_get_num_addresses (config); int i; + in_addr_t peer_network; for (i = 0; i < naddresses; i++) { const NMPlatformIP4Address *item = nm_ip4_config_get_address (config, i); - if (item->plen <= plen && same_prefix (item->address, network, item->plen)) - return TRUE; + if (item->plen > plen) + continue; + + peer_network = nm_utils_ip4_address_clear_host_address (item->peer_address, item->plen); + if (_ipv4_is_zeronet (peer_network)) + continue; + + if (peer_network != nm_utils_ip4_address_clear_host_address (network, item->plen)) + continue; + + return TRUE; } return FALSE; @@ -1229,6 +1335,16 @@ nm_ip4_config_unset_gateway (NMIP4Config *config) } } +/** + * nm_ip4_config_has_gateway: + * @config: the #NMIP4Config object + * + * NetworkManager's handling of default-routes is limited and usually a default-route + * cannot have gateway 0.0.0.0. For peer-to-peer routes, we still want to + * support that, so we need to differenciate between no-default-route and a + * on-link-default route. Hence nm_ip4_config_has_gateway(). + * + * Returns: whether the object has a gateway explicitly set. */ gboolean nm_ip4_config_has_gateway (const NMIP4Config *config) { @@ -1289,7 +1405,7 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new) for (i = 0; i < priv->addresses->len; i++ ) { NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - if (addresses_are_duplicate (item, new, FALSE)) { + if (addresses_are_duplicate (item, new)) { if (nm_platform_ip4_address_cmp (item, new) == 0) return; @@ -1356,16 +1472,7 @@ gboolean nm_ip4_config_address_exists (const NMIP4Config *config, const NMPlatformIP4Address *needle) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - guint i; - - for (i = 0; i < priv->addresses->len; i++) { - const NMPlatformIP4Address *haystack = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - - if (needle->address == haystack->address && needle->plen == haystack->plen) - return TRUE; - } - return FALSE; + return _addresses_get_index (config, needle) >= 0; } /******************************************************************/ @@ -1401,6 +1508,7 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new) g_return_if_fail (new != NULL); g_return_if_fail (new->plen > 0); + g_assert (priv->ifindex); for (i = 0; i < priv->routes->len; i++ ) { NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i); @@ -1412,11 +1520,13 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new) memcpy (item, new, sizeof (*item)); /* Restore highest priority source */ item->source = MAX (old_source, new->source); + item->ifindex = priv->ifindex; goto NOTIFY; } } g_array_append_val (priv->routes, *new); + g_array_index (priv->routes, NMPlatformIP4Route, priv->routes->len - 1).ifindex = priv->ifindex; NOTIFY: _NOTIFY (config, PROP_ROUTE_DATA); _NOTIFY (config, PROP_ROUTES); @@ -1480,28 +1590,6 @@ nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host return best_route; } -const NMPlatformIP4Address * -nm_ip4_config_get_subnet_for_host (const NMIP4Config *config, guint32 host) -{ - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - guint i; - NMPlatformIP4Address *subnet = NULL; - - g_return_val_if_fail (host, NULL); - - for (i = 0; i < priv->addresses->len; i++) { - NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - - if (subnet && subnet->plen >= item->plen) - continue; - if (nm_utils_ip4_address_clear_host_address (host, item->plen) != nm_utils_ip4_address_clear_host_address (item->address, item->plen)) - continue; - subnet = item; - } - - return subnet; -} - /******************************************************************/ void @@ -1690,6 +1778,63 @@ nm_ip4_config_get_search (const NMIP4Config *config, guint i) /******************************************************************/ void +nm_ip4_config_reset_dns_options (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + if (priv->dns_options->len != 0) { + g_ptr_array_set_size (priv->dns_options, 0); + _NOTIFY (config, PROP_DNS_OPTIONS); + } +} + +void +nm_ip4_config_add_dns_option (NMIP4Config *config, const char *new) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + int i; + + g_return_if_fail (new != NULL); + g_return_if_fail (new[0] != '\0'); + + for (i = 0; i < priv->dns_options->len; i++) + if (!g_strcmp0 (g_ptr_array_index (priv->dns_options, i), new)) + return; + + g_ptr_array_add (priv->dns_options, g_strdup (new)); + _NOTIFY (config, PROP_DNS_OPTIONS); +} + +void +nm_ip4_config_del_dns_option(NMIP4Config *config, guint i) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + g_return_if_fail (i < priv->dns_options->len); + + g_ptr_array_remove_index (priv->dns_options, i); + _NOTIFY (config, PROP_DNS_OPTIONS); +} + +guint32 +nm_ip4_config_get_num_dns_options (const NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->dns_options->len; +} + +const char * +nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return g_ptr_array_index (priv->dns_options, i); +} + +/******************************************************************/ + +void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -1900,6 +2045,7 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); hash_u32 (sum, address->address); hash_u32 (sum, address->plen); + hash_u32 (sum, address->peer_address & nm_utils_ip4_prefix_to_netmask (address->plen)); } for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) { @@ -1934,6 +2080,12 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only s = nm_ip4_config_get_search (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } + + for (i = 0; i < nm_ip4_config_get_num_dns_options (config); i++) { + s = nm_ip4_config_get_dns_option (config, i); + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } + } /** @@ -1981,13 +2133,17 @@ nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b) static void nm_ip4_config_init (NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + NMIP4ConfigPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (config, NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate); + config->priv = priv; priv->addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Address)); priv->routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); priv->nameservers = g_array_new (FALSE, FALSE, sizeof (guint32)); priv->domains = g_ptr_array_new_with_free_func (g_free); priv->searches = g_ptr_array_new_with_free_func (g_free); + priv->dns_options = g_ptr_array_new_with_free_func (g_free); priv->nis = g_array_new (FALSE, TRUE, sizeof (guint32)); priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32)); priv->route_metric = -1; @@ -1996,15 +2152,15 @@ nm_ip4_config_init (NMIP4Config *config) static void finalize (GObject *object) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); - - g_free (priv->path); + NMIP4Config *self = NM_IP4_CONFIG (object); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); g_array_unref (priv->addresses); g_array_unref (priv->routes); g_array_unref (priv->nameservers); g_ptr_array_unref (priv->domains); g_ptr_array_unref (priv->searches); + g_ptr_array_unref (priv->dns_options); g_array_unref (priv->nis); g_free (priv->nis_domain); g_array_unref (priv->wins); @@ -2013,145 +2169,133 @@ finalize (GObject *object) } static void -gvalue_destroy (gpointer data) -{ - GValue *value = (GValue *) data; - - g_value_unset (value); - g_slice_free (GValue, value); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMIP4Config *config = NM_IP4_CONFIG (object); - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); switch (prop_id) { + case PROP_IFINDEX: + g_value_set_int (value, priv->ifindex); + break; case PROP_ADDRESS_DATA: { - GPtrArray *addresses = g_ptr_array_new (); + GVariantBuilder array_builder, addr_builder; int naddr = nm_ip4_config_get_num_addresses (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); for (i = 0; i < naddr; i++) { const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); - GHashTable *addr_hash; - GValue *val; - addr_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, nm_utils_inet4_ntop (address->address, NULL)); - g_hash_table_insert (addr_hash, "address", val); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_UINT); - g_value_set_uint (val, address->plen); - g_hash_table_insert (addr_hash, "prefix", val); + g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&addr_builder, "{sv}", + "address", + g_variant_new_string (nm_utils_inet4_ntop (address->address, NULL))); + g_variant_builder_add (&addr_builder, "{sv}", + "prefix", + g_variant_new_uint32 (address->plen)); + if (address->peer_address != address->address) { + g_variant_builder_add (&addr_builder, "{sv}", + "peer", + g_variant_new_string (nm_utils_inet4_ntop (address->peer_address, NULL))); + } if (*address->label) { - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, address->label); - g_hash_table_insert (addr_hash, "label", val); + g_variant_builder_add (&addr_builder, "{sv}", + "label", + g_variant_new_string (address->label)); } - g_ptr_array_add (addresses, addr_hash); + g_variant_builder_add (&array_builder, "a{sv}", &addr_builder); } - g_value_take_boxed (value, addresses); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_ADDRESSES: { - GPtrArray *addresses = g_ptr_array_new (); + GVariantBuilder array_builder; int naddr = nm_ip4_config_get_num_addresses (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau")); for (i = 0; i < naddr; i++) { const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); - GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); - guint32 gateway = i == 0 ? priv->gateway : 0; + guint32 dbus_addr[3]; - g_array_append_val (array, address->address); - g_array_append_val (array, address->plen); - g_array_append_val (array, gateway); + dbus_addr[0] = address->address; + dbus_addr[1] = address->plen; + dbus_addr[2] = i == 0 ? priv->gateway : 0; - g_ptr_array_add (addresses, array); + g_variant_builder_add (&array_builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + dbus_addr, 3, sizeof (guint32))); } - g_value_take_boxed (value, addresses); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_ROUTE_DATA: { - GPtrArray *routes = g_ptr_array_new (); + GVariantBuilder array_builder, route_builder; guint nroutes = nm_ip4_config_get_num_routes (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); for (i = 0; i < nroutes; i++) { const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i); - GHashTable *route_hash; - GValue *val; - - route_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, nm_utils_inet4_ntop (route->network, NULL)); - g_hash_table_insert (route_hash, "dest", val); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_UINT); - g_value_set_uint (val, route->plen); - g_hash_table_insert (route_hash, "prefix", val); + g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&route_builder, "{sv}", + "dest", + g_variant_new_string (nm_utils_inet4_ntop (route->network, NULL))); + g_variant_builder_add (&route_builder, "{sv}", + "prefix", + g_variant_new_uint32 (route->plen)); if (route->gateway) { - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, nm_utils_inet4_ntop (route->gateway, NULL)); - g_hash_table_insert (route_hash, "next-hop", val); + g_variant_builder_add (&route_builder, "{sv}", + "next-hop", + g_variant_new_string (nm_utils_inet4_ntop (route->gateway, NULL))); } + g_variant_builder_add (&route_builder, "{sv}", + "metric", + g_variant_new_uint32 (route->metric)); - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_UINT); - g_value_set_uint (val, route->metric); - g_hash_table_insert (route_hash, "metric", val); - - g_ptr_array_add (routes, route_hash); + g_variant_builder_add (&array_builder, "a{sv}", &route_builder); } - g_value_take_boxed (value, routes); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_ROUTES: { - GPtrArray *routes = g_ptr_array_new (); + GVariantBuilder array_builder; guint nroutes = nm_ip4_config_get_num_routes (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau")); for (i = 0; i < nroutes; i++) { const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i); - GArray *array; + guint32 dbus_route[4]; /* legacy versions of nm_ip4_route_set_prefix() in libnm-util assert that the * plen is positive. Skip the default routes not to break older clients. */ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) continue; - array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4); - g_array_append_val (array, route->network); - g_array_append_val (array, route->plen); - g_array_append_val (array, route->gateway); - g_array_append_val (array, route->metric); + dbus_route[0] = route->network; + dbus_route[1] = route->plen; + dbus_route[2] = route->gateway; + dbus_route[3] = route->metric; - g_ptr_array_add (routes, array); + g_variant_builder_add (&array_builder, "@au", + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + dbus_route, 4, sizeof (guint32))); } - g_value_take_boxed (value, routes); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_GATEWAY: @@ -2161,16 +2305,46 @@ get_property (GObject *object, guint prop_id, g_value_set_string (value, NULL); break; case PROP_NAMESERVERS: - g_value_set_boxed (value, priv->nameservers); + g_value_take_variant (value, + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + priv->nameservers->data, + priv->nameservers->len, + sizeof (guint32))); break; case PROP_DOMAINS: - g_value_set_boxed (value, priv->domains); + nm_utils_g_value_set_strv (value, priv->domains); break; case PROP_SEARCHES: - g_value_set_boxed (value, priv->searches); + nm_utils_g_value_set_strv (value, priv->searches); + break; + case PROP_DNS_OPTIONS: + nm_utils_g_value_set_strv (value, priv->dns_options); break; case PROP_WINS_SERVERS: - g_value_set_boxed (value, priv->wins); + g_value_take_variant (value, + g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, + priv->wins->data, + priv->wins->len, + sizeof (guint32))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NMIP4Config *self = NM_IP4_CONFIG (object); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_IFINDEX: + priv->ifindex = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2182,61 +2356,83 @@ static void nm_ip4_config_class_init (NMIP4ConfigClass *config_class) { GObjectClass *object_class = G_OBJECT_CLASS (config_class); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (config_class); g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate)); + exported_object_class->export_path = NM_DBUS_PATH "/IP4Config/%u"; + object_class->get_property = get_property; + object_class->set_property = set_property; object_class->finalize = finalize; + obj_properties[PROP_IFINDEX] = + g_param_spec_int (NM_IP4_CONFIG_IFINDEX, "", "", + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_ADDRESS_DATA] = - g_param_spec_boxed (NM_IP4_CONFIG_ADDRESS_DATA, "", "", - DBUS_TYPE_NM_IP_ADDRESSES, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP4_CONFIG_ADDRESS_DATA, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_ADDRESSES] = - g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES, "", "", - DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP4_CONFIG_ADDRESSES, "", "", + G_VARIANT_TYPE ("aau"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_ROUTE_DATA] = - g_param_spec_boxed (NM_IP4_CONFIG_ROUTE_DATA, "", "", - DBUS_TYPE_NM_IP_ROUTES, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP4_CONFIG_ROUTE_DATA, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_ROUTES] = - g_param_spec_boxed (NM_IP4_CONFIG_ROUTES, "", "", - DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP4_CONFIG_ROUTES, "", "", + G_VARIANT_TYPE ("aau"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_GATEWAY] = g_param_spec_string (NM_IP4_CONFIG_GATEWAY, "", "", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_NAMESERVERS] = - g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS, "", "", - DBUS_TYPE_G_UINT_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP4_CONFIG_NAMESERVERS, "", "", + G_VARIANT_TYPE ("au"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_DOMAINS] = - g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS, "", "", - DBUS_TYPE_G_ARRAY_OF_STRING, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_SEARCHES] = - g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES, "", "", - DBUS_TYPE_G_ARRAY_OF_STRING, + g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DNS_OPTIONS] = + g_param_spec_boxed (NM_IP4_CONFIG_DNS_OPTIONS, "", "", + G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_WINS_SERVERS] = - g_param_spec_boxed (NM_IP4_CONFIG_WINS_SERVERS, "", "", - DBUS_TYPE_G_UINT_ARRAY, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP4_CONFIG_WINS_SERVERS, "", "", + G_VARIANT_TYPE ("au"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, obj_properties); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (config_class), - &dbus_glib_nm_ip4_config_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (config_class), + NMDBUS_TYPE_IP4_CONFIG_SKELETON, + NULL); } |