diff --git a/ChangeLog b/ChangeLog index 015ed0294..0c53e8592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2008-05-06 Dan Williams + + * src/dhcp-manager/nm-dhcp-manager.c + - (nm_dhcp_manager_get_ip4_config): clean up; update for changes to + NMIP4Config to support multiple IP addresses + + * src/NetworkManagerUtils.c + - (nm_utils_merge_ip4_config): update for multiple IP addresses + + * src/nm-ip4-config.c + src/nm-ip4-config.h + - Store a list of IPv4 address/netmask/gateway tuples + - (nm_ip4_config_get_gateway, nm_ip4_config_set_gateway, + nm_ip4_config_get_netmask, nm_ip4_config_set_netmask, + nm_ip4_config_get_broadcast, nm_ip4_config_set_broadcast, + nm_ip4_config_set_address): remove + - (nm_ip4_config_take_address, nm_ip4_config_add_address, + nm_ip4_config_replace_address, nm_ip4_config_get_num_addresses): + new functions; handle multiple IPv4 addresses + + * src/nm-device.c + src/ppp-manager/nm-ppp-manager.c + src/vpn-manager/nm-vpn-connection.c + src/NetworkManagerPolicy.c + test/nm-tool.c + libnm-glib/libnm-glib-test.c + - update for changes to NMIP4Config for multiple IPv4 addresses + + * src/NetworkManagerSystem.c + - (nm_system_device_set_ip4_route): don't add the route if any address + is on the same subnet as the destination + - (check_one_address): ignore the exact match, just match family and + interface index + - (add_ip4_addresses): add all IPv4 addresses in an NMIP4Config to + an interface + - (nm_system_device_set_from_ip4_config): use add_ip4_addresses() + - (nm_system_vpn_device_set_from_ip4_config): use add_ip4_addresses() + + * introspection/nm-ip4-config.xml + - Remove 'address', 'gateway', 'netmask', and 'broadcast' properties + - Add 'addresses' property which is an array of (uuu) tuples of + address/netmask/gateway + + * libnm-util/nm-setting-ip4-config.c + - (set_property): use ip-address <-> GValue converters from nm-utils.c + + * libnm-glib/nm-ip4-config.c + libnm-glib/nm-ip4-config.h + - Handle D-Bus interface changes to support multiple IP addresses + +2008-05-06 Dan Williams + + * libnm-util/nm-utils.c + libnm-util/nm-utils.h + - (nm_utils_ip4_addresses_from_gvalue, + nm_utils_ip4_addresses_to_gvalue): new functions + 2008-05-06 Tambet Ingo * libnm-glib/nm-dbus-settings.c (fetch_connections_done): Don't leak diff --git a/introspection/nm-ip4-config.xml b/introspection/nm-ip4-config.xml index 88671fe20..8e3bf573c 100644 --- a/introspection/nm-ip4-config.xml +++ b/introspection/nm-ip4-config.xml @@ -2,17 +2,8 @@ - - IPv4 address. FIXME: what about multiple addresses? - - - Default gateway. - - - Network mask of this network. - - - Broadcast address of this network. + + Tuples of IPv4 address/netmask/gateway. The gateway is optional, if not given should be 0. The hostname associated with this IPv4 address. FIXME: what about multiple hostnames? diff --git a/libnm-glib/libnm-glib-test.c b/libnm-glib/libnm-glib-test.c index c5247c739..23dff096b 100644 --- a/libnm-glib/libnm-glib-test.c +++ b/libnm-glib/libnm-glib-test.c @@ -13,6 +13,7 @@ #include "nm-device-802-11-wireless.h" #include "nm-utils.h" #include "nm-active-connection.h" +#include "nm-setting-ip4-config.h" static gboolean test_wireless_enabled (NMClient *client) @@ -61,23 +62,24 @@ dump_ip4_config (NMIP4Config *cfg) char *tmp; const GArray *array; const GPtrArray *ptr_array; + GSList *iter; int i; - tmp = ip4_address_as_string (nm_ip4_config_get_address (cfg)); - g_print ("IP4 address: %s\n", tmp); - g_free (tmp); + for (iter = (GSList *) nm_ip4_config_get_addresses (cfg); iter; iter = g_slist_next (iter)) { + NMSettingIP4Address *addr = iter->data; - tmp = ip4_address_as_string (nm_ip4_config_get_gateway (cfg)); - g_print ("IP4 gateway: %s\n", tmp); - g_free (tmp); + tmp = ip4_address_as_string (addr->address); + g_print ("IP4 address: %s\n", tmp); + g_free (tmp); - tmp = ip4_address_as_string (nm_ip4_config_get_netmask (cfg)); - g_print ("IP4 netmask: %s\n", tmp); - g_free (tmp); + tmp = ip4_address_as_string (addr->netmask); + g_print ("IP4 netmask: %s\n", tmp); + g_free (tmp); - tmp = ip4_address_as_string (nm_ip4_config_get_broadcast (cfg)); - g_print ("IP4 broadcast: %s\n", tmp); - g_free (tmp); + tmp = ip4_address_as_string (addr->gateway); + g_print ("IP4 gateway: %s\n\n", tmp); + g_free (tmp); + } g_print ("IP4 hostname: %s\n", nm_ip4_config_get_hostname (cfg)); diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c index 51426c8a7..6eb2c522c 100644 --- a/libnm-glib/nm-ip4-config.c +++ b/libnm-glib/nm-ip4-config.c @@ -4,6 +4,7 @@ #include "NetworkManager.h" #include "nm-types-private.h" #include "nm-object-private.h" +#include "nm-utils.h" G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_OBJECT) @@ -12,10 +13,7 @@ G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_OBJECT) typedef struct { DBusGProxy *proxy; - guint32 address; - guint32 gateway; - guint32 netmask; - guint32 broadcast; + GSList *addresses; char *hostname; GArray *nameservers; GPtrArray *domains; @@ -25,10 +23,7 @@ typedef struct { enum { PROP_0, - PROP_ADDRESS, - PROP_GATEWAY, - PROP_NETMASK, - PROP_BROADCAST, + PROP_ADDRESSES, PROP_HOSTNAME, PROP_NAMESERVERS, PROP_DOMAINS, @@ -43,6 +38,21 @@ nm_ip4_config_init (NMIP4Config *config) { } +static gboolean +demarshal_ip4_address_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); + + g_slist_foreach (priv->addresses, (GFunc) g_free, NULL); + g_slist_free (priv->addresses); + priv->addresses = NULL; + + priv->addresses = nm_utils_ip4_addresses_from_gvalue (value); + nm_object_queue_notify (object, NM_IP4_CONFIG_ADDRESSES); + + return TRUE; +} + static gboolean demarshal_ip4_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) { @@ -71,10 +81,7 @@ register_for_property_changed (NMIP4Config *config) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); const NMPropertiesChangedInfo property_changed_info[] = { - { NM_IP4_CONFIG_ADDRESS, nm_object_demarshal_generic, &priv->address }, - { NM_IP4_CONFIG_GATEWAY, nm_object_demarshal_generic, &priv->gateway }, - { NM_IP4_CONFIG_NETMASK, nm_object_demarshal_generic, &priv->netmask }, - { NM_IP4_CONFIG_BROADCAST, nm_object_demarshal_generic, &priv->broadcast }, + { NM_IP4_CONFIG_ADDRESSES, demarshal_ip4_address_array, &priv->addresses }, { NM_IP4_CONFIG_HOSTNAME, nm_object_demarshal_generic, &priv->hostname }, { NM_IP4_CONFIG_NAMESERVERS, demarshal_ip4_array, &priv->nameservers }, { NM_IP4_CONFIG_DOMAINS, demarshal_domains, &priv->domains }, @@ -121,6 +128,9 @@ finalize (GObject *object) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); + g_slist_foreach (priv->addresses, (GFunc) g_free, NULL); + g_slist_free (priv->addresses); + g_free (priv->hostname); g_free (priv->nis_domain); if (priv->nameservers) @@ -143,19 +153,11 @@ get_property (GObject *object, GParamSpec *pspec) { NMIP4Config *self = NM_IP4_CONFIG (object); + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); switch (prop_id) { - case PROP_ADDRESS: - g_value_set_uint (value, nm_ip4_config_get_address (self)); - break; - case PROP_GATEWAY: - g_value_set_uint (value, nm_ip4_config_get_gateway (self)); - break; - case PROP_NETMASK: - g_value_set_uint (value, nm_ip4_config_get_netmask (self)); - break; - case PROP_BROADCAST: - g_value_set_uint (value, nm_ip4_config_get_broadcast (self)); + case PROP_ADDRESSES: + nm_utils_ip4_addresses_to_gvalue (priv->addresses, value); break; case PROP_HOSTNAME: g_value_set_string (value, nm_ip4_config_get_hostname (self)); @@ -192,36 +194,11 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) /* properties */ g_object_class_install_property - (object_class, PROP_ADDRESS, - g_param_spec_uint (NM_IP4_CONFIG_ADDRESS, - "Address", - "Address", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_GATEWAY, - g_param_spec_uint (NM_IP4_CONFIG_GATEWAY, - "Gateway", - "Gateway", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_NETMASK, - g_param_spec_uint (NM_IP4_CONFIG_NETMASK, - "Netmask", - "Netmask", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_BROADCAST, - g_param_spec_uint (NM_IP4_CONFIG_BROADCAST, - "Broadcast", - "Broadcast", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); + (object_class, PROP_ADDRESSES, + g_param_spec_pointer (NM_IP4_CONFIG_ADDRESSES, + "Addresses", + "Addresses", + G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_HOSTNAME, @@ -273,72 +250,29 @@ nm_ip4_config_new (DBusGConnection *connection, const char *object_path) NULL); } -guint32 -nm_ip4_config_get_address (NMIP4Config *config) +const GSList * +nm_ip4_config_get_addresses (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->address) { - priv->address = nm_object_get_uint_property (NM_OBJECT (config), - NM_DBUS_INTERFACE_IP4_CONFIG, - "Address"); + if (priv->addresses) + return priv->addresses; + + if (!nm_object_get_property (NM_OBJECT (config), + "org.freedesktop.DBus.Properties", + "Addresses", + &value)) { + return NULL; } - return priv->address; -} + demarshal_ip4_address_array (NM_OBJECT (config), NULL, &value, &priv->addresses); + g_value_unset (&value); -guint32 -nm_ip4_config_get_gateway (NMIP4Config *config) -{ - NMIP4ConfigPrivate *priv; - - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (!priv->gateway) { - priv->gateway = nm_object_get_uint_property (NM_OBJECT (config), - NM_DBUS_INTERFACE_IP4_CONFIG, - "Gateway"); - } - - return priv->gateway; -} - -guint32 -nm_ip4_config_get_netmask (NMIP4Config *config) -{ - NMIP4ConfigPrivate *priv; - - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (!priv->netmask) { - priv->netmask = nm_object_get_uint_property (NM_OBJECT (config), - NM_DBUS_INTERFACE_IP4_CONFIG, - "Netmask"); - } - - return priv->netmask; -} - -guint32 -nm_ip4_config_get_broadcast (NMIP4Config *config) -{ - NMIP4ConfigPrivate *priv; - - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (!priv->broadcast) { - priv->broadcast = nm_object_get_uint_property (NM_OBJECT (config), - NM_DBUS_INTERFACE_IP4_CONFIG, - "Broadcast"); - } - - return priv->broadcast; + return priv->addresses; } const char * diff --git a/libnm-glib/nm-ip4-config.h b/libnm-glib/nm-ip4-config.h index b4f921580..18fdeb825 100644 --- a/libnm-glib/nm-ip4-config.h +++ b/libnm-glib/nm-ip4-config.h @@ -23,10 +23,7 @@ typedef struct { NMObjectClass parent; } NMIP4ConfigClass; -#define NM_IP4_CONFIG_ADDRESS "address" -#define NM_IP4_CONFIG_GATEWAY "gateway" -#define NM_IP4_CONFIG_NETMASK "netmask" -#define NM_IP4_CONFIG_BROADCAST "broadcast" +#define NM_IP4_CONFIG_ADDRESSES "addresses" #define NM_IP4_CONFIG_HOSTNAME "hostname" #define NM_IP4_CONFIG_NAMESERVERS "nameservers" #define NM_IP4_CONFIG_DOMAINS "domains" @@ -37,10 +34,7 @@ GType nm_ip4_config_get_type (void); GObject *nm_ip4_config_new (DBusGConnection *connection, const char *object_path); -guint32 nm_ip4_config_get_address (NMIP4Config *config); -guint32 nm_ip4_config_get_gateway (NMIP4Config *config); -guint32 nm_ip4_config_get_netmask (NMIP4Config *config); -guint32 nm_ip4_config_get_broadcast (NMIP4Config *config); +const GSList * nm_ip4_config_get_addresses (NMIP4Config *config); 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); diff --git a/libnm-util/nm-setting-ip4-config.c b/libnm-util/nm-setting-ip4-config.c index 17d4e9e8b..1e2c3c378 100644 --- a/libnm-util/nm-setting-ip4-config.c +++ b/libnm-util/nm-setting-ip4-config.c @@ -87,64 +87,6 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object); } -static GSList * -ip4_addresses_from_gvalue (const GValue *value) -{ - GPtrArray *addresses; - int i; - GSList *list = NULL; - - addresses = (GPtrArray *) g_value_get_boxed (value); - for (i = 0; addresses && (i < addresses->len); i++) { - GArray *array = (GArray *) g_ptr_array_index (addresses, i); - - if (array->len == 2 || array->len == 3) { - NMSettingIP4Address *ip4_addr; - - ip4_addr = g_new0 (NMSettingIP4Address, 1); - ip4_addr->address = g_array_index (array, guint32, 0); - ip4_addr->netmask = g_array_index (array, guint32, 1); - - if (array->len == 3) - ip4_addr->gateway = g_array_index (array, guint32, 2); - - list = g_slist_prepend (list, ip4_addr); - } else - nm_warning ("Ignoring invalid IP4 address"); - } - - return g_slist_reverse (list); -} - -static void -ip4_addresses_to_gvalue (GSList *list, GValue *value) -{ - GPtrArray *addresses; - GSList *iter; - - addresses = g_ptr_array_new (); - - for (iter = list; iter; iter = iter->next) { - NMSettingIP4Address *ip4_addr = (NMSettingIP4Address *) iter->data; - GArray *array; - const guint32 empty_val = 0; - - array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); - - g_array_append_val (array, ip4_addr->address); - g_array_append_val (array, ip4_addr->netmask); - - if (ip4_addr->gateway) - g_array_append_val (array, ip4_addr->gateway); - else - g_array_append_val (array, empty_val); - - g_ptr_array_add (addresses, array); - } - - g_value_take_boxed (value, addresses); -} - static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) @@ -167,7 +109,7 @@ set_property (GObject *object, guint prop_id, break; case PROP_ADDRESSES: nm_utils_slist_free (setting->addresses, g_free); - setting->addresses = ip4_addresses_from_gvalue (value); + setting->addresses = nm_utils_ip4_addresses_from_gvalue (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -192,7 +134,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boxed (value, setting->dns_search); break; case PROP_ADDRESSES: - ip4_addresses_to_gvalue (setting->addresses, value); + nm_utils_ip4_addresses_to_gvalue (setting->addresses, value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index e77ef069c..fcb54f38d 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -86,10 +86,11 @@ update_default_route (NMPolicy *policy, NMDevice *new) nm_system_device_replace_default_ip4_route (ip_iface, 0, 0); } else { NMIP4Config *config; + const NMSettingIP4Address *def_addr; config = nm_device_get_ip4_config (new); - nm_system_device_replace_default_ip4_route (ip_iface, nm_ip4_config_get_gateway (config), - nm_ip4_config_get_mss (config)); + def_addr = nm_ip4_config_get_address (config, 0); + nm_system_device_replace_default_ip4_route (ip_iface, def_addr->gateway, nm_ip4_config_get_mss (config)); } } @@ -129,6 +130,8 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update) NMIP4Config *ip4_config; NMSettingIP4Config *s_ip4; guint32 prio; + guint i; + gboolean have_gateway = FALSE; if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED) continue; @@ -147,8 +150,18 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update) if (s_ip4 && !strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_AUTOIP)) continue; - /* FIXME: handle more than one IP address */ - if (!nm_ip4_config_get_gateway (ip4_config)) + /* Make sure at least one of this device's IP addresses has a gateway */ + for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) { + const NMSettingIP4Address *addr; + + addr = nm_ip4_config_get_address (ip4_config, i); + if (addr->gateway) { + have_gateway = TRUE; + break; + } + } + + if (!have_gateway) continue; prio = get_device_priority (dev); diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index e64f0311b..30d4a78ed 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -80,7 +80,7 @@ nm_system_device_set_ip4_route (const char *iface, struct nl_handle *nlh = NULL; struct nl_addr *gw_addr = NULL; struct nl_addr *dest_addr = NULL; - int err, iface_idx; + int err, iface_idx, i; /* * Zero is not a legal gateway and the ioctl will fail. But zero is a @@ -93,10 +93,15 @@ nm_system_device_set_ip4_route (const char *iface, /* * Do not add the route if the destination is on the same subnet. */ - if (iface_config && - ((guint32)ip4_dest & nm_ip4_config_get_netmask (iface_config)) == - (nm_ip4_config_get_address (iface_config) & nm_ip4_config_get_netmask (iface_config))) - return TRUE; + if (iface_config) { + for (i = 0; i < nm_ip4_config_get_num_addresses (iface_config); i++) { + const NMSettingIP4Address *cfg_addr; + + cfg_addr = nm_ip4_config_get_address (iface_config, i); + if ((ip4_dest & cfg_addr->netmask) == (cfg_addr->address & cfg_addr->netmask)) + return TRUE; + } + } nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, FALSE); @@ -186,8 +191,9 @@ out: typedef struct { const char *iface; + int ifindex; + int family; struct nl_handle *nlh; - struct rtnl_addr *match; } AddrCheckData; static void @@ -197,23 +203,78 @@ check_one_address (struct nl_object *object, void *user_data) struct rtnl_addr *addr = (struct rtnl_addr *) object; int err; - /* Delete addresses on this interface which don't match the one we - * are about to add to it. - */ - if (nl_object_identical ((struct nl_object *) data->match, (struct nl_object *) addr)) - return; - if (rtnl_addr_get_ifindex (addr) != rtnl_addr_get_ifindex (data->match)) - return; - if (rtnl_addr_get_family (addr) != rtnl_addr_get_family (data->match)) - return; - - err = rtnl_addr_delete (data->nlh, addr, 0); - if (err < 0) { - nm_warning ("(%s) error %d returned from rtnl_addr_delete(): %s", - data->iface, err, nl_geterror()); + if (rtnl_addr_get_ifindex (addr) == data->ifindex) { + if (rtnl_addr_get_family (addr) == data->family) { + err = rtnl_addr_delete (data->nlh, addr, 0); + if (err < 0) { + nm_warning ("(%s) error %d returned from rtnl_addr_delete(): %s", + data->iface, err, nl_geterror()); + } + } } } +static gboolean +add_ip4_addresses (NMIP4Config *config, const char *iface) +{ + struct nl_handle *nlh = NULL; + struct nl_cache *addr_cache = NULL; + int i, iface_idx, err; + AddrCheckData check_data; + guint32 flags = 0; + gboolean did_gw = FALSE; + + nlh = nm_netlink_get_default_handle (); + if (!nlh) + return FALSE; + + addr_cache = rtnl_addr_alloc_cache (nlh); + if (!addr_cache) + return FALSE; + nl_cache_mngt_provide (addr_cache); + + iface_idx = nm_netlink_iface_to_index (iface); + + memset (&check_data, 0, sizeof (check_data)); + check_data.iface = iface; + check_data.nlh = nlh; + check_data.ifindex = iface_idx; + check_data.family = AF_INET; + + /* Remove all existing IPv4 addresses */ + nl_cache_foreach (addr_cache, check_one_address, &check_data); + + for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) { + const NMSettingIP4Address *addr; + struct rtnl_addr *nl_addr = NULL; + + addr = nm_ip4_config_get_address (config, i); + g_assert (addr); + + flags = NM_RTNL_ADDR_DEFAULT; + if (addr->gateway && !did_gw) { + if (nm_ip4_config_get_ptp_address (config)) + flags |= NM_RTNL_ADDR_PTP_ADDR; + did_gw = TRUE; + } + + nl_addr = nm_ip4_config_to_rtnl_addr (config, i, flags); + if (!nl_addr) { + nm_warning ("couldn't create rtnl address!\n"); + continue; + } + rtnl_addr_set_ifindex (nl_addr, iface_idx); + + if ((err = rtnl_addr_add (nlh, nl_addr, 0)) < 0) + nm_warning ("(%s) error %d returned from rtnl_addr_add():\n%s", iface, err, nl_geterror()); + + rtnl_addr_put (nl_addr); + } + + nl_cache_free (addr_cache); + return TRUE; +} + /* * nm_system_device_set_from_ip4_config * @@ -225,48 +286,14 @@ nm_system_device_set_from_ip4_config (const char *iface, NMIP4Config *config, gboolean route_to_iface) { - struct nl_handle *nlh = NULL; - struct rtnl_addr *addr = NULL; - struct nl_cache *addr_cache = NULL; - int len, i, err; - guint32 flags; - AddrCheckData check_data; - gboolean success = FALSE; + int len, i; g_return_val_if_fail (iface != NULL, FALSE); g_return_val_if_fail (config != NULL, FALSE); - nlh = nm_netlink_get_default_handle (); - if (!nlh) + if (!add_ip4_addresses (config, iface)) return FALSE; - addr_cache = rtnl_addr_alloc_cache (nlh); - if (!addr_cache) - goto out; - nl_cache_mngt_provide (addr_cache); - - flags = NM_RTNL_ADDR_DEFAULT; - if (nm_ip4_config_get_ptp_address (config)) - flags |= NM_RTNL_ADDR_PTP_ADDR; - - addr = nm_ip4_config_to_rtnl_addr (config, flags); - if (!addr) { - nm_warning ("couldn't create rtnl address!\n"); - goto out; - } - rtnl_addr_set_ifindex (addr, nm_netlink_iface_to_index (iface)); - - memset (&check_data, 0, sizeof (check_data)); - check_data.iface = iface; - check_data.nlh = nlh; - check_data.match = addr; - - /* Remove all addresses except the one we're about to add */ - nl_cache_foreach (addr_cache, check_one_address, &check_data); - - if ((err = rtnl_addr_add (nlh, addr, 0)) < 0) - nm_warning ("(%s) error %d returned from rtnl_addr_add():\n%s", iface, err, nl_geterror()); - sleep (1); len = nm_ip4_config_get_num_static_routes (config); @@ -281,14 +308,7 @@ nm_system_device_set_from_ip4_config (const char *iface, if (nm_ip4_config_get_mtu (config)) nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config)); - success = TRUE; - -out: - if (addr) - rtnl_addr_put (addr); - if (addr_cache) - nl_cache_free (addr_cache); - return success; + return TRUE; } /* @@ -303,43 +323,45 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device, NMIP4Config *config, GSList *routes) { - NMIP4Config * ad_config = NULL; - struct nl_handle * nlh = NULL; - struct rtnl_addr * addr = NULL; + NMIP4Config *ad_config = NULL; NMNamedManager *named_mgr; - int iface_idx; + int i; g_return_val_if_fail (config != NULL, FALSE); /* Set up a route to the VPN gateway through the real network device */ if (active_device && (ad_config = nm_device_get_ip4_config (active_device))) { + guint32 ad_gw = 0, vpn_gw = 0; + const NMSettingIP4Address *tmp; + + for (i = 0; i < nm_ip4_config_get_num_addresses (ad_config); i++) { + tmp = nm_ip4_config_get_address (ad_config, i); + if (tmp->gateway) { + ad_gw = tmp->gateway; + break; + } + } + + for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) { + tmp = nm_ip4_config_get_address (config, i); + if (tmp->gateway) { + vpn_gw = tmp->gateway; + break; + } + } + nm_system_device_set_ip4_route (nm_device_get_ip_iface (active_device), - ad_config, - nm_ip4_config_get_gateway (ad_config), - nm_ip4_config_get_gateway (config), - 32, + ad_config, ad_gw, vpn_gw, 32, nm_ip4_config_get_mss (config)); } if (!iface || !strlen (iface)) goto out; - nlh = nm_netlink_get_default_handle (); - if (!nlh) - goto out; - nm_system_device_set_up_down_with_iface (iface, TRUE); - iface_idx = nm_netlink_iface_to_index (iface); - - if ((addr = nm_ip4_config_to_rtnl_addr (config, NM_RTNL_ADDR_PTP_DEFAULT))) { - int err = 0; - rtnl_addr_set_ifindex (addr, iface_idx); - if ((err = rtnl_addr_add (nlh, addr, 0)) < 0) - nm_warning ("error %d returned from rtnl_addr_add():\n%s", err, nl_geterror()); - rtnl_addr_put (addr); - } else - nm_warning ("couldn't create rtnl address!\n"); + if (!add_ip4_addresses (config, iface)) + goto out; /* Set the MTU */ if (nm_ip4_config_get_mtu (config)) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index c1e24e171..1c0989732 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -237,6 +237,8 @@ nm_ether_ntop (const struct ether_addr *mac) void nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) { + GSList *iter; + if (!setting) return; /* Defaults are just fine */ @@ -261,42 +263,44 @@ nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) } } - if (setting->dns_search) { - GSList *iter; + /* DNS search domains */ + for (iter = setting->dns_search; iter; iter = iter->next) { + int i; + gboolean found = FALSE; - for (iter = setting->dns_search; iter; iter = iter->next) { - int i; - gboolean found = FALSE; + /* Avoid dupes */ + for (i = 0; i < nm_ip4_config_get_num_searches (ip4_config); i++) { + const char *search = nm_ip4_config_get_search (ip4_config, i); - /* Avoid dupes */ - for (i = 0; i < nm_ip4_config_get_num_searches (ip4_config); i++) { - const char *search = nm_ip4_config_get_search (ip4_config, i); - - if (!strcmp (search, (char *) iter->data)) { - found = TRUE; - break; - } + if (!strcmp (search, (char *) iter->data)) { + found = TRUE; + break; } - - if (!found) - nm_ip4_config_add_search (ip4_config, (char *) iter->data); } + + if (!found) + nm_ip4_config_add_search (ip4_config, (char *) iter->data); } - if (setting->addresses) { - /* FIXME; add support for more than one set of address/netmask/gateway for NMIP4Config */ - NMSettingIP4Address *addr = (NMSettingIP4Address *) setting->addresses->data; + /* IPv4 addresses */ + for (iter = setting->addresses; iter; iter = g_slist_next (iter)) { + NMSettingIP4Address *setting_addr = (NMSettingIP4Address *) iter->data; + guint32 i, num; - /* Avoid dupes, but override if anything is different */ - if ( (nm_ip4_config_get_address (ip4_config) != addr->address) - || (nm_ip4_config_get_netmask (ip4_config) != addr->netmask) - || (addr->gateway && (nm_ip4_config_get_gateway (ip4_config) != addr->gateway))) { - nm_ip4_config_set_address (ip4_config, addr->address); - nm_ip4_config_set_netmask (ip4_config, addr->netmask); + num = nm_ip4_config_get_num_addresses (ip4_config); + for (i = 0; i < num; i++) { + const NMSettingIP4Address *cfg_addr; - if (addr->gateway) - nm_ip4_config_set_gateway (ip4_config, addr->gateway); + cfg_addr = nm_ip4_config_get_address (ip4_config, i); + /* Dupe, override with user-specified address */ + if (cfg_addr->address == setting_addr->address) { + nm_ip4_config_replace_address (ip4_config, i, setting_addr); + break; + } } + + if (i == num) + nm_ip4_config_add_address (ip4_config, setting_addr); } } diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index de82c1661..3f338e040 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -834,20 +834,10 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, { NMDHCPManagerPrivate *priv; NMDHCPDevice *device; - NMIP4Config * ip4_config = NULL; - guint32 ip4_address = 0; - guint32 ip4_netmask = 0; - guint32 ip4_broadcast = 0; - guint32 ip4_gateway = 0; - char * hostname = NULL; - char * domain = NULL; - char * search = NULL; - char * nameservers = NULL; - char * nis_domain = NULL; - char * nis_servers = NULL; - char * static_routes = NULL; - char * ip = NULL; //this is a general string that is used as a temporary place for ip(s) - char * mtu = NULL; + NMIP4Config *ip4_config = NULL; + NMSettingIP4Address *addr; + guint32 ip4_num = 0; + char *str = NULL; g_return_val_if_fail (NM_IS_DHCP_MANAGER (manager), NULL); g_return_val_if_fail (iface != NULL, NULL); @@ -865,82 +855,73 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, return NULL; } - ip = g_hash_table_lookup (device->options, "new_ip_address"); - if (ip != NULL) { - ip4_address = inet_addr (ip); - nm_info(" address %s", ip); - } - else { - return NULL; - } - - ip = g_hash_table_lookup (device->options, "new_subnet_mask"); - if (ip != NULL) { - ip4_netmask = inet_addr (ip); - nm_info(" netmask %s", ip); - } - else { - return NULL; - } - - ip = g_hash_table_lookup (device->options, "new_broadcast_address"); - if (ip != NULL) { - ip4_broadcast = inet_addr (ip); - nm_info(" broadcast %s", ip); - } - else { - return NULL; - } - - ip = g_hash_table_lookup (device->options, "new_routers"); - if (ip != NULL) { - ip4_gateway = inet_addr (ip); - } - else { /* If DHCP doesn't have a 'routers', just use the DHCP server's address as our gateway for now */ - ip = g_hash_table_lookup (device->options, "new_dhcp_server_identifier"); - if (ip != NULL) - ip4_gateway = inet_addr (ip); - else - return NULL; - } - - nm_info(" gateway %s", ip); - ip4_config = nm_ip4_config_new (); - nm_ip4_config_set_address (ip4_config, ip4_address); - nm_ip4_config_set_netmask (ip4_config, ip4_netmask); - nm_ip4_config_set_broadcast (ip4_config, ip4_broadcast); - nm_ip4_config_set_gateway (ip4_config, ip4_gateway); + if (!ip4_config) { + nm_warning ("%s: couldn't allocate memory for an IP4Config!", device->iface); + return NULL; + } - hostname = g_hash_table_lookup (device->options, "new_host_name"); - nameservers = g_hash_table_lookup (device->options, "new_domain_name_servers"); - domain = g_hash_table_lookup (device->options, "new_domain_name"); - search = g_hash_table_lookup (device->options, "new_domain_search"); - nis_domain = g_hash_table_lookup (device->options, "new_nis_domain"); - nis_servers = g_hash_table_lookup (device->options, "new_nis_servers"); - static_routes = g_hash_table_lookup (device->options, "new_static_routes"); + addr = g_malloc0 (sizeof (NMSettingIP4Address)); + if (!addr) { + nm_warning ("%s: couldn't allocate memory for an IP4 Address!", device->iface); + goto error; + } - if (nameservers) { - char **searches = g_strsplit (nameservers, " ", 0); + str = g_hash_table_lookup (device->options, "new_ip_address"); + if (str != NULL) { + addr->address = inet_addr (str); + nm_info(" address %s", str); + } + if (!addr->address) { + g_free (addr); + goto error; + } + + str = g_hash_table_lookup (device->options, "new_subnet_mask"); + if (str != NULL) { + addr->netmask = inet_addr (str); + nm_info(" netmask %s", str); + } + + str = g_hash_table_lookup (device->options, "new_routers"); + if (str != NULL) { + addr->gateway = inet_addr (str); + } else { /* If DHCP doesn't have a 'routers', just use the DHCP server's address as our gateway for now */ + str = g_hash_table_lookup (device->options, "new_dhcp_server_identifier"); + if (str != NULL) + addr->gateway = inet_addr (str); + else { + g_free (addr); + return NULL; + } + } + nm_info(" gateway %s", str); + + nm_ip4_config_take_address (ip4_config, addr); + + str = g_hash_table_lookup (device->options, "new_host_name"); + if (str) { + nm_ip4_config_set_hostname (ip4_config, str); + nm_info (" hostname '%s'", str); + } + + str = g_hash_table_lookup (device->options, "new_domain_name_servers"); + if (str) { + char **searches = g_strsplit (str, " ", 0); char **s; - int ip4_nameserver; for (s = searches; *s; s++) { // FIXME: use inet_aton - ip4_nameserver = inet_addr (*s); - nm_ip4_config_add_nameserver (ip4_config, ip4_nameserver); + ip4_num = inet_addr (*s); + nm_ip4_config_add_nameserver (ip4_config, ip4_num); nm_info (" nameserver '%s'", *s); } g_strfreev (searches); } - if (hostname) { - nm_ip4_config_set_hostname (ip4_config, hostname); - nm_info (" hostname '%s'", hostname); - } - - if (domain) { - char **domains = g_strsplit (domain, " ", 0); + str = g_hash_table_lookup (device->options, "new_domain_name"); + if (str) { + char **domains = g_strsplit (str, " ", 0); char **s; for (s = domains; *s; s++) { @@ -950,8 +931,9 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, g_strfreev (domains); } - if (search) { - char **searches = g_strsplit (search, " ", 0); + str = g_hash_table_lookup (device->options, "new_domain_search"); + if (str) { + char **searches = g_strsplit (str, " ", 0); char **s; for (s = searches; *s; s++) { @@ -961,48 +943,50 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, g_strfreev (searches); } - if (nis_domain) { - nm_ip4_config_set_nis_domain (ip4_config, nis_domain); - nm_info (" nis domain '%s'", nis_domain); + str = g_hash_table_lookup (device->options, "new_nis_domain"); + if (str) { + nm_ip4_config_set_nis_domain (ip4_config, str); + nm_info (" nis domain '%s'", str); } - if (nis_servers) { - char **searches = g_strsplit (nis_servers, " ", 0); + str = g_hash_table_lookup (device->options, "new_nis_servers"); + if (str) { + char **searches = g_strsplit (str, " ", 0); char **s; - int ip4_nis_server; for (s = searches; *s; s++) { // FIXME: use inet_aton - ip4_nis_server = inet_addr (*s); - nm_ip4_config_add_nis_server (ip4_config, ip4_nis_server); + ip4_num = inet_addr (*s); + nm_ip4_config_add_nis_server (ip4_config, ip4_num); nm_info (" nis server '%s'", *s); } g_strfreev (searches); } - if (static_routes) { - char **searches = g_strsplit (static_routes, " ", 0); + str = g_hash_table_lookup (device->options, "new_static_routes"); + if (str) { + char **searches = g_strsplit (str, " ", 0); if ((g_strv_length (searches) % 2) == 0) { char **s; for (s = searches; *s; s += 2) { - struct in_addr addr; - struct in_addr route; + struct in_addr rt_addr; + struct in_addr rt_route; - if (inet_aton (*s, &addr) == 0) { + if (inet_aton (*s, &rt_addr) == 0) { nm_warning ("DHCP provided invalid static route address: '%s'", *s); continue; } - if (inet_aton (*(s + 1), &route) == 0) { + if (inet_aton (*(s + 1), &rt_route) == 0) { nm_warning ("DHCP provided invalid static route gateway: '%s'", *(s + 1)); continue; } // FIXME: ensure the IP addresse and route are sane nm_ip4_config_add_static_route (ip4_config, - (guint32) addr.s_addr, - (guint32) route.s_addr); + (guint32) rt_addr.s_addr, + (guint32) rt_route.s_addr); nm_info (" static route %s gw %s", *s, *(s + 1)); } } else { @@ -1011,13 +995,17 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager, g_strfreev (searches); } - mtu = g_hash_table_lookup (device->options, "new_interface_mtu"); - if (mtu) { - int int_mtu = atoi (mtu); + str = g_hash_table_lookup (device->options, "new_interface_mtu"); + if (str) { + int int_mtu = atoi (str); if (int_mtu) nm_ip4_config_set_mtu (ip4_config, int_mtu); } return ip4_config; + +error: + g_object_unref (ip4_config); + return NULL; } diff --git a/src/nm-device.c b/src/nm-device.c index f23e3803a..3b67db0db 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -618,21 +618,21 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) NMIP4Config * nm_device_new_ip4_autoip_config (NMDevice *self) { - struct in_addr ip; - NMIP4Config * config = NULL; + struct in_addr ip; + NMIP4Config *config = NULL; + NMSettingIP4Address *addr; g_return_val_if_fail (self != NULL, NULL); // FIXME: make our autoip implementation not suck; use avahi-autoip - if (get_autoip (self, &ip)) { - #define LINKLOCAL_BCAST 0xa9feffff + if (!get_autoip (self, &ip)) + return NULL; - config = nm_ip4_config_new (); - nm_ip4_config_set_address (config, (guint32)(ip.s_addr)); - nm_ip4_config_set_netmask (config, (guint32)(ntohl (0xFFFF0000))); - nm_ip4_config_set_broadcast (config, (guint32)(ntohl (LINKLOCAL_BCAST))); - nm_ip4_config_set_gateway (config, 0); - } + config = nm_ip4_config_new (); + addr = g_malloc0 (sizeof (NMSettingIP4Address)); + addr->address = (guint32) ip.s_addr; + addr->netmask = (guint32) ntohl (0xFFFF0000); + nm_ip4_config_take_address (config, addr); return config; } diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 4e849a22b..7a3507d18 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -27,6 +27,7 @@ #include "nm-dbus-manager.h" #include "NetworkManager.h" #include "NetworkManagerUtils.h" +#include "nm-setting-ip4-config.h" #include #include @@ -41,11 +42,8 @@ G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT) #define NM_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate)) typedef struct { - guint32 ip4_address; - guint32 ip4_ptp_address; - guint32 ip4_gateway; - guint32 ip4_netmask; - guint32 ip4_broadcast; + GSList *addresses; + guint32 ptp_address; guint32 mtu; /* Maximum Transmission Unit of the interface */ guint32 mss; /* Maximum Segment Size of the route */ @@ -54,8 +52,8 @@ typedef struct { GPtrArray *domains; GPtrArray *searches; - gchar * hostname; - gchar * nis_domain; + gchar *hostname; + gchar *nis_domain; GArray *nis_servers; GArray *static_routes; } NMIP4ConfigPrivate; @@ -63,10 +61,7 @@ typedef struct { enum { PROP_0, - PROP_ADDRESS, - PROP_GATEWAY, - PROP_NETMASK, - PROP_BROADCAST, + PROP_ADDRESSES, PROP_HOSTNAME, PROP_NAMESERVERS, PROP_DOMAINS, @@ -100,20 +95,26 @@ nm_ip4_config_new (void) NMIP4Config *nm_ip4_config_copy (NMIP4Config *src_config) { NMIP4Config *dst_config; - NMIP4ConfigPrivate *priv; + NMIP4ConfigPrivate *src_priv; int i; int len; + GSList *iter; g_return_val_if_fail (NM_IS_IP4_CONFIG (src_config), NULL); dst_config = nm_ip4_config_new (); - priv = NM_IP4_CONFIG_GET_PRIVATE (dst_config); + src_priv = NM_IP4_CONFIG_GET_PRIVATE (src_config); + + for (iter = src_priv->addresses; iter; iter = g_slist_next (iter)) { + NMSettingIP4Address *src_addr = (NMSettingIP4Address *) iter->data; + NMSettingIP4Address *dst_addr; + + dst_addr = g_malloc0 (sizeof (NMSettingIP4Address)); + memcpy (dst_addr, src_addr, sizeof (NMSettingIP4Address)); + nm_ip4_config_take_address (dst_config, dst_addr); + } - nm_ip4_config_set_address (dst_config, nm_ip4_config_get_address (src_config)); nm_ip4_config_set_ptp_address (dst_config, nm_ip4_config_get_ptp_address (src_config)); - nm_ip4_config_set_gateway (dst_config, nm_ip4_config_get_gateway (src_config)); - nm_ip4_config_set_netmask (dst_config, nm_ip4_config_get_netmask (src_config)); - nm_ip4_config_set_broadcast (dst_config, nm_ip4_config_get_broadcast (src_config)); nm_ip4_config_set_hostname (dst_config, nm_ip4_config_get_hostname (src_config)); nm_ip4_config_set_nis_domain (dst_config, nm_ip4_config_get_nis_domain (src_config)); @@ -140,74 +141,79 @@ NMIP4Config *nm_ip4_config_copy (NMIP4Config *src_config) return dst_config; } -guint32 nm_ip4_config_get_address (NMIP4Config *config) +void +nm_ip4_config_take_address (NMIP4Config *config, + NMSettingIP4Address *address) +{ + NMIP4ConfigPrivate *priv; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + g_return_if_fail (address != NULL); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + priv->addresses = g_slist_append (priv->addresses, address); +} + +void +nm_ip4_config_add_address (NMIP4Config *config, + NMSettingIP4Address *address) +{ + NMIP4ConfigPrivate *priv; + NMSettingIP4Address *copy; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + g_return_if_fail (address != NULL); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + copy = g_malloc0 (sizeof (NMSettingIP4Address)); + memcpy (copy, address, sizeof (NMSettingIP4Address)); + priv->addresses = g_slist_append (priv->addresses, copy); +} + +void +nm_ip4_config_replace_address (NMIP4Config *config, + guint i, + NMSettingIP4Address *new_address) +{ + NMIP4ConfigPrivate *priv; + GSList *old; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + old = g_slist_nth (priv->addresses, i); + g_return_if_fail (old != NULL); + + g_free (old->data); + old->data = new_address; +} + +const NMSettingIP4Address *nm_ip4_config_get_address (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)->addresses, i); +} + +guint32 nm_ip4_config_get_num_addresses (NMIP4Config *config) { g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_address; -} - -void nm_ip4_config_set_address (NMIP4Config *config, guint32 addr) -{ - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - - NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_address = addr; + return g_slist_length (NM_IP4_CONFIG_GET_PRIVATE (config)->addresses); } guint32 nm_ip4_config_get_ptp_address (NMIP4Config *config) { g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_ptp_address; + return NM_IP4_CONFIG_GET_PRIVATE (config)->ptp_address; } void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr) { g_return_if_fail (NM_IS_IP4_CONFIG (config)); - NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_ptp_address = ptp_addr; -} - -guint32 nm_ip4_config_get_gateway (NMIP4Config *config) -{ - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - - return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_gateway; -} - -void nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway) -{ - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - - NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_gateway = gateway; -} - -guint32 nm_ip4_config_get_netmask (NMIP4Config *config) -{ - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - - return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_netmask; -} - -void nm_ip4_config_set_netmask (NMIP4Config *config, guint32 netmask) -{ - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - - NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_netmask = netmask; -} - -guint32 nm_ip4_config_get_broadcast (NMIP4Config *config) -{ - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0); - - return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_broadcast; -} - -void nm_ip4_config_set_broadcast (NMIP4Config *config, guint32 broadcast) -{ - g_return_if_fail (NM_IS_IP4_CONFIG (config)); - - NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_broadcast = broadcast; + NM_IP4_CONFIG_GET_PRIVATE (config)->ptp_address = ptp_addr; } void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver) @@ -440,43 +446,42 @@ static int ip4_addr_to_rtnl_broadcast (guint32 ip4_broadcast, struct rtnl_addr * } -struct rtnl_addr * nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 flags) +struct rtnl_addr * +nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 i, guint32 flags) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - struct rtnl_addr * addr = NULL; - gboolean success = TRUE; + const NMSettingIP4Address *config_addr; + struct rtnl_addr *addr; + gboolean success = TRUE; g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); + config_addr = nm_ip4_config_get_address (config, i); + g_return_val_if_fail (config_addr != NULL, NULL); + if (!(addr = rtnl_addr_alloc())) return NULL; if (flags & NM_RTNL_ADDR_ADDR) - success = (ip4_addr_to_rtnl_local (priv->ip4_address, addr) >= 0); + success = (ip4_addr_to_rtnl_local (config_addr->address, addr) >= 0); if (flags & NM_RTNL_ADDR_PTP_ADDR) - success = (ip4_addr_to_rtnl_peer (priv->ip4_ptp_address, addr) >= 0); + success = (ip4_addr_to_rtnl_peer (priv->ptp_address, addr) >= 0); if (flags & NM_RTNL_ADDR_NETMASK) - ip4_addr_to_rtnl_prefixlen (priv->ip4_netmask, addr); + ip4_addr_to_rtnl_prefixlen (config_addr->netmask, addr); if (flags & NM_RTNL_ADDR_BROADCAST) { - guint32 bcast = priv->ip4_broadcast; + guint32 hostmask, network, bcast; - /* Calculate the broadcast address if needed */ - if (!bcast) { - guint32 hostmask, network; - - network = ntohl (priv->ip4_address) & ntohl (priv->ip4_netmask); - hostmask = ~ntohl (priv->ip4_netmask); - bcast = htonl (network | hostmask); - } + network = ntohl (config_addr->address) & ntohl (config_addr->netmask); + hostmask = ~ntohl (config_addr->netmask); + bcast = htonl (network | hostmask); success = (ip4_addr_to_rtnl_broadcast (bcast, addr) >= 0); } - if (!success) - { + if (!success) { rtnl_addr_put (addr); addr = NULL; } @@ -501,6 +506,8 @@ finalize (GObject *object) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); + g_slist_foreach (priv->addresses, (GFunc) g_free, NULL); + g_slist_free (priv->addresses); g_free (priv->hostname); g_free (priv->nis_domain); g_array_free (priv->nameservers, TRUE); @@ -510,6 +517,35 @@ finalize (GObject *object) g_array_free (priv->static_routes, TRUE); } +static void +ip4_addresses_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *addresses; + GSList *iter; + + addresses = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + NMSettingIP4Address *ip4_addr = (NMSettingIP4Address *) iter->data; + GArray *array; + const guint32 empty_val = 0; + + array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + + g_array_append_val (array, ip4_addr->address); + g_array_append_val (array, ip4_addr->netmask); + + if (ip4_addr->gateway) + g_array_append_val (array, ip4_addr->gateway); + else + g_array_append_val (array, empty_val); + + g_ptr_array_add (addresses, array); + } + + g_value_take_boxed (value, addresses); +} + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -517,17 +553,8 @@ get_property (GObject *object, guint prop_id, NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); switch (prop_id) { - case PROP_ADDRESS: - g_value_set_uint (value, priv->ip4_address); - break; - case PROP_GATEWAY: - g_value_set_uint (value, priv->ip4_gateway); - break; - case PROP_NETMASK: - g_value_set_uint (value, priv->ip4_netmask); - break; - case PROP_BROADCAST: - g_value_set_uint (value, priv->ip4_broadcast); + case PROP_ADDRESSES: + ip4_addresses_to_gvalue (priv->addresses, value); break; case PROP_HOSTNAME: g_value_set_string (value, priv->hostname); @@ -566,32 +593,11 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) /* properties */ g_object_class_install_property - (object_class, PROP_ADDRESS, - g_param_spec_uint (NM_IP4_CONFIG_ADDRESS, - "Address", - "IP4 address", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_GATEWAY, - g_param_spec_uint (NM_IP4_CONFIG_GATEWAY, - "Gateway", - "Gateway address", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_NETMASK, - g_param_spec_uint (NM_IP4_CONFIG_NETMASK, - "Netmask", - "Netmask address", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_BROADCAST, - g_param_spec_uint (NM_IP4_CONFIG_BROADCAST, - "Broadcast", - "Broadcast address", - 0, G_MAXUINT32, 0, + (object_class, PROP_ADDRESSES, + g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES, + "Addresses", + "IP4 addresses", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_HOSTNAME, diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 720a64948..7a87be50a 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -27,6 +27,8 @@ #include #include +#include "nm-setting-ip4-config.h" + #define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ()) #define NM_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP4_CONFIG, NMIP4Config)) #define NM_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) @@ -42,10 +44,7 @@ typedef struct { GObjectClass parent; } NMIP4ConfigClass; -#define NM_IP4_CONFIG_ADDRESS "address" -#define NM_IP4_CONFIG_GATEWAY "gateway" -#define NM_IP4_CONFIG_NETMASK "netmask" -#define NM_IP4_CONFIG_BROADCAST "broadcast" +#define NM_IP4_CONFIG_ADDRESSES "addresses" #define NM_IP4_CONFIG_HOSTNAME "hostname" #define NM_IP4_CONFIG_NAMESERVERS "nameservers" #define NM_IP4_CONFIG_DOMAINS "domains" @@ -59,21 +58,15 @@ GType nm_ip4_config_get_type (void); NMIP4Config * nm_ip4_config_new (void); NMIP4Config * nm_ip4_config_copy (NMIP4Config *config); -guint32 nm_ip4_config_get_address (NMIP4Config *config); -void nm_ip4_config_set_address (NMIP4Config *config, guint32 addr); +void nm_ip4_config_take_address (NMIP4Config *config, NMSettingIP4Address *address); +void nm_ip4_config_add_address (NMIP4Config *config, NMSettingIP4Address *address); +void nm_ip4_config_replace_address (NMIP4Config *config, guint32 i, NMSettingIP4Address *new_address); +const NMSettingIP4Address * nm_ip4_config_get_address (NMIP4Config *config, guint32 i); +guint32 nm_ip4_config_get_num_addresses (NMIP4Config *config); guint32 nm_ip4_config_get_ptp_address (NMIP4Config *config); void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr); -guint32 nm_ip4_config_get_gateway (NMIP4Config *config); -void nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway); - -guint32 nm_ip4_config_get_netmask (NMIP4Config *config); -void nm_ip4_config_set_netmask (NMIP4Config *config, guint32 netmask); - -guint32 nm_ip4_config_get_broadcast (NMIP4Config *config); -void nm_ip4_config_set_broadcast (NMIP4Config *config, guint32 broadcast); - void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver); guint32 nm_ip4_config_get_nameserver (NMIP4Config *config, guint i); guint32 nm_ip4_config_get_num_nameservers (NMIP4Config *config); @@ -116,6 +109,6 @@ void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); #define NM_RTNL_ADDR_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_NETMASK | NM_RTNL_ADDR_BROADCAST) #define NM_RTNL_ADDR_PTP_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_NETMASK | NM_RTNL_ADDR_PTP_ADDR) -struct rtnl_addr * nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 flags); +struct rtnl_addr *nm_ip4_config_to_rtnl_addr (NMIP4Config *config, guint32 i, guint32 flags); #endif /* NM_IP4_CONFIG_H */ diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 35112c680..1b84a3a65 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "nm-ppp-manager.h" #include "nm-setting-connection.h" @@ -231,6 +232,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, GError **err) { NMIP4Config *config; + NMSettingIP4Address *addr; GValue *val; const char *iface; int i; @@ -244,23 +246,33 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, /* priv->ipconfig_timeout = 0; */ config = nm_ip4_config_new (); + addr = g_malloc0 (sizeof (NMSettingIP4Address)); val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_GATEWAY); if (val) { - nm_ip4_config_set_gateway (config, g_value_get_uint (val)); + addr->gateway = g_value_get_uint (val); nm_ip4_config_set_ptp_address (config, g_value_get_uint (val)); } val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_ADDRESS); if (val) - nm_ip4_config_set_address (config, g_value_get_uint (val)); + addr->address = g_value_get_uint (val); val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_NETMASK); if (val) - nm_ip4_config_set_netmask (config, g_value_get_uint (val)); - else + addr->netmask = g_value_get_uint (val); + else { /* If no netmask, default to Class C address */ - nm_ip4_config_set_netmask (config, 0x00FF); + addr->netmask = htonl (0x000000FF); + } + + if (addr->netmask && addr->address) { + nm_ip4_config_take_address (config, addr); + } else { + nm_warning ("%s: invalid IPv4 address or netmask received!", __func__); + g_free (addr); + goto out; + } val = (GValue *) g_hash_table_lookup (config_hash, NM_PPP_IP4_CONFIG_DNS); if (val) { diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 7c28f20ff..c39b2bc0a 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -271,6 +271,7 @@ print_vpn_config (NMIP4Config *config, const char *tundev, const char *banner) { + const NMSettingIP4Address *addr; struct in_addr temp_addr; char * dns_domain = NULL; guint32 num; @@ -278,12 +279,13 @@ print_vpn_config (NMIP4Config *config, g_return_if_fail (config != NULL); - temp_addr.s_addr = nm_ip4_config_get_gateway (config); + addr = nm_ip4_config_get_address (config, 0); + temp_addr.s_addr = addr->gateway; nm_info ("VPN Gateway: %s", inet_ntoa (temp_addr)); nm_info ("Tunnel Device: %s", tundev); - temp_addr.s_addr = nm_ip4_config_get_address (config); + temp_addr.s_addr = addr->address; nm_info ("Internal IP4 Address: %s", inet_ntoa (temp_addr)); - temp_addr.s_addr = nm_ip4_config_get_netmask (config); + temp_addr.s_addr = addr->netmask; nm_info ("Internal IP4 Netmask: %s", inet_ntoa (temp_addr)); temp_addr.s_addr = nm_ip4_config_get_ptp_address (config); nm_info ("Internal IP4 Point-to-Point Address: %s", inet_ntoa (temp_addr)); @@ -312,6 +314,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); NMSettingIP4Config *s_ip4; + NMSettingIP4Address *addr; NMIP4Config *config; GValue *val; int i; @@ -324,13 +327,15 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, config = nm_ip4_config_new (); + addr = g_malloc0 (sizeof (NMSettingIP4Address)); + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY); if (val) - nm_ip4_config_set_gateway (config, g_value_get_uint (val)); + addr->gateway = g_value_get_uint (val); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS); if (val) - nm_ip4_config_set_address (config, g_value_get_uint (val)); + addr->address = g_value_get_uint (val); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PTP); if (val) @@ -338,10 +343,18 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_NETMASK); if (val) - nm_ip4_config_set_netmask (config, g_value_get_uint (val)); - else + addr->netmask = g_value_get_uint (val); + else { /* If no netmask, default to Class C address */ - nm_ip4_config_set_netmask (config, 0x00FF); + addr->netmask = htonl (0x000000FF); + } + + if (addr->address && addr->netmask) { + nm_ip4_config_take_address (config, addr); + } else { + g_warning ("%s: invalid IP4 config received!", __func__); + g_free (addr); + } val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_DNS); if (val) { diff --git a/test/nm-tool.c b/test/nm-tool.c index 6367a7a43..d5a1ac3c8 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -37,6 +37,7 @@ #include #include #include +#include static gboolean get_nm_state (NMClient *client) @@ -303,24 +304,26 @@ detail_device (gpointer data, gpointer user_data) /* IP Setup info */ if (state == NM_DEVICE_STATE_ACTIVATED) { NMIP4Config *cfg = nm_device_get_ip4_config (device); + GSList *iter; - printf ("\n IP Settings:\n"); + printf ("\n IPv4 Settings:\n"); - tmp = ip4_address_as_string (nm_ip4_config_get_address (cfg)); - print_string (" IP Address", tmp); - g_free (tmp); + for (iter = (GSList *) nm_ip4_config_get_addresses (cfg); iter; iter = g_slist_next (iter)) { + NMSettingIP4Address *addr = iter->data; - tmp = ip4_address_as_string (nm_ip4_config_get_netmask (cfg)); - print_string (" Subnet Mask", tmp); - g_free (tmp); + tmp = ip4_address_as_string (addr->address); + print_string (" Address", tmp); + g_free (tmp); - tmp = ip4_address_as_string (nm_ip4_config_get_broadcast (cfg)); - print_string (" Broadcast", tmp); - g_free (tmp); + tmp = ip4_address_as_string (addr->netmask); + print_string (" Netmask", tmp); + g_free (tmp); - tmp = ip4_address_as_string (nm_ip4_config_get_gateway (cfg)); - print_string (" Gateway", tmp); - g_free (tmp); + tmp = ip4_address_as_string (addr->gateway); + print_string (" Gateway", tmp); + g_free (tmp); + printf ("\n"); + } array = nm_ip4_config_get_nameservers (cfg); if (array) {