diff --git a/ChangeLog b/ChangeLog index 09f1145a0..f734739a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2008-08-06 Dan Williams + + * libnm-glib/nm-ip4-config.c + libnm-glib/nm-ip4-config.h + - Add 'routes' property + + * libnm-util/nm-setting-vpn.c + libnm-util/nm-setting-vpn.h + - Remove 'routes' property + + * libnm-util/nm-setting-ip4-config.c + libnm-util/nm-setting-ip4-config.h + - 'ignore-dhcp-dns' renamed to 'ignore-auto-dns' + - Add 'ignore-auto-routes' property + - 'routes' exposed over D-Bus is now an array of array of uint (4) to + accomodate route metrics + - 'routes' exposed in C is now a list of NMSettingIP4Route structures + + * libnm-util/nm-utils.c + libnm-util/nm-utils.h + - Add helpers for marshalling IP4 routes + + * src/NetworkManagerUtils.c + - (nm_utils_merge_ip4_config): handle property renames and new route + structure + + * src/NetworkManagerSystem.c + - (nm_system_device_set_ip4_route, nm_system_device_set_from_ip4_config, + nm_system_vpn_device_set_from_ip4_config): respect route metrics + + * src/dhcp-manager/nm-dhcp-manager.c + - (nm_dhcp_manager_get_ip4_config): handle new route structure + + * system-settings/plugins/ifcfg-fedora/reader.c + system-settings/plugins/ifcfg-fedora/writer.c + - Handle routes separately from addresses now that routes have a different + format + + * introspection/nm-ip4-config.xml + src/nm-ip4-config.c + src/nm-ip4-config.h + - Rename internal routing functions + - 'static-routes' renamed to 'routes' + 2008-08-04 Dan Williams Patch from Sjoerd Simons diff --git a/introspection/nm-ip4-config.xml b/introspection/nm-ip4-config.xml index 8ac92a9a1..a4eea8163 100644 --- a/introspection/nm-ip4-config.xml +++ b/introspection/nm-ip4-config.xml @@ -3,7 +3,7 @@ - Tuples of IPv4 address/prefix/gateway. The gateway is optional, if not given should be 0. + Tuples of IPv4 address/prefix/gateway. The hostname associated with this IPv4 address. FIXME: what about multiple hostnames? @@ -20,6 +20,9 @@ The NIS servers associated with this address. + + Tuples of IPv4 route/prefix/next-hop/metric. + diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c index 6eb2c522c..1382378d3 100644 --- a/libnm-glib/nm-ip4-config.c +++ b/libnm-glib/nm-ip4-config.c @@ -19,6 +19,7 @@ typedef struct { GPtrArray *domains; char *nis_domain; GArray *nis_servers; + GSList *routes; } NMIP4ConfigPrivate; enum { @@ -29,6 +30,7 @@ enum { PROP_DOMAINS, PROP_NIS_DOMAIN, PROP_NIS_SERVERS, + PROP_ROUTES, LAST_PROP }; @@ -76,6 +78,21 @@ demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer return TRUE; } +static gboolean +demarshal_ip4_routes_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); + + g_slist_foreach (priv->routes, (GFunc) g_free, NULL); + g_slist_free (priv->routes); + priv->routes = NULL; + + priv->routes = nm_utils_ip4_routes_from_gvalue (value); + nm_object_queue_notify (object, NM_IP4_CONFIG_ROUTES); + + return TRUE; +} + static void register_for_property_changed (NMIP4Config *config) { @@ -87,6 +104,7 @@ register_for_property_changed (NMIP4Config *config) { NM_IP4_CONFIG_DOMAINS, demarshal_domains, &priv->domains }, { NM_IP4_CONFIG_NIS_DOMAIN, nm_object_demarshal_generic, &priv->nis_domain }, { NM_IP4_CONFIG_NIS_SERVERS, demarshal_ip4_array, &priv->nis_servers }, + { NM_IP4_CONFIG_ROUTES, demarshal_ip4_routes_array, &priv->routes }, { NULL }, }; @@ -131,6 +149,9 @@ finalize (GObject *object) g_slist_foreach (priv->addresses, (GFunc) g_free, NULL); g_slist_free (priv->addresses); + g_slist_foreach (priv->routes, (GFunc) g_free, NULL); + g_slist_free (priv->routes); + g_free (priv->hostname); g_free (priv->nis_domain); if (priv->nameservers) @@ -174,6 +195,9 @@ get_property (GObject *object, case PROP_NIS_SERVERS: g_value_set_boxed (value, nm_ip4_config_get_nis_servers (self)); break; + case PROP_ROUTES: + nm_utils_ip4_routes_to_gvalue (priv->routes, value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -239,6 +263,13 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) "NIS servers", NM_TYPE_UINT_ARRAY, G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_ROUTES, + g_param_spec_pointer (NM_IP4_CONFIG_ROUTES, + "Routes", + "Routes", + G_PARAM_READABLE)); } GObject * @@ -366,7 +397,7 @@ nm_ip4_config_get_nis_domain (NMIP4Config *config) return priv->nis_domain; } -GArray * +const GArray * nm_ip4_config_get_nis_servers (NMIP4Config *config) { NMIP4ConfigPrivate *priv; @@ -392,3 +423,29 @@ nm_ip4_config_get_nis_servers (NMIP4Config *config) return priv->nis_servers; } + +const GSList * +nm_ip4_config_get_routes (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv; + GValue value = { 0, }; + + g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + if (priv->routes) + return priv->routes; + + if (!nm_object_get_property (NM_OBJECT (config), + "org.freedesktop.DBus.Properties", + "Routes", + &value)) { + return NULL; + } + + demarshal_ip4_routes_array (NM_OBJECT (config), NULL, &value, &priv->routes); + g_value_unset (&value); + + return priv->routes; +} + diff --git a/libnm-glib/nm-ip4-config.h b/libnm-glib/nm-ip4-config.h index 18fdeb825..79de2f849 100644 --- a/libnm-glib/nm-ip4-config.h +++ b/libnm-glib/nm-ip4-config.h @@ -29,6 +29,7 @@ typedef struct { #define NM_IP4_CONFIG_DOMAINS "domains" #define NM_IP4_CONFIG_NIS_DOMAIN "nis-domain" #define NM_IP4_CONFIG_NIS_SERVERS "nis-servers" +#define NM_IP4_CONFIG_ROUTES "routes" GType nm_ip4_config_get_type (void); @@ -39,7 +40,8 @@ const char * nm_ip4_config_get_hostname (NMIP4Config *config); const GArray * nm_ip4_config_get_nameservers (NMIP4Config *config); const GPtrArray *nm_ip4_config_get_domains (NMIP4Config *config); const char * nm_ip4_config_get_nis_domain (NMIP4Config *config); -GArray * nm_ip4_config_get_nis_servers (NMIP4Config *config); +const GArray * nm_ip4_config_get_nis_servers (NMIP4Config *config); +const GSList * nm_ip4_config_get_routes (NMIP4Config *config); G_END_DECLS diff --git a/libnm-util/nm-setting-ip4-config.c b/libnm-util/nm-setting-ip4-config.c index 1def822e1..2e3873d50 100644 --- a/libnm-util/nm-setting-ip4-config.c +++ b/libnm-util/nm-setting-ip4-config.c @@ -76,7 +76,8 @@ enum { PROP_DNS_SEARCH, PROP_ADDRESSES, PROP_ROUTES, - PROP_IGNORE_DHCP_DNS, + PROP_IGNORE_AUTO_ROUTES, + PROP_IGNORE_AUTO_DNS, PROP_DHCP_CLIENT_ID, PROP_DHCP_HOSTNAME, @@ -186,9 +187,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error) /* Validate routes */ for (iter = self->routes, i = 0; iter; iter = g_slist_next (iter), i++) { - NMSettingIP4Address *addr = (NMSettingIP4Address *) iter->data; + NMSettingIP4Route *route = (NMSettingIP4Route *) iter->data; - if (!addr->address) { + if (!route->address) { g_set_error (error, NM_SETTING_IP4_CONFIG_ERROR, NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, @@ -196,7 +197,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error) return FALSE; } - if (!addr->prefix || addr->prefix > 32) { + if (!route->prefix || route->prefix > 32) { g_set_error (error, NM_SETTING_IP4_CONFIG_ERROR, NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, @@ -258,10 +259,13 @@ set_property (GObject *object, guint prop_id, break; case PROP_ROUTES: nm_utils_slist_free (setting->routes, g_free); - setting->routes = nm_utils_ip4_addresses_from_gvalue (value); + setting->routes = nm_utils_ip4_routes_from_gvalue (value); break; - case PROP_IGNORE_DHCP_DNS: - setting->ignore_dhcp_dns = g_value_get_boolean (value); + case PROP_IGNORE_AUTO_ROUTES: + setting->ignore_auto_routes = g_value_get_boolean (value); + break; + case PROP_IGNORE_AUTO_DNS: + setting->ignore_auto_dns = g_value_get_boolean (value); break; case PROP_DHCP_CLIENT_ID: g_free (setting->dhcp_client_id); @@ -297,10 +301,13 @@ get_property (GObject *object, guint prop_id, nm_utils_ip4_addresses_to_gvalue (setting->addresses, value); break; case PROP_ROUTES: - nm_utils_ip4_addresses_to_gvalue (setting->routes, value); + nm_utils_ip4_routes_to_gvalue (setting->routes, value); break; - case PROP_IGNORE_DHCP_DNS: - g_value_set_boolean (value, setting->ignore_dhcp_dns); + case PROP_IGNORE_AUTO_ROUTES: + g_value_set_boolean (value, setting->ignore_auto_routes); + break; + case PROP_IGNORE_AUTO_DNS: + g_value_set_boolean (value, setting->ignore_auto_dns); break; case PROP_DHCP_CLIENT_ID: g_value_set_string (value, setting->dhcp_client_id); @@ -363,15 +370,23 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class) (object_class, PROP_ROUTES, nm_param_spec_specialized (NM_SETTING_IP4_CONFIG_ROUTES, "Routes", - "List of NMSettingIP4Addresses", + "List of NMSettingIP4Routes", DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); g_object_class_install_property - (object_class, PROP_IGNORE_DHCP_DNS, - g_param_spec_boolean (NM_SETTING_IP4_CONFIG_IGNORE_DHCP_DNS, - "Ignore DHCP DNS", - "Ignore DHCP DNS", + (object_class, PROP_IGNORE_AUTO_ROUTES, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, + "Ignore automatic routes", + "Ignore automatic routes", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + g_object_class_install_property + (object_class, PROP_IGNORE_AUTO_DNS, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, + "Ignore automatic DNS", + "Ignore automatic DNS", FALSE, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); diff --git a/libnm-util/nm-setting-ip4-config.h b/libnm-util/nm-setting-ip4-config.h index a6928a40f..119b09c14 100644 --- a/libnm-util/nm-setting-ip4-config.h +++ b/libnm-util/nm-setting-ip4-config.h @@ -53,14 +53,15 @@ GType nm_setting_ip4_config_error_get_type (void); #define NM_SETTING_IP4_CONFIG_ERROR nm_setting_ip4_config_error_quark () GQuark nm_setting_ip4_config_error_quark (void); -#define NM_SETTING_IP4_CONFIG_METHOD "method" -#define NM_SETTING_IP4_CONFIG_DNS "dns" -#define NM_SETTING_IP4_CONFIG_DNS_SEARCH "dns-search" -#define NM_SETTING_IP4_CONFIG_ADDRESSES "addresses" -#define NM_SETTING_IP4_CONFIG_ROUTES "routes" -#define NM_SETTING_IP4_CONFIG_IGNORE_DHCP_DNS "ignore-dhcp-dns" -#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" -#define NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME "dhcp-hostname" +#define NM_SETTING_IP4_CONFIG_METHOD "method" +#define NM_SETTING_IP4_CONFIG_DNS "dns" +#define NM_SETTING_IP4_CONFIG_DNS_SEARCH "dns-search" +#define NM_SETTING_IP4_CONFIG_ADDRESSES "addresses" +#define NM_SETTING_IP4_CONFIG_ROUTES "routes" +#define NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" +#define NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" +#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" +#define NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME "dhcp-hostname" #define NM_SETTING_IP4_CONFIG_METHOD_AUTO "auto" #define NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL "link-local" @@ -73,6 +74,13 @@ typedef struct { guint32 gateway; /* network byte order */ } NMSettingIP4Address; +typedef struct { + guint32 address; /* network byte order */ + guint32 prefix; + guint32 next_hop; /* network byte order */ + guint32 metric; /* lower metric == more preferred */ +} NMSettingIP4Route; + typedef struct { NMSetting parent; @@ -80,8 +88,9 @@ typedef struct { GArray *dns; /* array of guint32; elements in network byte order */ GSList *dns_search; /* list of strings */ GSList *addresses; /* array of NMSettingIP4Address */ - GSList *routes; /* array of NMSettingIP4Address */ - gboolean ignore_dhcp_dns; + GSList *routes; /* array of NMSettingIP4Route */ + gboolean ignore_auto_routes; + gboolean ignore_auto_dns; char *dhcp_client_id; char *dhcp_hostname; } NMSettingIP4Config; diff --git a/libnm-util/nm-setting-vpn.c b/libnm-util/nm-setting-vpn.c index 4c4b54d4d..9a8258b84 100644 --- a/libnm-util/nm-setting-vpn.c +++ b/libnm-util/nm-setting-vpn.c @@ -70,7 +70,6 @@ enum { PROP_0, PROP_SERVICE_TYPE, PROP_USER_NAME, - PROP_ROUTES, LAST_PROP }; @@ -127,7 +126,6 @@ finalize (GObject *object) g_free (self->service_type); g_free (self->user_name); - nm_utils_slist_free (self->routes, g_free); G_OBJECT_CLASS (nm_setting_vpn_parent_class)->finalize (object); } @@ -147,10 +145,6 @@ set_property (GObject *object, guint prop_id, g_free (setting->user_name); setting->user_name = g_value_dup_string (value); break; - case PROP_ROUTES: - nm_utils_slist_free (setting->routes, g_free); - setting->routes = g_value_dup_boxed (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -170,9 +164,6 @@ get_property (GObject *object, guint prop_id, case PROP_USER_NAME: g_value_set_string (value, setting->user_name); break; - case PROP_ROUTES: - g_value_set_boxed (value, setting->routes); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -207,12 +198,4 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class) "User name", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); - - g_object_class_install_property - (object_class, PROP_ROUTES, - nm_param_spec_specialized (NM_SETTING_VPN_ROUTES, - "Routes", - "Routes", - DBUS_TYPE_G_LIST_OF_STRING, - G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); } diff --git a/libnm-util/nm-setting-vpn.h b/libnm-util/nm-setting-vpn.h index 7048ce96f..a52627ae9 100644 --- a/libnm-util/nm-setting-vpn.h +++ b/libnm-util/nm-setting-vpn.h @@ -54,14 +54,12 @@ GQuark nm_setting_vpn_error_quark (void); #define NM_SETTING_VPN_SERVICE_TYPE "service-type" #define NM_SETTING_VPN_USER_NAME "user-name" -#define NM_SETTING_VPN_ROUTES "routes" typedef struct { NMSetting parent; char *service_type; char *user_name; - GSList *routes; } NMSettingVPN; typedef struct { diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c index 0f9ba3d94..3171660b0 100644 --- a/libnm-util/nm-utils.c +++ b/libnm-util/nm-utils.c @@ -859,6 +859,58 @@ nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value) g_value_take_boxed (value, addresses); } +GSList * +nm_utils_ip4_routes_from_gvalue (const GValue *value) +{ + GPtrArray *routes; + int i; + GSList *list = NULL; + + routes = (GPtrArray *) g_value_get_boxed (value); + for (i = 0; routes && (i < routes->len); i++) { + GArray *array = (GArray *) g_ptr_array_index (routes, i); + NMSettingIP4Route *route; + + if (array->len != 4) { + nm_warning ("Ignoring invalid IP4 route"); + continue; + } + + route = g_malloc0 (sizeof (NMSettingIP4Route)); + route->address = g_array_index (array, guint32, 0); + route->prefix = g_array_index (array, guint32, 1); + route->next_hop = g_array_index (array, guint32, 2); + route->metric = g_array_index (array, guint32, 3); + list = g_slist_prepend (list, route); + } + + return g_slist_reverse (list); +} + +void +nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *routes; + GSList *iter; + + routes = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + NMSettingIP4Route *route = (NMSettingIP4Route *) iter->data; + GArray *array; + + array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + + g_array_append_val (array, route->address); + g_array_append_val (array, route->prefix); + g_array_append_val (array, route->next_hop); + g_array_append_val (array, route->metric); + g_ptr_array_add (routes, array); + } + + g_value_take_boxed (value, routes); +} + /* * nm_utils_ip4_netmask_to_prefix * diff --git a/libnm-util/nm-utils.h b/libnm-util/nm-utils.h index e573ac444..394988fab 100644 --- a/libnm-util/nm-utils.h +++ b/libnm-util/nm-utils.h @@ -187,6 +187,9 @@ gboolean nm_utils_security_valid (NMUtilsSecurityType type, GSList *nm_utils_ip4_addresses_from_gvalue (const GValue *value); void nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value); +GSList *nm_utils_ip4_routes_from_gvalue (const GValue *value); +void nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value); + guint32 nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask); guint32 nm_utils_ip4_prefix_to_netmask (guint32 ip4_prefix); diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index 8aa885c0f..bf6b11d79 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -107,6 +107,7 @@ nm_system_device_set_ip4_route (const char *iface, guint32 ip4_dest, guint32 ip4_prefix, guint32 ip4_gateway, + guint32 metric, int mss) { struct nl_handle *nlh; @@ -148,6 +149,10 @@ nm_system_device_set_ip4_route (const char *iface, } } + /* Metric */ + if (metric) + rtnl_route_set_prio (route, metric); + /* Add the route */ err = rtnl_route_add (nlh, route, 0); if (err == -ESRCH && ip4_gateway) { @@ -284,14 +289,15 @@ nm_system_device_set_from_ip4_config (const char *iface, sleep (1); - len = nm_ip4_config_get_num_static_routes (config); + len = nm_ip4_config_get_num_routes (config); for (i = 0; i < len; i++) { - const NMSettingIP4Address *route = nm_ip4_config_get_static_route (config, i); + const NMSettingIP4Route *route = nm_ip4_config_get_route (config, i); nm_system_device_set_ip4_route (iface, config, route->address, route->prefix, - route->gateway, + route->next_hop, + route->metric, nm_ip4_config_get_mss (config)); } @@ -344,7 +350,7 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device, } nm_system_device_set_ip4_route (nm_device_get_ip_iface (active_device), - ad_config, vpn_gw, 32, ad_gw, + ad_config, vpn_gw, 32, ad_gw, 0, nm_ip4_config_get_mss (config)); } } @@ -362,14 +368,15 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device, nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config)); /* Set routes */ - num = nm_ip4_config_get_num_static_routes (config); + num = nm_ip4_config_get_num_routes (config); for (i = 0; i < num; i++) { - const NMSettingIP4Address *route = nm_ip4_config_get_static_route (config, i); + const NMSettingIP4Route *route = nm_ip4_config_get_route (config, i); nm_system_device_set_ip4_route (iface, config, route->address, route->prefix, - route->gateway, + route->next_hop, + route->metric, nm_ip4_config_get_mss (config)); } diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index a4a56448e..66fe99079 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -278,11 +278,14 @@ nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) if (!setting) return; /* Defaults are just fine */ - if (setting->ignore_dhcp_dns) { + if (setting->ignore_auto_dns) { nm_ip4_config_reset_nameservers (ip4_config); nm_ip4_config_reset_searches (ip4_config); } + if (setting->ignore_auto_routes) + nm_ip4_config_reset_routes (ip4_config); + if (setting->dns) { int i, j; @@ -344,25 +347,27 @@ nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) nm_ip4_config_add_address (ip4_config, setting_addr); } - /* IPv4 static routes */ + /* IPv4 routes */ for (iter = setting->routes; iter; iter = g_slist_next (iter)) { - NMSettingIP4Address *setting_route = (NMSettingIP4Address *) iter->data; + NMSettingIP4Route *setting_route = (NMSettingIP4Route *) iter->data; guint32 i, num; - num = nm_ip4_config_get_num_static_routes (ip4_config); + num = nm_ip4_config_get_num_routes (ip4_config); for (i = 0; i < num; i++) { - const NMSettingIP4Address *cfg_route; + const NMSettingIP4Route *cfg_route; - cfg_route = nm_ip4_config_get_static_route (ip4_config, i); - /* Dupe, override with user-specified address */ - if (cfg_route->address == setting_route->address) { - nm_ip4_config_replace_static_route (ip4_config, i, setting_route); + cfg_route = nm_ip4_config_get_route (ip4_config, i); + /* Dupe, override with user-specified route */ + if ( (cfg_route->address == setting_route->address) + && (cfg_route->prefix == setting_route->prefix) + && (cfg_route->next_hop == setting_route->next_hop)) { + nm_ip4_config_replace_route (ip4_config, i, setting_route); break; } } if (i == num) - nm_ip4_config_add_static_route (ip4_config, setting_route); + nm_ip4_config_add_route (ip4_config, setting_route); } } diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index 4846bf104..94c4a65c6 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -829,6 +829,7 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, char **s; for (s = searches; *s; s += 2) { + NMSettingIP4Route *route; struct in_addr rt_addr; struct in_addr rt_route; @@ -843,13 +844,12 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, // FIXME: ensure the IP addresse and route are sane - addr = g_malloc0 (sizeof (NMSettingIP4Address)); - addr->address = (guint32) rt_addr.s_addr; - addr->prefix = 32; /* 255.255.255.255 */ - addr->gateway = (guint32) rt_route.s_addr; + route = g_malloc0 (sizeof (NMSettingIP4Route)); + route->address = (guint32) rt_addr.s_addr; + route->prefix = 32; /* 255.255.255.255 */ + route->next_hop = (guint32) rt_route.s_addr; - nm_ip4_config_take_static_route (ip4_config, addr); - addr = NULL; + nm_ip4_config_take_route (ip4_config, route); nm_info (" static route %s gw %s", *s, *(s + 1)); } } else { diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 40acfc364..0bf780b89 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -58,7 +58,7 @@ typedef struct { gchar *hostname; gchar *nis_domain; GArray *nis_servers; - GSList *static_routes; + GSList *routes; } NMIP4ConfigPrivate; @@ -70,7 +70,7 @@ enum { PROP_DOMAINS, PROP_NIS_DOMAIN, PROP_NIS_SERVERS, - PROP_STATIC_ROUTES, + PROP_ROUTES, LAST_PROP }; @@ -133,13 +133,13 @@ NMIP4Config *nm_ip4_config_copy (NMIP4Config *src_config) for (i = 0; i < len; i++) nm_ip4_config_add_nis_server (dst_config, nm_ip4_config_get_nis_server (src_config, i)); - for (iter = src_priv->static_routes; iter; iter = g_slist_next (iter)) { - NMSettingIP4Address *src_addr = (NMSettingIP4Address *) iter->data; - NMSettingIP4Address *dst_addr; + for (iter = src_priv->routes; iter; iter = g_slist_next (iter)) { + NMSettingIP4Route *src_route = (NMSettingIP4Route *) iter->data; + NMSettingIP4Route *dst_route; - dst_addr = g_malloc0 (sizeof (NMSettingIP4Address)); - memcpy (dst_addr, src_addr, sizeof (NMSettingIP4Address)); - nm_ip4_config_take_static_route (dst_config, dst_addr); + dst_route = g_malloc0 (sizeof (NMSettingIP4Route)); + memcpy (dst_route, src_route, sizeof (NMSettingIP4Route)); + nm_ip4_config_take_route (dst_config, dst_route); } return dst_config; @@ -310,38 +310,38 @@ const char *nm_ip4_config_get_nis_domain (NMIP4Config *config) } void -nm_ip4_config_take_static_route (NMIP4Config *config, - NMSettingIP4Address *address) +nm_ip4_config_take_route (NMIP4Config *config, + NMSettingIP4Route *route) { NMIP4ConfigPrivate *priv; g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (address != NULL); + g_return_if_fail (route != NULL); priv = NM_IP4_CONFIG_GET_PRIVATE (config); - priv->static_routes = g_slist_append (priv->static_routes, address); + priv->routes = g_slist_append (priv->routes, route); } void -nm_ip4_config_add_static_route (NMIP4Config *config, - NMSettingIP4Address *address) +nm_ip4_config_add_route (NMIP4Config *config, + NMSettingIP4Route *route) { NMIP4ConfigPrivate *priv; - NMSettingIP4Address *copy; + NMSettingIP4Route *copy; g_return_if_fail (NM_IS_IP4_CONFIG (config)); - g_return_if_fail (address != NULL); + g_return_if_fail (route != NULL); priv = NM_IP4_CONFIG_GET_PRIVATE (config); - copy = g_malloc0 (sizeof (NMSettingIP4Address)); - memcpy (copy, address, sizeof (NMSettingIP4Address)); - priv->static_routes = g_slist_append (priv->static_routes, copy); + copy = g_malloc0 (sizeof (NMSettingIP4Route)); + memcpy (copy, route, sizeof (NMSettingIP4Route)); + priv->routes = g_slist_append (priv->routes, copy); } void -nm_ip4_config_replace_static_route (NMIP4Config *config, +nm_ip4_config_replace_route (NMIP4Config *config, guint i, - NMSettingIP4Address *new_address) + NMSettingIP4Route *new_route) { NMIP4ConfigPrivate *priv; GSList *old; @@ -349,28 +349,38 @@ nm_ip4_config_replace_static_route (NMIP4Config *config, g_return_if_fail (NM_IS_IP4_CONFIG (config)); priv = NM_IP4_CONFIG_GET_PRIVATE (config); - old = g_slist_nth (priv->static_routes, i); + old = g_slist_nth (priv->routes, i); g_return_if_fail (old != NULL); g_free (old->data); - old->data = new_address; + old->data = new_route; } -const NMSettingIP4Address * -nm_ip4_config_get_static_route (NMIP4Config *config, guint i) +const NMSettingIP4Route * +nm_ip4_config_get_route (NMIP4Config *config, guint i) { g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); - return (const NMSettingIP4Address *) g_slist_nth_data (NM_IP4_CONFIG_GET_PRIVATE (config)->static_routes, i); + return (const NMSettingIP4Route *) g_slist_nth_data (NM_IP4_CONFIG_GET_PRIVATE (config)->routes, i); } -guint32 nm_ip4_config_get_num_static_routes (NMIP4Config *config) +guint32 nm_ip4_config_get_num_routes (NMIP4Config *config) { g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - return g_slist_length (NM_IP4_CONFIG_GET_PRIVATE (config)->static_routes); + return g_slist_length (NM_IP4_CONFIG_GET_PRIVATE (config)->routes); } +void nm_ip4_config_reset_routes (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + g_slist_foreach (priv->routes, (GFunc) g_free, NULL); + priv->routes = NULL; +} void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain) { @@ -572,7 +582,7 @@ finalize (GObject *object) g_ptr_array_free (priv->domains, TRUE); g_ptr_array_free (priv->searches, TRUE); g_array_free (priv->nis_servers, TRUE); - nm_utils_slist_free (priv->static_routes, g_free); + nm_utils_slist_free (priv->routes, g_free); } static void @@ -629,8 +639,8 @@ get_property (GObject *object, guint prop_id, case PROP_NIS_SERVERS: g_value_set_boxed (value, priv->nis_servers); break; - case PROP_STATIC_ROUTES: - ip4_addresses_to_gvalue (priv->static_routes, value); + case PROP_ROUTES: + ip4_addresses_to_gvalue (priv->routes, value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -694,10 +704,10 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) G_PARAM_READABLE)); g_object_class_install_property - (object_class, PROP_STATIC_ROUTES, - g_param_spec_boxed (NM_IP4_CONFIG_STATIC_ROUTES, - "Static routes", - "Static routes", + (object_class, PROP_ROUTES, + g_param_spec_boxed (NM_IP4_CONFIG_ROUTES, + "Routes", + "Routes", DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, G_PARAM_READABLE)); diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index e071dd8e9..00f0f1620 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -50,7 +50,7 @@ typedef struct { #define NM_IP4_CONFIG_DOMAINS "domains" #define NM_IP4_CONFIG_NIS_DOMAIN "nis-domain" #define NM_IP4_CONFIG_NIS_SERVERS "nis-servers" -#define NM_IP4_CONFIG_STATIC_ROUTES "static-routes" +#define NM_IP4_CONFIG_ROUTES "routes" GType nm_ip4_config_get_type (void); @@ -76,11 +76,12 @@ void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis_server); guint32 nm_ip4_config_get_nis_server (NMIP4Config *config, guint i); guint32 nm_ip4_config_get_num_nis_servers (NMIP4Config *config); -void nm_ip4_config_take_static_route (NMIP4Config *config, NMSettingIP4Address *address); -void nm_ip4_config_add_static_route (NMIP4Config *config, NMSettingIP4Address *address); -void nm_ip4_config_replace_static_route (NMIP4Config *config, guint32 i, NMSettingIP4Address *new_address); -const NMSettingIP4Address * nm_ip4_config_get_static_route (NMIP4Config *config, guint32 i); -guint32 nm_ip4_config_get_num_static_routes (NMIP4Config *config); +void nm_ip4_config_take_route (NMIP4Config *config, NMSettingIP4Route *route); +void nm_ip4_config_add_route (NMIP4Config *config, NMSettingIP4Route *route); +void nm_ip4_config_replace_route (NMIP4Config *config, guint32 i, NMSettingIP4Route *new_route); +const NMSettingIP4Route * nm_ip4_config_get_route (NMIP4Config *config, guint32 i); +guint32 nm_ip4_config_get_num_routes (NMIP4Config *config); +void nm_ip4_config_reset_routes (NMIP4Config *config); void nm_ip4_config_set_hostname (NMIP4Config *config, const char *hostname); const char * nm_ip4_config_get_hostname (NMIP4Config *config); diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 0e93e1e49..be32ead55 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -299,13 +299,15 @@ print_vpn_config (NMIP4Config *config, ip_address_to_string (nm_ip4_config_get_ptp_address (config))); nm_info ("Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (config)); - num = nm_ip4_config_get_num_static_routes (config); + num = nm_ip4_config_get_num_routes (config); for (i = 0; i < num; i++) { - addr = nm_ip4_config_get_static_route (config, i); - nm_info ("Static Route: %s/%d Gateway: %s", - ip_address_to_string (addr->address), - addr->prefix, - ip_address_to_string (addr->gateway)); + const NMSettingIP4Route *route; + + route = nm_ip4_config_get_route (config, i); + nm_info ("Static Route: %s/%d Next Hop: %s", + ip_address_to_string (route->address), + route->prefix, + ip_address_to_string (route->next_hop)); } num = nm_ip4_config_get_num_nameservers (config); @@ -321,57 +323,6 @@ print_vpn_config (NMIP4Config *config, nm_info ("-----------------------------------------"); } -static void -merge_vpn_routes (NMVPNConnection *connection, NMIP4Config *config) -{ - NMSettingVPN *setting; - GSList *iter; - - setting = NM_SETTING_VPN (nm_connection_get_setting (NM_VPN_CONNECTION_GET_PRIVATE (connection)->connection, - NM_TYPE_SETTING_VPN)); - - /* FIXME: Shouldn't the routes from user (NMSettingVPN) be inserted in the beginning - instead of appending to the end? - */ - - for (iter = setting->routes; iter; iter = iter->next) { - struct in_addr tmp; - char *p, *route; - long int prefix = 32; - - route = g_strdup ((char *) iter->data); - p = strchr (route, '/'); - if (!p || !(*(p + 1))) { - nm_warning ("Ignoring invalid route '%s'", route); - goto next; - } - - errno = 0; - prefix = strtol (p + 1, NULL, 10); - if (errno || prefix <= 0 || prefix > 32) { - nm_warning ("Ignoring invalid route '%s'", route); - goto next; - } - - /* don't pass the prefix to inet_pton() */ - *p = '\0'; - if (inet_pton (AF_INET, route, &tmp) > 0) { - NMSettingIP4Address *addr; - - addr = g_new0 (NMSettingIP4Address, 1); - addr->address = tmp.s_addr; - addr->prefix = (guint32) prefix; - addr->gateway = 0; - - nm_ip4_config_take_static_route (config, addr); - } else - nm_warning ("Ignoring invalid route '%s'", route); - -next: - g_free (route); - } -} - static void nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, GHashTable *config_hash, @@ -463,9 +414,9 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, GSList *routes; GSList *iter; - routes = nm_utils_ip4_addresses_from_gvalue (val); + routes = nm_utils_ip4_routes_from_gvalue (val); for (iter = routes; iter; iter = iter->next) - nm_ip4_config_take_static_route (config, (NMSettingIP4Address *) iter->data); + nm_ip4_config_take_route (config, (NMSettingIP4Route *) iter->data); g_slist_free (routes); } @@ -478,7 +429,6 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, /* Merge in user overrides from the NMConnection's IPv4 setting */ s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_IP4_CONFIG)); nm_utils_merge_ip4_config (config, s_ip4); - merge_vpn_routes (connection, config); if (nm_system_vpn_device_set_from_ip4_config (priv->parent_dev, priv->tundev, priv->ip4_config)) { nm_info ("VPN connection '%s' (IP Config Get) complete.", diff --git a/system-settings/plugins/ifcfg-fedora/reader.c b/system-settings/plugins/ifcfg-fedora/reader.c index 83ade7981..0f926cce1 100644 --- a/system-settings/plugins/ifcfg-fedora/reader.c +++ b/system-settings/plugins/ifcfg-fedora/reader.c @@ -238,7 +238,7 @@ make_ip4_setting (shvarFile *ifcfg, GError **error) /* Yay, let's make an IP4 config */ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); s_ip4->method = g_strdup (method); - s_ip4->ignore_dhcp_dns = !svTrueValue (ifcfg, "PEERDNS", 1); + s_ip4->ignore_auto_dns = !svTrueValue (ifcfg, "PEERDNS", 1); /* DHCP hostname for 'send host-name' option */ if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { diff --git a/system-settings/plugins/keyfile/reader.c b/system-settings/plugins/keyfile/reader.c index ef6c7ee59..14b974ea7 100644 --- a/system-settings/plugins/keyfile/reader.c +++ b/system-settings/plugins/keyfile/reader.c @@ -61,6 +61,22 @@ read_array_of_uint (GKeyFile *file, return TRUE; } +static gboolean +get_one_int (const char *str, guint32 max_val, const char *key_name, guint32 *out) +{ + long tmp; + + errno = 0; + tmp = strtol (str, NULL, 10); + if (errno || (tmp < 0) || (tmp > max_val)) { + g_warning ("%s: ignoring invalid IPv4 %s item '%s'", __func__, key_name, str); + return FALSE; + } + + *out = (guint32) tmp; + return TRUE; +} + static void free_one_address (gpointer data, gpointer user_data) { @@ -69,8 +85,8 @@ free_one_address (gpointer data, gpointer user_data) static GPtrArray * read_addresses (GKeyFile *file, - const char *setting_name, - const char *key) + const char *setting_name, + const char *key) { GPtrArray *addresses; int i = 0; @@ -105,18 +121,14 @@ read_addresses (GKeyFile *file, struct in_addr addr; if (j == 1) { - /* prefix */ - long tmp_prefix; - guint32 prefix; + guint32 prefix = 0; - errno = 0; - tmp_prefix = strtol (*iter, NULL, 10); - if (errno || (tmp_prefix < 0) || (tmp_prefix > 32)) { - g_warning ("%s: ignoring invalid IPv4 %s prefix '%s'", __func__, key_name, *iter); + /* prefix */ + if (!get_one_int (*iter, 32, key_name, &prefix)) { g_array_free (address, TRUE); goto next; } - prefix = (guint32) tmp_prefix; + g_array_append_val (address, prefix); } else { /* address and gateway */ @@ -148,32 +160,132 @@ next: return addresses; } +static void +free_one_route (gpointer data, gpointer user_data) +{ + g_array_free ((GArray *) data, TRUE); +} + +static GPtrArray * +read_routes (GKeyFile *file, + const char *setting_name, + const char *key) +{ + GPtrArray *routes; + int i = 0; + + routes = g_ptr_array_sized_new (3); + + /* Look for individual routes */ + while (i++ < 1000) { + gchar **tmp, **iter; + char *key_name; + gsize length = 0; + int ret; + GArray *route; + int j; + + key_name = g_strdup_printf ("%s%d", key, i); + tmp = g_key_file_get_string_list (file, setting_name, key_name, &length, NULL); + g_free (key_name); + + if (!tmp || !length) + break; /* all done */ + + if (length != 4) { + g_warning ("%s: ignoring invalid IPv4 route item '%s'", __func__, key_name); + goto next; + } + + /* convert the string array into IP addresses */ + route = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4); + for (iter = tmp, j = 0; *iter; iter++, j++) { + struct in_addr addr; + + if (j == 1) { + guint32 prefix = 0; + + /* prefix */ + if (!get_one_int (*iter, 32, key_name, &prefix)) { + g_array_free (route, TRUE); + goto next; + } + + g_array_append_val (route, prefix); + } else if (j == 3) { + guint32 metric = 0; + + /* prefix */ + if (!get_one_int (*iter, G_MAXUINT32, key_name, &metric)) { + g_array_free (route, TRUE); + goto next; + } + + g_array_append_val (route, metric); + } else { + /* address and next hop */ + ret = inet_pton (AF_INET, *iter, &addr); + if (ret <= 0) { + g_warning ("%s: ignoring invalid IPv4 %s element '%s'", __func__, key_name, *iter); + g_array_free (route, TRUE); + goto next; + } + g_array_append_val (route, addr.s_addr); + } + } + g_ptr_array_add (routes, route); + +next: + g_strfreev (tmp); + } + + if (routes->len < 1) { + g_ptr_array_free (routes, TRUE); + routes = NULL; + } + + return routes; +} + static gboolean read_array_of_array_of_uint (GKeyFile *file, NMSetting *setting, const char *key) { - GPtrArray *addresses; + gboolean success = FALSE; /* Only handle IPv4 addresses and routes for now */ - if ( !NM_IS_SETTING_IP4_CONFIG (setting) || - (strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES) && - strcmp (key, NM_SETTING_IP4_CONFIG_ROUTES))) - return FALSE; + if (!NM_IS_SETTING_IP4_CONFIG (setting)) + return FALSE; - addresses = read_addresses (file, setting->name, key); + if (!strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) { + GPtrArray *addresses; - /* Work around for previous syntax */ - if (!addresses && !strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) - addresses = read_addresses (file, setting->name, "address"); + addresses = read_addresses (file, setting->name, key); - if (addresses) { - g_object_set (setting, key, addresses, NULL); - g_ptr_array_foreach (addresses, free_one_address, NULL); - g_ptr_array_free (addresses, TRUE); + /* Work around for previous syntax */ + if (!addresses && !strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) + addresses = read_addresses (file, setting->name, "address"); + + if (addresses) { + g_object_set (setting, key, addresses, NULL); + g_ptr_array_foreach (addresses, free_one_address, NULL); + g_ptr_array_free (addresses, TRUE); + } + success = TRUE; + } else if (!strcmp (key, NM_SETTING_IP4_CONFIG_ROUTES)) { + GPtrArray *routes; + + routes = read_routes (file, setting->name, key); + if (routes) { + g_object_set (setting, key, routes, NULL); + g_ptr_array_foreach (routes, free_one_route, NULL); + g_ptr_array_free (routes, TRUE); + } + success = TRUE; } - return TRUE; + return success; } static void diff --git a/system-settings/plugins/keyfile/writer.c b/system-settings/plugins/keyfile/writer.c index 4174b42e8..eb5508d5b 100644 --- a/system-settings/plugins/keyfile/writer.c +++ b/system-settings/plugins/keyfile/writer.c @@ -62,6 +62,61 @@ write_array_of_uint (GKeyFile *file, return TRUE; } +static void +write_ip4_values (GKeyFile *file, + const char *setting_name, + const char *key, + GPtrArray *array, + guint32 tuple_len, + guint32 addr1_pos, + guint32 addr2_pos) +{ + char **list = NULL; + int i, j; + + list = g_malloc (tuple_len); + + for (i = 0, j = 0; i < array->len; i++, j++) { + GArray *tuple = g_ptr_array_index (array, i); + gboolean success = TRUE; + char *key_name; + int k; + + memset (list, 0, tuple_len); + + for (k = 0; k < tuple_len; k++) { + if (k == addr1_pos || k == addr2_pos) { + char buf[INET_ADDRSTRLEN + 1]; + struct in_addr addr; + + /* IP addresses */ + addr.s_addr = g_array_index (tuple, guint32, k); + if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) { + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + success = FALSE; + break; + } else { + list[k] = g_strdup (buf); + } + } else { + /* prefix, metric */ + list[k] = g_strdup_printf ("%d", g_array_index (tuple, guint32, k)); + } + } + + if (success) { + key_name = g_strdup_printf ("%s%d", key, j + 1); + g_key_file_set_string_list (file, setting_name, key_name, (const char **) list, tuple_len); + g_free (key_name); + } + + for (k = 0; k < tuple_len; k++) + g_free (list[k]); + } + g_free (list); +} + static gboolean write_array_of_array_of_uint (GKeyFile *file, NMSetting *setting, @@ -69,58 +124,19 @@ write_array_of_array_of_uint (GKeyFile *file, const GValue *value) { GPtrArray *array; - int i, j; /* Only handle IPv4 addresses and routes for now */ - if ( !NM_IS_SETTING_IP4_CONFIG (setting) || - (strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES) && - strcmp (key, NM_SETTING_IP4_CONFIG_ROUTES))) - return FALSE; + if (!NM_IS_SETTING_IP4_CONFIG (setting)) + return FALSE; array = (GPtrArray *) g_value_get_boxed (value); if (!array || !array->len) return TRUE; - for (i = 0, j = 0; i < array->len; i++, j++) { - GArray *tuple = g_ptr_array_index (array, i); - char buf[INET_ADDRSTRLEN + 1]; - struct in_addr addr; - char *list[3] = { NULL, NULL, NULL }; - char *key_name; - - /* Address */ - addr.s_addr = g_array_index (tuple, guint32, 0); - if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) { - nm_warning ("%s: error converting IP4 address 0x%X", - __func__, ntohl (addr.s_addr)); - list[0] = NULL; - } else { - list[0] = g_strdup (buf); - } - - /* Prefix */ - list[1] = g_strdup_printf ("%d", g_array_index (tuple, guint32, 1)); - - /* Gateway */ - addr.s_addr = g_array_index (tuple, guint32, 2); - if (addr.s_addr) { - if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) { - nm_warning ("%s: error converting IP4 address 0x%X", - __func__, ntohl (addr.s_addr)); - list[2] = NULL; - } else { - list[2] = g_strdup (buf); - } - } - - key_name = g_strdup_printf ("%s%d", key, j + 1); - g_key_file_set_string_list (file, setting->name, key_name, (const char **) list, list[2] ? 3 : 2); - g_free (key_name); - - g_free (list[0]); - g_free (list[1]); - g_free (list[2]); - } + if (!strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) + write_ip4_values (file, setting->name, key, array, 3, 0, 2); + else if (!strcmp (key, NM_SETTING_IP4_CONFIG_ROUTES)) + write_ip4_values (file, setting->name, key, array, 4, 0, 2); return TRUE; }