NetworkManager r3637 - in trunk: . introspection libnm-glib libnm-util src src/dhcp-manager src/ppp-manager src/vpn-manager test



Author: dcbw
Date: Tue May  6 21:53:22 2008
New Revision: 3637
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3637&view=rev

Log:
2008-05-06  Dan Williams  <dcbw redhat com>

	* 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



Modified:
   trunk/ChangeLog
   trunk/introspection/nm-ip4-config.xml
   trunk/libnm-glib/libnm-glib-test.c
   trunk/libnm-glib/nm-ip4-config.c
   trunk/libnm-glib/nm-ip4-config.h
   trunk/libnm-util/nm-setting-ip4-config.c
   trunk/src/NetworkManagerPolicy.c
   trunk/src/NetworkManagerSystem.c
   trunk/src/NetworkManagerUtils.c
   trunk/src/dhcp-manager/nm-dhcp-manager.c
   trunk/src/nm-device.c
   trunk/src/nm-ip4-config.c
   trunk/src/nm-ip4-config.h
   trunk/src/ppp-manager/nm-ppp-manager.c
   trunk/src/vpn-manager/nm-vpn-connection.c
   trunk/test/nm-tool.c

Modified: trunk/introspection/nm-ip4-config.xml
==============================================================================
--- trunk/introspection/nm-ip4-config.xml	(original)
+++ trunk/introspection/nm-ip4-config.xml	Tue May  6 21:53:22 2008
@@ -2,17 +2,8 @@
 
 <node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0";>
   <interface name="org.freedesktop.NetworkManager.IP4Config">
-    <property name="Address" type="u" access="read">
-      <tp:docstring>IPv4 address. FIXME: what about multiple addresses?</tp:docstring>
-    </property>
-    <property name="Gateway" type="u" access="read">
-      <tp:docstring>Default gateway.</tp:docstring>
-    </property>
-    <property name="Netmask" type="u" access="read">
-      <tp:docstring>Network mask of this network.</tp:docstring>
-    </property>
-    <property name="Broadcast" type="u" access="read">
-      <tp:docstring>Broadcast address of this network.</tp:docstring>
+    <property name="Addresses" type="aau" access="read">
+      <tp:docstring>Tuples of IPv4 address/netmask/gateway.  The gateway is optional, if not given should be 0.</tp:docstring>
     </property>
     <property name="Hostname" type="s" access="read">
       <tp:docstring>The hostname associated with this IPv4 address. FIXME: what about multiple hostnames?</tp:docstring>

Modified: trunk/libnm-glib/libnm-glib-test.c
==============================================================================
--- trunk/libnm-glib/libnm-glib-test.c	(original)
+++ trunk/libnm-glib/libnm-glib-test.c	Tue May  6 21:53:22 2008
@@ -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 @@
 	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);
-
-	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 (nm_ip4_config_get_netmask (cfg));
-	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);
+	for (iter = (GSList *) nm_ip4_config_get_addresses (cfg); iter; iter = g_slist_next (iter)) {
+		NMSettingIP4Address *addr = iter->data;
+
+		tmp = ip4_address_as_string (addr->address);
+		g_print ("IP4 address: %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 (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));
 

Modified: trunk/libnm-glib/nm-ip4-config.c
==============================================================================
--- trunk/libnm-glib/nm-ip4-config.c	(original)
+++ trunk/libnm-glib/nm-ip4-config.c	Tue May  6 21:53:22 2008
@@ -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 @@
 typedef struct {
 	DBusGProxy *proxy;
 
-	guint32 address;
-	guint32 gateway;
-	guint32 netmask;
-	guint32 broadcast;
+	GSList *addresses;
 	char *hostname;
 	GArray *nameservers;
 	GPtrArray *domains;
@@ -25,10 +23,7 @@
 
 enum {
 	PROP_0,
-	PROP_ADDRESS,
-	PROP_GATEWAY,
-	PROP_NETMASK,
-	PROP_BROADCAST,
+	PROP_ADDRESSES,
 	PROP_HOSTNAME,
 	PROP_NAMESERVERS,
 	PROP_DOMAINS,
@@ -44,6 +39,21 @@
 }
 
 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)
 {
 	if (!nm_uint_array_demarshal (value, (GArray **) field))
@@ -71,10 +81,7 @@
 {
 	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 @@
 {
 	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 @@
               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 @@
 
 	/* 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 @@
 									 NULL);
 }
 
-guint32
-nm_ip4_config_get_address (NMIP4Config *config)
-{
-	NMIP4ConfigPrivate *priv;
-
-	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");
-	}
-
-	return priv->address;
-}
-
-guint32
-nm_ip4_config_get_gateway (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->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;
+	if (priv->addresses)
+		return priv->addresses;
 
-	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");
+	if (!nm_object_get_property (NM_OBJECT (config),
+	                             "org.freedesktop.DBus.Properties",
+	                             "Addresses",
+	                             &value)) {
+		return NULL;
 	}
 
-	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");
-	}
+	demarshal_ip4_address_array (NM_OBJECT (config), NULL, &value, &priv->addresses);	
+	g_value_unset (&value);
 
-	return priv->broadcast;
+	return priv->addresses;
 }
 
 const char *

Modified: trunk/libnm-glib/nm-ip4-config.h
==============================================================================
--- trunk/libnm-glib/nm-ip4-config.h	(original)
+++ trunk/libnm-glib/nm-ip4-config.h	Tue May  6 21:53:22 2008
@@ -23,10 +23,7 @@
 	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 @@
 
 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);

Modified: trunk/libnm-util/nm-setting-ip4-config.c
==============================================================================
--- trunk/libnm-util/nm-setting-ip4-config.c	(original)
+++ trunk/libnm-util/nm-setting-ip4-config.c	Tue May  6 21:53:22 2008
@@ -87,64 +87,6 @@
 	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 @@
 		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 @@
 		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);

Modified: trunk/src/NetworkManagerPolicy.c
==============================================================================
--- trunk/src/NetworkManagerPolicy.c	(original)
+++ trunk/src/NetworkManagerPolicy.c	Tue May  6 21:53:22 2008
@@ -86,10 +86,11 @@
 		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 @@
 		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 @@
 		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);

Modified: trunk/src/NetworkManagerSystem.c
==============================================================================
--- trunk/src/NetworkManagerSystem.c	(original)
+++ trunk/src/NetworkManagerSystem.c	Tue May  6 21:53:22 2008
@@ -80,7 +80,7 @@
 	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 @@
 	/*
 	 * 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 @@
 
 typedef struct {
 	const char *iface;
+	int ifindex;
+	int family;
 	struct nl_handle *nlh;
-	struct rtnl_addr *match;
 } AddrCheckData;
 
 static void
@@ -197,44 +203,26 @@
 	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());
+			}
+		}
 	}
 }
 
-/*
- * nm_system_device_set_from_ip4_config
- *
- * Set IPv4 configuration of the device from an NMIP4Config object.
- *
- */
-gboolean
-nm_system_device_set_from_ip4_config (const char *iface,
-							   NMIP4Config *config,
-							   gboolean route_to_iface)
+static gboolean
+add_ip4_addresses (NMIP4Config *config, const char *iface)
 {
 	struct nl_handle *nlh = NULL;
-	struct rtnl_addr *addr = NULL;
 	struct nl_cache *addr_cache = NULL;
-	int len, i, err;
-	guint32 flags;
+	int i, iface_idx, err;
 	AddrCheckData check_data;
-	gboolean success = FALSE;
-
-	g_return_val_if_fail (iface != NULL, FALSE);
-	g_return_val_if_fail (config != NULL, FALSE);
+	guint32 flags = 0;
+	gboolean did_gw = FALSE;
 
 	nlh = nm_netlink_get_default_handle ();
 	if (!nlh)
@@ -242,30 +230,69 @@
 
 	addr_cache = rtnl_addr_alloc_cache (nlh);
 	if (!addr_cache)
-		goto out;
+		return FALSE;
 	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));
+	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.match = addr;
+	check_data.ifindex = iface_idx;
+	check_data.family = AF_INET;
 
-	/* Remove all addresses except the one we're about to add */
+	/* Remove all existing IPv4 addresses */
 	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());
+	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
+ *
+ * Set IPv4 configuration of the device from an NMIP4Config object.
+ *
+ */
+gboolean
+nm_system_device_set_from_ip4_config (const char *iface,
+							   NMIP4Config *config,
+							   gboolean route_to_iface)
+{
+	int len, i;
+
+	g_return_val_if_fail (iface != NULL, FALSE);
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	if (!add_ip4_addresses (config, iface))
+		return FALSE;
 
 	sleep (1);
 
@@ -281,14 +308,7 @@
 	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 @@
                                           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))

Modified: trunk/src/NetworkManagerUtils.c
==============================================================================
--- trunk/src/NetworkManagerUtils.c	(original)
+++ trunk/src/NetworkManagerUtils.c	Tue May  6 21:53:22 2008
@@ -237,6 +237,8 @@
 void
 nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting)
 {
+	GSList *iter;
+
 	if (!setting)
 		return; /* Defaults are just fine */
 
@@ -261,42 +263,44 @@
 		}
 	}
 
-	if (setting->dns_search) {
-		GSList *iter;
-
-		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);
-
-				if (!strcmp (search, (char *) iter->data)) {
-					found = TRUE;
-					break;
-				}
+	/* DNS search domains */
+	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);
+
+			if (!strcmp (search, (char *) iter->data)) {
+				found = TRUE;
+				break;
 			}
-
-			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;
-
-		/* 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);
+		if (!found)
+			nm_ip4_config_add_search (ip4_config, (char *) iter->data);
+	}
 
-			if (addr->gateway)
-				nm_ip4_config_set_gateway (ip4_config, addr->gateway);
+	/* IPv4 addresses */
+	for (iter = setting->addresses; iter; iter = g_slist_next (iter)) {
+		NMSettingIP4Address *setting_addr = (NMSettingIP4Address *) iter->data;
+		guint32 i, num;
+
+		num = nm_ip4_config_get_num_addresses (ip4_config);
+		for (i = 0; i < num; i++) {
+			const NMSettingIP4Address *cfg_addr;
+
+			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);
 	}
 }
 

Modified: trunk/src/dhcp-manager/nm-dhcp-manager.c
==============================================================================
--- trunk/src/dhcp-manager/nm-dhcp-manager.c	(original)
+++ trunk/src/dhcp-manager/nm-dhcp-manager.c	Tue May  6 21:53:22 2008
@@ -834,20 +834,10 @@
 {
 	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 @@
 		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 {
+	ip4_config = nm_ip4_config_new ();
+	if (!ip4_config) {
+		nm_warning ("%s: couldn't allocate memory for an IP4Config!", device->iface);
 		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
+	addr = g_malloc0 (sizeof (NMSettingIP4Address));
+	if (!addr) {
+		nm_warning ("%s: couldn't allocate memory for an IP4 Address!", device->iface);
+		goto error;
+	}
+
+	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_info("  gateway %s", ip);
+	nm_ip4_config_take_address (ip4_config, addr);
 
-	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);
-
-	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");
+	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);
+	}
 
-	if (nameservers) {
-		char **searches = g_strsplit (nameservers, " ", 0);
+	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 @@
 		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 @@
 		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 @@
 		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;
 }

Modified: trunk/src/nm-device.c
==============================================================================
--- trunk/src/nm-device.c	(original)
+++ trunk/src/nm-device.c	Tue May  6 21:53:22 2008
@@ -618,21 +618,21 @@
 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;
 }

Modified: trunk/src/nm-ip4-config.c
==============================================================================
--- trunk/src/nm-ip4-config.c	(original)
+++ trunk/src/nm-ip4-config.c	Tue May  6 21:53:22 2008
@@ -27,6 +27,7 @@
 #include "nm-dbus-manager.h"
 #include "NetworkManager.h"
 #include "NetworkManagerUtils.h"
+#include "nm-setting-ip4-config.h"
 
 #include <netlink/route/addr.h>
 #include <netlink/utils.h>
@@ -41,11 +42,8 @@
 #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 @@
 	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 @@
 
 enum {
 	PROP_0,
-	PROP_ADDRESS,
-	PROP_GATEWAY,
-	PROP_NETMASK,
-	PROP_BROADCAST,
+	PROP_ADDRESSES,
 	PROP_HOSTNAME,
 	PROP_NAMESERVERS,
 	PROP_DOMAINS,
@@ -100,20 +95,26 @@
 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 @@
 	return dst_config;
 }
 
-guint32 nm_ip4_config_get_address (NMIP4Config *config)
+void
+nm_ip4_config_take_address (NMIP4Config *config,
+                            NMSettingIP4Address *address)
 {
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
-
-	return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_address;
-}
+	NMIP4ConfigPrivate *priv;
 
-void nm_ip4_config_set_address (NMIP4Config *config, guint32 addr)
-{
 	g_return_if_fail (NM_IS_IP4_CONFIG (config));
+	g_return_if_fail (address != NULL);
 
-	NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_address = addr;
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	priv->addresses = g_slist_append (priv->addresses, address);
 }
 
-guint32 nm_ip4_config_get_ptp_address (NMIP4Config *config)
+void
+nm_ip4_config_add_address (NMIP4Config *config,
+                           NMSettingIP4Address *address)
 {
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
-
-	return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_ptp_address;
-}
+	NMIP4ConfigPrivate *priv;
+	NMSettingIP4Address *copy;
 
-void nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr)
-{
 	g_return_if_fail (NM_IS_IP4_CONFIG (config));
+	g_return_if_fail (address != NULL);
 
-	NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_ptp_address = ptp_addr;
+	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);
 }
 
-guint32 nm_ip4_config_get_gateway (NMIP4Config *config)
+void
+nm_ip4_config_replace_address (NMIP4Config *config,
+                               guint i,
+                               NMSettingIP4Address *new_address)
 {
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
-
-	return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_gateway;
-}
+	NMIP4ConfigPrivate *priv;
+	GSList *old;
 
-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;
+	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;
 }
 
-guint32 nm_ip4_config_get_netmask (NMIP4Config *config)
+const NMSettingIP4Address *nm_ip4_config_get_address (NMIP4Config *config, guint i)
 {
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
+	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	return NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_netmask;
+	return (const NMSettingIP4Address *) g_slist_nth_data (NM_IP4_CONFIG_GET_PRIVATE (config)->addresses, i);
 }
 
-void nm_ip4_config_set_netmask (NMIP4Config *config, guint32 netmask)
+guint32 nm_ip4_config_get_num_addresses (NMIP4Config *config)
 {
-	g_return_if_fail (NM_IS_IP4_CONFIG (config));
+	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
 
-	NM_IP4_CONFIG_GET_PRIVATE (config)->ip4_netmask = netmask;
+	return g_slist_length (NM_IP4_CONFIG_GET_PRIVATE (config)->addresses);
 }
 
-guint32 nm_ip4_config_get_broadcast (NMIP4Config *config)
+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_broadcast;
+	return NM_IP4_CONFIG_GET_PRIVATE (config)->ptp_address;
 }
 
-void nm_ip4_config_set_broadcast (NMIP4Config *config, guint32 broadcast)
+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_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 @@
 }
 
 
-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 @@
 {
 	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);
@@ -511,23 +518,43 @@
 }
 
 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)
 {
 	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 @@
 
 	/* 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,

Modified: trunk/src/nm-ip4-config.h
==============================================================================
--- trunk/src/nm-ip4-config.h	(original)
+++ trunk/src/nm-ip4-config.h	Tue May  6 21:53:22 2008
@@ -27,6 +27,8 @@
 #include <glib/gtypes.h>
 #include <glib-object.h>
 
+#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 @@
 	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 @@
 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 @@
 #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 */

Modified: trunk/src/ppp-manager/nm-ppp-manager.c
==============================================================================
--- trunk/src/ppp-manager/nm-ppp-manager.c	(original)
+++ trunk/src/ppp-manager/nm-ppp-manager.c	Tue May  6 21:53:22 2008
@@ -5,6 +5,7 @@
 #include <signal.h>
 #include <string.h>
 #include <unistd.h>
+#include <arpa/inet.h>
 
 #include "nm-ppp-manager.h"
 #include "nm-setting-connection.h"
@@ -231,6 +232,7 @@
 						   GError **err)
 {
 	NMIP4Config *config;
+	NMSettingIP4Address *addr;
 	GValue *val;
 	const char *iface;
 	int i;
@@ -244,23 +246,33 @@
 /* 	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) {

Modified: trunk/src/vpn-manager/nm-vpn-connection.c
==============================================================================
--- trunk/src/vpn-manager/nm-vpn-connection.c	(original)
+++ trunk/src/vpn-manager/nm-vpn-connection.c	Tue May  6 21:53:22 2008
@@ -271,6 +271,7 @@
 			   const char *tundev,
 			   const char *banner)
 {
+	const NMSettingIP4Address *addr;
 	struct in_addr temp_addr;
 	char *         dns_domain = NULL;
 	guint32        num;
@@ -278,12 +279,13 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 
 	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) {

Modified: trunk/test/nm-tool.c
==============================================================================
--- trunk/test/nm-tool.c	(original)
+++ trunk/test/nm-tool.c	Tue May  6 21:53:22 2008
@@ -37,6 +37,7 @@
 #include <nm-gsm-device.h>
 #include <nm-cdma-device.h>
 #include <nm-utils.h>
+#include <nm-setting-ip4-config.h>
 
 static gboolean
 get_nm_state (NMClient *client)
@@ -303,24 +304,26 @@
 	/* 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) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]