2008-03-07 Dan Williams <dcbw@redhat.com>
authorDan Williams <dcbw@redhat.com>
Fri, 7 Mar 2008 19:41:32 +0000 (19:41 +0000)
committerDan Williams <dcbw@redhat.com>
Fri, 7 Mar 2008 19:41:32 +0000 (19:41 +0000)
First pass of multiple active device support.  Expect bugs.

* src/nm-ip4-config.c
  src/nm-ip4-config.h
- (nm_ip4_config_get_secondary, nm_ip4_config_set_secondary): remove;
there are better ways to do this in the named manager

* src/nm-device.c
  src/nm-device.h
- (nm_device_can_activate): return whether the device can activate a
connection right now; taking into account things like carrier state
and rfkill state
- (nm_device_get_best_auto_connection): renamed from
nm_device_get_best_connection
- (real_act_stage4_get_ip4_config): MTU stuff is now handled in the
device subclasses themselves, so that each device can override the
MTU from it's NMSetting subclass if needed
- (nm_device_set_ip4_config): set MTU when setting up routes and stuff
in NetworkManagerSystem.c, not here

* src/named-manager/nm-named-manager.c
  src/named-manager/nm-named-manager.h
- (nm_named_manager_name_owner_changed,
   nm_named_manager_dbus_connection_changed): fix for changes to
rewrite_resolv_conf()
- (compute_nameservers): don't need the NMNamedManager at all, remove
from parameter list
- (merge_one_ip4_config): new function; merge ip4 configs together
- (rewrite_resolv_conf): write out resolv.conf from all the stored
ip4 configs; the VPN config takes precedence, then the best
device config, then the rest of the configs
- (get_domain_for_config): take the NMNamedManager as an argument
to check whether the config is the VPN config
- (add_ip4_config_to_named): fixups for removal of the 'secondary'
attribute from ip4 configs
- (add_all_ip4_configs_to_named): add all the configs in priority order
- (remove_ip4_config_from_named): fix for changes to
get_domain_for_config()
- (nm_named_manager_add_ip4_config): assign the config to the right slot
based on its type; callers must pass in the type now
- (get_last_default_domain): remove, unused
- (nm_named_manager_remove_ip4_config): handle config slots correctly

* src/nm-device-802-11-wireless.c
- (real_can_activate): new function
- (real_get_best_auto_connection): renamed from real_get_best_connection
- (real_act_stage4_get_ip4_config): handle MTU override

* src/nm-device-802-3-ethernet.c
- (real_can_activate): new function
- (real_get_best_auto_connection): renamed from real_get_best_connection
- (real_act_stage4_get_ip4_config): new function; handle MTU override

* src/vpn-manager/nm-vpn-connection.c
- (nm_vpn_connection_ip4_config_get): don't need to set the 'secondary'
attribute on the ip4 config

* src/NetworkManagerPolicy.c
- (nm_policy_auto_get_best_device): remove
- (nm_policy_device_change_check): remove
- (update_default_route): new function; set the default route via
the specified device
- (get_device_priority): new function; return the priority number of
a device type WRT which one should have the default route.  Order is
(highest to lowest)  wired, wireless, GSM, CDMA.
- (update_routing_and_dns): new function; determine which device should
have the default route, then update the routing table and DNS
- (maybe_auto_activate_device): new function; if a device is now
available for activation, find out what connection it would like to
activate and do it
- (schedule_activate_check): new function; if a device can be activated
now, schedule the activation.  Each device may have only one
pending activation at a given time.
- (device_state_changed): if activation was canceled, try again,
possibly with another connection; if the device was activated,
update routing and DNS; if the device was deactivated, try again
with another connection
- (device_carrier_changed): if there is no carrier, deactivate the
device; otherwise schedule an activation check for the device
- (wireless_networks_changed): schedule an activation check for the
device
- (device_added): keep track of the signal handler IDs so they can
be removed when the device goes away
- (device_removed): remove any signal handlers that might be attached
to the device; update routing and DNS
- (schedule_activate_all): new function
- (connections_added, connection_added, connection_updated): when
connections change, schedule all devices for an activation check
- (connection_removed): when a device is deactivated because its
connection was removed, schedule another activation check for it
- (nm_policy_destroy): destroy pending activations and disconnect
all device signal handlers

* src/nm-manager.c
- (nm_manager_activate_device): if the device was already actived,
deactivate it
- (deactivate_old_device): remove
- (connection_added_default_handler, impl_manager_activate_device):
don't deactivate other devices when activating this one

* src/backends/NetworkManagerGentoo.c
  src/backends/NetworkManagerFrugalware.c
  src/backends/NetworkManagerPaldo.c
  src/backends/NetworkManagerRedHat.c
  src/backends/NetworkManagerSlackware.c
  src/backends/NetworkManagerArch.c
  src/backends/NetworkManagerSuSE.c
  src/backends/NetworkManagerDebian.c
- (nm_system_get_mtu): remove; MTU should be provided through the
distro's system settings service plugin instead
- (nm_system_device_add_default_route_via_device): remove
- (nm_system_device_add_default_route_via_device_with_iface): remove
- (nm_system_device_replace_default_route): new function; call
generic implementation

* src/backends/NetworkManagerGeneric.c
  src/backends/NetworkManagerGeneric.h
- (nm_generic_device_add_default_route_via_device,
   nm_generic_device_add_default_route_via_device_with_iface): remove
- (nm_generic_device_replace_default_route): replace the default route
with the given route via some gateway

* src/NetworkManagerSystem.c
  src/NetworkManagerSystem.h
- (nm_system_device_set_from_ip4_config): let the policy handle updates
to routing and DNS; but set the MTU here
- (nm_system_vpn_device_set_from_ip4_config): set the route with the
ip_iface of the active device; use the standard MTU setting function
- (nm_system_set_mtu): remove
- (nm_system_device_set_mtu): consolidate MTU setting code in one place

git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3391 4912f4e0-d625-0410-9fb7-b9a5a253dbdc

25 files changed:
ChangeLog
po/POTFILES.in
src/NetworkManagerPolicy.c
src/NetworkManagerSystem.c
src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGeneric.c
src/backends/NetworkManagerGeneric.h
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
src/named-manager/nm-named-manager.c
src/named-manager/nm-named-manager.h
src/nm-device-802-11-wireless.c
src/nm-device-802-3-ethernet.c
src/nm-device.c
src/nm-device.h
src/nm-ip4-config.c
src/nm-ip4-config.h
src/nm-manager.c
src/vpn-manager/nm-vpn-connection.c

index e835170..74633f0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,136 @@
+2008-03-07  Dan Williams  <dcbw@redhat.com>
+
+       First pass of multiple active device support.  Expect bugs.
+
+       * src/nm-ip4-config.c
+         src/nm-ip4-config.h
+               - (nm_ip4_config_get_secondary, nm_ip4_config_set_secondary): remove;
+                       there are better ways to do this in the named manager
+
+       * src/nm-device.c
+         src/nm-device.h
+               - (nm_device_can_activate): return whether the device can activate a
+                       connection right now; taking into account things like carrier state
+                       and rfkill state
+               - (nm_device_get_best_auto_connection): renamed from
+                       nm_device_get_best_connection
+               - (real_act_stage4_get_ip4_config): MTU stuff is now handled in the
+                       device subclasses themselves, so that each device can override the
+                       MTU from it's NMSetting subclass if needed
+               - (nm_device_set_ip4_config): set MTU when setting up routes and stuff
+                       in NetworkManagerSystem.c, not here
+
+       * src/named-manager/nm-named-manager.c
+         src/named-manager/nm-named-manager.h
+               - (nm_named_manager_name_owner_changed,
+                  nm_named_manager_dbus_connection_changed): fix for changes to
+                       rewrite_resolv_conf()
+               - (compute_nameservers): don't need the NMNamedManager at all, remove
+                       from parameter list
+               - (merge_one_ip4_config): new function; merge ip4 configs together
+               - (rewrite_resolv_conf): write out resolv.conf from all the stored
+                       ip4 configs; the VPN config takes precedence, then the best
+                       device config, then the rest of the configs
+               - (get_domain_for_config): take the NMNamedManager as an argument
+                       to check whether the config is the VPN config
+               - (add_ip4_config_to_named): fixups for removal of the 'secondary'
+                       attribute from ip4 configs
+               - (add_all_ip4_configs_to_named): add all the configs in priority order
+               - (remove_ip4_config_from_named): fix for changes to
+                       get_domain_for_config()
+               - (nm_named_manager_add_ip4_config): assign the config to the right slot
+                       based on its type; callers must pass in the type now
+               - (get_last_default_domain): remove, unused
+               - (nm_named_manager_remove_ip4_config): handle config slots correctly
+
+       * src/nm-device-802-11-wireless.c
+               - (real_can_activate): new function
+               - (real_get_best_auto_connection): renamed from real_get_best_connection
+               - (real_act_stage4_get_ip4_config): handle MTU override
+
+       * src/nm-device-802-3-ethernet.c
+               - (real_can_activate): new function
+               - (real_get_best_auto_connection): renamed from real_get_best_connection
+               - (real_act_stage4_get_ip4_config): new function; handle MTU override
+
+       * src/vpn-manager/nm-vpn-connection.c
+               - (nm_vpn_connection_ip4_config_get): don't need to set the 'secondary'
+                       attribute on the ip4 config
+
+       * src/NetworkManagerPolicy.c
+               - (nm_policy_auto_get_best_device): remove
+               - (nm_policy_device_change_check): remove
+               - (update_default_route): new function; set the default route via
+                       the specified device
+               - (get_device_priority): new function; return the priority number of
+                       a device type WRT which one should have the default route.  Order is
+                       (highest to lowest)  wired, wireless, GSM, CDMA.
+               - (update_routing_and_dns): new function; determine which device should
+                       have the default route, then update the routing table and DNS
+               - (maybe_auto_activate_device): new function; if a device is now
+                       available for activation, find out what connection it would like to
+                       activate and do it
+               - (schedule_activate_check): new function; if a device can be activated
+                       now, schedule the activation.  Each device may have only one
+                       pending activation at a given time.
+               - (device_state_changed): if activation was canceled, try again,
+                       possibly with another connection; if the device was activated,
+                       update routing and DNS; if the device was deactivated, try again
+                       with another connection
+               - (device_carrier_changed): if there is no carrier, deactivate the
+                       device; otherwise schedule an activation check for the device
+               - (wireless_networks_changed): schedule an activation check for the
+                       device
+               - (device_added): keep track of the signal handler IDs so they can
+                       be removed when the device goes away
+               - (device_removed): remove any signal handlers that might be attached
+                       to the device; update routing and DNS
+               - (schedule_activate_all): new function
+               - (connections_added, connection_added, connection_updated): when
+                       connections change, schedule all devices for an activation check
+               - (connection_removed): when a device is deactivated because its
+                       connection was removed, schedule another activation check for it
+               - (nm_policy_destroy): destroy pending activations and disconnect
+                       all device signal handlers
+
+       * src/nm-manager.c
+               - (nm_manager_activate_device): if the device was already actived,
+                       deactivate it
+               - (deactivate_old_device): remove
+               - (connection_added_default_handler, impl_manager_activate_device):
+                       don't deactivate other devices when activating this one
+
+       * src/backends/NetworkManagerGentoo.c
+         src/backends/NetworkManagerFrugalware.c
+         src/backends/NetworkManagerPaldo.c
+         src/backends/NetworkManagerRedHat.c
+         src/backends/NetworkManagerSlackware.c
+         src/backends/NetworkManagerArch.c
+         src/backends/NetworkManagerSuSE.c
+         src/backends/NetworkManagerDebian.c
+               - (nm_system_get_mtu): remove; MTU should be provided through the
+                       distro's system settings service plugin instead
+               - (nm_system_device_add_default_route_via_device): remove
+               - (nm_system_device_add_default_route_via_device_with_iface): remove
+               - (nm_system_device_replace_default_route): new function; call
+                       generic implementation
+
+       * src/backends/NetworkManagerGeneric.c
+         src/backends/NetworkManagerGeneric.h
+               - (nm_generic_device_add_default_route_via_device,
+                  nm_generic_device_add_default_route_via_device_with_iface): remove
+               - (nm_generic_device_replace_default_route): replace the default route
+                       with the given route via some gateway
+
+       * src/NetworkManagerSystem.c
+         src/NetworkManagerSystem.h
+               - (nm_system_device_set_from_ip4_config): let the policy handle updates
+                       to routing and DNS; but set the MTU here
+               - (nm_system_vpn_device_set_from_ip4_config): set the route with the
+                       ip_iface of the active device; use the standard MTU setting function
+               - (nm_system_set_mtu): remove
+               - (nm_system_device_set_mtu): consolidate MTU setting code in one place
+
 2008-03-07  Tambet Ingo  <tambet@gmail.com>
 
        Rework the interaction between ppp manager and pppd plugin. Register a well
index 9a03e79..70049f2 100644 (file)
@@ -3,3 +3,5 @@
 # Please keep this file sorted alphabetically.
 src/nm-netlink-monitor.c
 src/NetworkManager.c
+src/named-manager/nm-named-manager.c
+
index b1e3eda..5d72fec 100644 (file)
 #include "nm-activation-request.h"
 #include "nm-utils.h"
 #include "nm-device-interface.h"
+#include "nm-device.h"
 #include "nm-device-802-11-wireless.h"
 #include "nm-device-802-3-ethernet.h"
+#include "nm-gsm-device.h"
+#include "nm-cdma-device.h"
 #include "nm-dbus-manager.h"
 #include "nm-setting-connection.h"
 #include "NetworkManagerSystem.h"
+#include "nm-named-manager.h"
 
 struct NMPolicy {
        NMManager *manager;
        guint update_state_id;
+       GSList *pending_activation_checks;
        GSList *signal_ids;
+       GSList *dev_signal_ids;
+
+       NMDevice *default_device;
 };
 
 #define INVALID_TAG "invalid"
 
-static void schedule_change_check (NMPolicy *policy);
-
 static const char *
 get_connection_id (NMConnection *connection)
 {
@@ -64,362 +70,149 @@ get_connection_id (NMConnection *connection)
        return s_con->id;
 }
 
-/*
- * nm_policy_auto_get_best_device
- *
- * Find the best device to use, regardless of whether we are
- * "locked" on one device at this time.
- *
- */
-static NMDevice *
-nm_policy_auto_get_best_device (NMPolicy *policy,
-                                NMConnection **connection,
-                                char **specific_object)
+static void
+update_default_route (NMPolicy *policy, NMDevice *new)
 {
-       GSList *connections;
-       GSList *                                elt;
-       NMDevice8023Ethernet *  best_wired_dev = NULL;
-       guint                           best_wired_prio = 0;
-       NMConnection * best_wired_connection = NULL;
-       char * best_wired_specific_object = NULL;
-       NMDevice80211Wireless * best_wireless_dev = NULL;
-       guint                           best_wireless_prio = 0;
-       NMConnection * best_wireless_connection = NULL;
-       char * best_wireless_specific_object = NULL;
-       NMDevice *                      highest_priority_dev = NULL;
-
-       g_return_val_if_fail (connection != NULL, NULL);
-       g_return_val_if_fail (*connection == NULL, NULL);
-       g_return_val_if_fail (specific_object != NULL, NULL);
-       g_return_val_if_fail (*specific_object == NULL, NULL);
+       const char *ip_iface;
+
+       /* FIXME: Not sure if the following makes any sense. */
+       /* If iface and ip_iface are the same, it's a regular network device and we
+          treat it as such. However, if they differ, it's most likely something like
+          a serial device with ppp interface, so route all the traffic to it. */
+       ip_iface = nm_device_get_ip_iface (new);
+       if (strcmp (ip_iface, nm_device_get_iface (new))) {
+               nm_system_device_replace_default_route (ip_iface, 0, 0);
+       } else {
+               NMIP4Config *config;
+
+               config = nm_device_get_ip4_config (new);
+               nm_system_device_replace_default_route (ip_iface, nm_ip4_config_get_gateway (config),
+                                                       nm_ip4_config_get_mss (config));
+       }
+}
 
-       if (nm_manager_get_state (policy->manager) == NM_STATE_ASLEEP)
-               return NULL;
+static guint32
+get_device_priority (NMDevice *dev)
+{
+       if (NM_IS_CDMA_DEVICE (dev))
+               return 2;
 
-       /* System connections first, then user connections */
-       connections = nm_manager_get_connections (policy->manager, NM_CONNECTION_SCOPE_SYSTEM);
-       connections = g_slist_concat (connections, nm_manager_get_connections (policy->manager, NM_CONNECTION_SCOPE_USER));
+       if (NM_IS_GSM_DEVICE (dev))
+               return 3;
 
-       /* Remove connections that are in the invalid list. */
-       elt = connections;
-       while (elt) {
-               NMConnection *iter_connection = NM_CONNECTION (elt->data);
-               GSList *next = g_slist_next (elt);
+       if (NM_IS_DEVICE_802_11_WIRELESS (dev))
+               return 4;
 
-               if (g_object_get_data (G_OBJECT (iter_connection), INVALID_TAG)) {
-                       connections = g_slist_remove_link (connections, elt);
-                       g_object_unref (iter_connection);
-                       g_slist_free (elt);
-               }
-               elt = next;
-       }
+       if (NM_IS_DEVICE_802_3_ETHERNET (dev))
+               return 5;
 
-       for (elt = nm_manager_get_devices (policy->manager); elt; elt = elt->next) {
-               NMConnection *tmp_con = NULL;
-               char *tmp_obj = NULL;
-               gboolean carrier;
-               guint prio = 0;
-               NMDevice * dev = (NMDevice *)(elt->data);
-               guint32 caps;
-
-               carrier = nm_device_get_carrier (dev);
-               caps = nm_device_get_capabilities (dev);
-
-               tmp_con = nm_device_get_best_connection (dev, connections, &tmp_obj);
-               if (tmp_con == NULL) {
-                       NMActRequest *req = nm_device_get_act_request (dev);
-
-                       /* If the device is activating, the NMConnection it's got is the
-                        * best one.  In other words, follow activation of a particular
-                        * NMConnection through to success/failure rather than cutting it
-                        * off if it becomes invalid
-                        */
-                       tmp_con = req ? nm_act_request_get_connection (req) : NULL;
-                       if (!tmp_con)
-                               continue;
-               }
+       return 1;
+}
 
-               if (NM_IS_DEVICE_802_3_ETHERNET (dev)) {
-                       if (carrier)
-                               prio += 1;
-
-                       if (nm_device_get_act_request (dev) && carrier)
-                               prio += 1;
-
-                       if (prio > best_wired_prio) {
-                               best_wired_dev = NM_DEVICE_802_3_ETHERNET (dev);
-                               best_wired_prio = prio;
-                               best_wired_connection = tmp_con;
-                               best_wired_specific_object = tmp_obj;
-                       }
-               } else if (   NM_IS_DEVICE_802_11_WIRELESS (dev)
-                          && nm_manager_wireless_enabled (policy->manager)) {
-                       /* Bump by 1 so that _something_ gets chosen every time */
-                       prio += 1;
-
-                       if (carrier)
-                               prio += 1;
-
-                       if (nm_device_get_act_request (dev) && carrier)
-                               prio += 3;
-
-                       if (prio > best_wireless_prio) {
-                               best_wireless_dev = NM_DEVICE_802_11_WIRELESS (dev);
-                               best_wireless_prio = prio;
-                               best_wireless_connection = tmp_con;
-                               best_wireless_specific_object = tmp_obj;
-                       }
-               }
-       }
+static void
+update_routing_and_dns (NMPolicy *policy)
+{
+       NMDevice *best = NULL;
+       guint32 best_prio = 0;
+       GSList *devices, *iter;
+       NMNamedManager *named_mgr;
+       NMIP4Config *config;
+
+       devices = nm_manager_get_devices (policy->manager);
+       for (iter = devices; iter; iter = g_slist_next (iter)) {
+               NMDevice *dev = NM_DEVICE (iter->data);
+               guint32 prio;
+               
+               if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
+                       continue;
 
-       if (best_wired_dev) {
-               highest_priority_dev = NM_DEVICE (best_wired_dev);
-               *connection = g_object_ref (best_wired_connection);
-               *specific_object = best_wired_specific_object;
-       } else if (best_wireless_dev) {
-               gboolean can_activate;
-
-               can_activate = nm_device_802_11_wireless_can_activate (best_wireless_dev);
-               if (can_activate) {
-                       highest_priority_dev = NM_DEVICE (best_wireless_dev);
-                       *connection = g_object_ref (best_wireless_connection);
-                       *specific_object = best_wireless_specific_object;
+               prio = get_device_priority (dev);
+               if (prio > best_prio) {
+                       best = dev;
+                       best_prio = prio;
                }
        }
 
-       g_slist_foreach (connections, (GFunc) g_object_unref, NULL);
-       g_slist_free (connections);
+       if (!best)
+               goto out;
 
-       if (FALSE) {
-               nm_info ("AUTO: Best wired device = %s, best wireless device = %s, best connection name = '%s'",
-                        best_wired_dev ? nm_device_get_iface (NM_DEVICE (best_wired_dev)) : "(null)",
-                        best_wireless_dev ? nm_device_get_iface (NM_DEVICE (best_wireless_dev)) : "(null)",
-                        *connection ? get_connection_id (*connection) : "(none)");
-       }
+       update_default_route (policy, best);
 
-       return *connection ? highest_priority_dev : NULL;
+       named_mgr = nm_named_manager_get ();
+       config = nm_device_get_ip4_config (best);
+       nm_named_manager_add_ip4_config (named_mgr, config, NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE);
+       g_object_unref (named_mgr);
+
+out:
+       policy->default_device = best;  
 }
 
-/*
- * nm_policy_device_change_check
- *
- * Figures out which interface to switch the active
- * network connection to if our global network state has changed.
- * Global network state changes are triggered by:
- *    1) insertion/deletion of interfaces
- *    2) link state change of an interface
- *    3) wireless network topology changes
- *
- */
+typedef struct {
+       NMPolicy *policy;
+       NMDevice *device;
+       guint id;
+} ActivateData;
+
 static gboolean
-nm_policy_device_change_check (gpointer user_data)
+auto_activate_device (gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
-       GSList *iter;
-       guint32 caps;
-       NMConnection *connection = NULL;
-       NMConnection *old_connection = NULL;
-       NMActRequest *old_act_req = NULL;
-       char * specific_object = NULL;
-       NMDevice * new_dev = NULL;
-       NMDevice * old_dev = NULL;
-       gboolean do_switch = FALSE;
-
-       policy->update_state_id = 0;
+       ActivateData *data = (ActivateData *) user_data;
+       NMPolicy *policy;
+       NMConnection *best_connection;
+       char *specific_object = NULL;
+       GSList *connections, *iter;
 
-       switch (nm_manager_get_state (policy->manager)) {
-       case NM_STATE_CONNECTED:
-               old_dev = nm_manager_get_active_device (policy->manager);
-
-               /* Don't touch devices that are not upped/downed automatically */
-               if (!NM_IS_DEVICE_802_3_ETHERNET (old_dev) && !NM_IS_DEVICE_802_11_WIRELESS (old_dev))
-                       goto out;
-
-               caps = nm_device_get_capabilities (old_dev);
-
-               /* Don't interrupt semi-supported devices.  If the user chose
-                * one, they must explicitly choose to move to another device, we're not
-                * going to move for them.
-                */
-               if ((NM_IS_DEVICE_802_3_ETHERNET (old_dev) && !(caps & NM_DEVICE_CAP_CARRIER_DETECT))) {
-                       nm_info ("Old device '%s' was semi-supported and user chosen, won't"
-                                " change unless told to.",
-                                nm_device_get_iface (old_dev));
-                       goto out;
-               }
-               break;
-       case NM_STATE_CONNECTING:
-               for (iter = nm_manager_get_devices (policy->manager); iter; iter = iter->next) {
-                       NMDevice *d = NM_DEVICE (iter->data);
-
-                       if (nm_device_is_activating (d)) {
-                               if (nm_device_can_interrupt_activation (d)) {
-                                       old_dev = d;
-                                       break;
-                               } else
-                                       goto out;
-                       }
-               }
-               break;
-       case NM_STATE_DISCONNECTED:
-               if (nm_manager_activation_pending (policy->manager)) {
-                       nm_info ("There is a pending activation, won't change.");
-                       goto out;
-               }
-               break;
-       default:
-               break;
-       }
+       g_assert (data);
+       policy = data->policy;
 
-       new_dev = nm_policy_auto_get_best_device (policy, &connection, &specific_object);
-
-       if (old_dev) {
-               old_act_req = nm_device_get_act_request (old_dev);
-               if (old_act_req)
-                       old_connection = nm_act_request_get_connection (old_act_req);
-       }
-
-       /* Four cases here:
-        *
-        * 1) old device is NULL, new device is NULL - we aren't currently connected to anything, and we
-        *              can't find anything to connect to.  Do nothing.
-        *
-        * 2) old device is NULL, new device is good - we aren't currently connected to anything, but
-        *              we have something we can connect to.  Connect to it.
-        *
-        * 3) old device is good, new device is NULL - have a current connection, but it's no good since
-        *              auto device picking didn't come up with the save device.  Terminate current connection.
-        *
-        * 4) old device is good, new device is good - have a current connection, and auto device picking
-        *              came up with a device too.  More considerations:
-        *              a) different devices?  activate new device
-        *              b) same device, different access points?  activate new device
-        *              c) same device, same access point?  do nothing
-        */
+       /* System connections first, then user connections */
+       connections = nm_manager_get_connections (policy->manager, NM_CONNECTION_SCOPE_SYSTEM);
+       connections = g_slist_concat (connections, nm_manager_get_connections (policy->manager, NM_CONNECTION_SCOPE_USER));
 
-       if (!old_dev && !new_dev) {
-               ; /* Do nothing, wait for something like link-state to change, or an access point to be found */
-       } else if (!old_dev && new_dev) {
-               /* Activate new device */
-               nm_info ("SWITCH: no current connection, found better connection '%s (%s)'.",
-                        connection ? get_connection_id (connection) : "(none)",
-                        nm_device_get_iface (new_dev));
-               do_switch = TRUE;
-       } else if (old_dev && !new_dev) {
-               /* Terminate current connection */
-               nm_info ("SWITCH: terminating current connection '%s (%s)' because it's"
-                        " no longer valid.",
-                        old_connection ? get_connection_id (old_connection) : "(none)",
-                        nm_device_get_iface (old_dev));
-               do_switch = TRUE;
-       } else if (old_dev && new_dev) {
-               gboolean old_user_requested = nm_act_request_get_user_requested (old_act_req);
-               gboolean old_carrier = nm_device_get_carrier (old_dev);
-
-               /* If an old device is active or being activated (and has an active link),
-                * and its connection is a system connection, and the best connection is
-                * a user connection, don't switch.
-                */
-               if (   old_connection
-                   && (nm_connection_get_scope (old_connection) == NM_CONNECTION_SCOPE_SYSTEM)
-                   && (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_USER)
-                   && old_carrier)
-                       goto out;
-
-               if (   (nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM)
-                   && (nm_connection_get_scope (old_connection) == NM_CONNECTION_SCOPE_USER)) {
-                       do_switch = TRUE;
-                       nm_info ("SWITCH: found system connection '%s (%s)', overrides"
-                                " current connection '%s (%s)'.",
-                                connection ? get_connection_id (connection) : "(none)",
-                                nm_device_get_iface (new_dev),
-                                old_connection ? get_connection_id (old_connection) : "(none)",
-                                nm_device_get_iface (old_dev));
-                       goto do_switch;
-               }
+       /* Remove connections that are in the invalid list. */
+       iter = connections;
+       while (iter) {
+               NMConnection *iter_connection = NM_CONNECTION (iter->data);
+               GSList *next = g_slist_next (iter);
 
-               if (NM_IS_DEVICE_802_3_ETHERNET (old_dev)) {
-                       /* Only switch if the old device was not user requested, and we are switching to
-                        * a new device.  Note that new_dev will never be wireless since automatic device picking
-                        * above will prefer a wired device to a wireless device.
-                        */
-                       if ((!old_user_requested || !old_carrier) && (new_dev != old_dev)) {
-                               nm_info ("SWITCH: found better connection '%s (%s)' than "
-                                        " current connection '%s (%s)'.",
-                                        connection ? get_connection_id (connection) : "(none)",
-                                        nm_device_get_iface (new_dev),
-                                        old_connection ? get_connection_id (old_connection) : "(none)",
-                                        nm_device_get_iface (old_dev));
-                               do_switch = TRUE;
-                       }
-               } else if (NM_IS_DEVICE_802_11_WIRELESS (old_dev)) {
-                       /* Only switch if the old device's wireless config is invalid */
-                       if (NM_IS_DEVICE_802_11_WIRELESS (new_dev)) {
-                               NMAccessPoint *old_ap = nm_device_802_11_wireless_get_activation_ap (NM_DEVICE_802_11_WIRELESS (old_dev));
-                               int old_mode = nm_ap_get_mode (old_ap);
-                               gboolean same_activating = FALSE;
-
-                               /* Don't interrupt activation of a wireless device by
-                                * trying to auto-activate any connection on that device.
-                                */
-                               if (old_dev == new_dev && nm_device_is_activating (new_dev))
-                                       same_activating = TRUE;
-
-                               if (!same_activating && !old_carrier && (old_mode != IW_MODE_ADHOC)) {
-                                       NMSettingConnection * new_sc = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
-                                       NMSettingConnection * old_sc = (NMSettingConnection *) nm_connection_get_setting (old_connection, NM_TYPE_SETTING_CONNECTION);
-
-                                       nm_info ("SWITCH: found better connection '%s/%s'"
-                                                " than current connection '%s/%s'.  "
-                                                "have_link=%d",
-                                                nm_device_get_iface (new_dev),
-                                                new_sc->id,
-                                                nm_device_get_iface (old_dev),
-                                                old_sc->id,
-                                                old_carrier);
-                                       do_switch = TRUE;
-                               }
-                       } else if (NM_IS_DEVICE_802_3_ETHERNET (new_dev)) {
-                               /* Always prefer Ethernet over wireless, unless the user explicitly switched away. */
-                               if (!old_user_requested)
-                                       do_switch = TRUE;
-                       }
+               if (g_object_get_data (G_OBJECT (iter_connection), INVALID_TAG)) {
+                       connections = g_slist_remove_link (connections, iter);
+                       g_object_unref (iter_connection);
+                       g_slist_free (iter);
                }
+               iter = next;
        }
 
-do_switch:
-       if (do_switch) {
-               // FIXME: remove old_dev deactivation when multiple device support lands
-               if (old_dev)
-                       nm_device_interface_deactivate (NM_DEVICE_INTERFACE (old_dev));
-
-               if (new_dev) {
-                       GError *error = NULL;
-                       gboolean success;
-
-                       success = nm_manager_activate_device (policy->manager,
-                                                             new_dev,
-                                                             connection,
-                                                             specific_object,
-                                                             FALSE,
-                                                             &error);
-                       if (!success) {
-                               nm_warning ("Failed to automatically activate device %s: (%d) %s",
-                                           nm_device_get_iface (new_dev),
-                                           error->code,
-                                           error->message);
-                               g_error_free (error);
-                       }
+       best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object);
+       if (best_connection) {
+               GError *error = NULL;
+
+               if (!nm_manager_activate_device (policy->manager,
+                                                data->device,
+                                                best_connection,
+                                                specific_object,
+                                                FALSE,
+                                                &error)) {
+                       nm_warning ("Failed to automatically activate device %s: (%d) %s",
+                                   nm_device_get_iface (data->device),
+                                   error->code,
+                                   error->message);
+                       g_error_free (error);
                }
        }
 
-out:
-       if (connection)
-               g_object_unref (connection);
+       /* Remove this call's handler ID */
+       policy->pending_activation_checks = g_slist_remove (policy->pending_activation_checks, data);
+
+       g_object_unref (data->device);
+
+       g_slist_foreach (connections, (GFunc) g_object_unref, NULL);
+       g_slist_free (connections);
+
+       g_free (data);
        return FALSE;
 }
 
-
 /*****************************************************************************/
 
 static void
@@ -430,13 +223,41 @@ global_state_changed (NMManager *manager, NMState state, gpointer user_data)
 }
 
 static void
-schedule_change_check (NMPolicy *policy)
+schedule_activate_check (NMPolicy *policy, NMDevice *device)
 {
-       if (policy->update_state_id > 0)
+       ActivateData *data;
+       GSList *iter;
+       gboolean wireless_enabled;
+
+       if (nm_manager_get_state (policy->manager) == NM_STATE_ASLEEP)
+               return;
+
+       // FIXME: kind of a hack, but devices don't have access to the manager
+       // object directly
+       wireless_enabled = nm_manager_wireless_enabled (policy->manager);
+       if (!nm_device_can_activate (device, wireless_enabled))
+               return;
+
+       // FIXME: if a device is already activating (or activated) with a connection
+       // but another connection now overrides the current one for that device,
+       // deactivate the device and activate the new connection instead of just
+       // bailing if the device is already active
+       if (nm_device_get_act_request (device))
                return;
 
-       policy->update_state_id = g_idle_add (nm_policy_device_change_check,
-                                                          policy);
+       for (iter = policy->pending_activation_checks; iter; iter = g_slist_next (iter)) {
+               /* Only one pending activation check at a time */
+               if (((ActivateData *) iter->data)->device == device)
+                       return;
+       }
+
+       data = g_malloc0 (sizeof (ActivateData));
+       g_return_if_fail (data != NULL);
+
+       data->policy = policy;
+       data->device = g_object_ref (device);
+       data->id = g_idle_add (auto_activate_device, data);
+       policy->pending_activation_checks = g_slist_append (policy->pending_activation_checks, data);
 }
 
 static NMConnection *
@@ -458,69 +279,126 @@ device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data)
        NMConnection *connection = get_device_connection (device);
 
        if ((state == NM_DEVICE_STATE_FAILED) || (state == NM_DEVICE_STATE_CANCELLED)) {
-               schedule_change_check (policy);
-
                /* Mark the connection invalid so it doesn't get automatically chosen */
                if (connection) {
                        g_object_set_data (G_OBJECT (connection), INVALID_TAG, GUINT_TO_POINTER (TRUE));
                        nm_info ("Marking connection '%s' invalid.", get_connection_id (connection));
                }
+
+               if (state == NM_DEVICE_STATE_CANCELLED)
+                       schedule_activate_check (policy, device);
        } else if (state == NM_DEVICE_STATE_ACTIVATED) {
                /* Clear the invalid tag on the connection */
                if (connection)
                        g_object_set_data (G_OBJECT (connection), INVALID_TAG, NULL);
+
+               update_routing_and_dns (policy);
        } else if (state == NM_DEVICE_STATE_DISCONNECTED) {
-               schedule_change_check (policy);
+               update_routing_and_dns (policy);
+
+               schedule_activate_check (policy, device);
        }
 }
 
 static void
-device_carrier_changed (NMDevice *device, gboolean carrier_on, gpointer user_data)
+device_carrier_changed (NMDevice *device, gboolean carrier, gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
-
-       schedule_change_check (policy);
+       if (!carrier) {
+               if (NM_IS_DEVICE_802_3_ETHERNET (device))
+                       nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device));
+       } else {
+               schedule_activate_check ((NMPolicy *) user_data, device);
+       }
 }
 
 static void
 wireless_networks_changed (NMDevice80211Wireless *device, NMAccessPoint *ap, gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
+       schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device));
+}
 
-       schedule_change_check (policy);
+typedef struct {
+       gulong id;
+       NMDevice *device;
+} DeviceSignalID;
+
+static GSList *
+add_device_signal_id (GSList *list, gulong id, NMDevice *device)
+{
+       DeviceSignalID *data;
+
+       data = g_malloc0 (sizeof (DeviceSignalID));
+       if (!data)
+               return list;
+
+       data->id = id;
+       data->device = device;
+       return g_slist_append (list, data);
 }
 
 static void
 device_added (NMManager *manager, NMDevice *device, gpointer user_data)
 {
        NMPolicy *policy = (NMPolicy *) user_data;
+       gulong id;
 
-       g_signal_connect (device, "state-changed",
-                                         G_CALLBACK (device_state_changed),
-                                         policy);
+       id = g_signal_connect (device, "state-changed",
+                              G_CALLBACK (device_state_changed),
+                              policy);
+       policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
 
-       g_signal_connect (device, "carrier-changed",
-                                         G_CALLBACK (device_carrier_changed),
-                                         policy);
+       id = g_signal_connect (device, "carrier-changed",
+                              G_CALLBACK (device_carrier_changed),
+                              policy);
+       policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
 
        if (NM_IS_DEVICE_802_11_WIRELESS (device)) {
-               g_signal_connect (device, "access-point-added",
-                                                 G_CALLBACK (wireless_networks_changed),
-                                                 policy);
-               g_signal_connect (device, "access-point-removed",
-                                                 G_CALLBACK (wireless_networks_changed),
-                                                 policy);
+               id = g_signal_connect (device, "access-point-added",
+                                      G_CALLBACK (wireless_networks_changed),
+                                      policy);
+               policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
+
+               id = g_signal_connect (device, "access-point-removed",
+                                      G_CALLBACK (wireless_networks_changed),
+                                      policy);
+               policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
        }
 
-       schedule_change_check (policy);
+       schedule_activate_check (policy, device);
 }
 
 static void
 device_removed (NMManager *manager, NMDevice *device, gpointer user_data)
 {
        NMPolicy *policy = (NMPolicy *) user_data;
+       GSList *iter = policy->dev_signal_ids;
+
+       /* Clear any signal handlers for this device */
+       while (iter) {
+               DeviceSignalID *data = (DeviceSignalID *) iter->data;
+               GSList *next = g_slist_next (iter);
+
+               if (data->device == device) {
+                       policy->dev_signal_ids = g_slist_remove_link (policy->dev_signal_ids, iter);
+                       
+                       g_signal_handler_disconnect (data->device, data->id);
+                       g_free (data);
+                       g_slist_free (iter);
+               }
+               iter = next;
+       }
+
+       update_routing_and_dns (policy);
+}
+
+static void
+schedule_activate_all (NMPolicy *policy)
+{
+       GSList *iter, *devices;
 
-       schedule_change_check (policy);
+       devices = nm_manager_get_devices (policy->manager);
+       for (iter = devices; iter; iter = g_slist_next (iter))
+               schedule_activate_check (policy, NM_DEVICE (iter->data));
 }
 
 static void
@@ -528,9 +406,7 @@ connections_added (NMManager *manager,
                    NMConnectionScope scope,
                    gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
-
-       schedule_change_check (policy);
+       schedule_activate_all ((NMPolicy *) user_data);
 }
 
 static void
@@ -539,9 +415,7 @@ connection_added (NMManager *manager,
                   NMConnectionScope scope,
                   gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
-
-       schedule_change_check (policy);
+       schedule_activate_all ((NMPolicy *) user_data);
 }
 
 static void
@@ -550,12 +424,10 @@ connection_updated (NMManager *manager,
                     NMConnectionScope scope,
                     gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
-
        /* Clear the invalid tag on the connection if it got updated. */
        g_object_set_data (G_OBJECT (connection), INVALID_TAG, NULL);
 
-       schedule_change_check (policy);
+       schedule_activate_all ((NMPolicy *) user_data);
 }
 
 static void
@@ -564,12 +436,11 @@ connection_removed (NMManager *manager,
                     NMConnectionScope scope,
                     gpointer user_data)
 {
-       NMPolicy *policy = (NMPolicy *) user_data;
        GSList *iter;
 
        /* If the connection just removed was active, deactive it */
        for (iter = nm_manager_get_devices (manager); iter; iter = g_slist_next (iter)) {
-               NMDevice *device = (NMDevice *) iter->data;
+               NMDevice *device = NM_DEVICE (iter->data);
                NMActRequest *req = nm_device_get_act_request (device);
                NMConnection *dev_connection;
 
@@ -577,11 +448,11 @@ connection_removed (NMManager *manager,
                        continue;
 
                dev_connection = nm_act_request_get_connection (req);
-               if (dev_connection == connection)
+               if (dev_connection == connection) {
                        nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device));
+                       schedule_activate_check ((NMPolicy *) user_data, device);
+               }
        }
-
-       schedule_change_check (policy);
 }
 
 NMPolicy *
@@ -640,15 +511,27 @@ nm_policy_destroy (NMPolicy *policy)
 
        g_return_if_fail (policy != NULL);
 
-       if (policy->update_state_id) {
-               g_source_remove (policy->update_state_id);
-               policy->update_state_id = 0;
+       for (iter = policy->pending_activation_checks; iter; iter = g_slist_next (iter)) {
+               ActivateData *data = (ActivateData *) iter->data;
+
+               g_source_remove (data->id);
+               g_object_unref (data->device);
+               g_free (data);
        }
+       g_slist_free (policy->pending_activation_checks);
 
        for (iter = policy->signal_ids; iter; iter = g_slist_next (iter))
                g_signal_handler_disconnect (policy->manager, (gulong) iter->data);
        g_slist_free (policy->signal_ids);
 
+       for (iter = policy->dev_signal_ids; iter; iter = g_slist_next (iter)) {
+               DeviceSignalID *data = (DeviceSignalID *) iter->data;
+
+               g_signal_handler_disconnect (data->device, data->id);
+               g_free (data);
+       }
+       g_slist_free (policy->dev_signal_ids);
+
        g_object_unref (policy->manager);
        g_free (policy);
 }
index faec48e..603cd73 100644 (file)
@@ -190,11 +190,9 @@ nm_system_device_set_from_ip4_config (const char *iface,
                                                           NMIP4Config *config,
                                                           gboolean route_to_iface)
 {
-       NMNamedManager * named_mgr;
-       struct nl_handle *      nlh = NULL;
-       struct rtnl_addr *      addr = NULL;
-       int                             err;
-       int len, i;
+       struct nl_handle *nlh = NULL;
+       struct rtnl_addr *addr = NULL;
+       int len, i, err;
        guint32 flags;
 
        g_return_val_if_fail (iface != NULL, FALSE);
@@ -224,13 +222,6 @@ nm_system_device_set_from_ip4_config (const char *iface,
 
        sleep (1);
 
-       if (route_to_iface)
-               nm_system_device_add_default_route_via_device_with_iface (iface);
-       else
-               nm_system_device_set_ip4_route (iface, config,
-                                                                 nm_ip4_config_get_gateway (config), 0, 0, 
-                                                                 nm_ip4_config_get_mss (config));
-
        len = nm_ip4_config_get_num_static_routes (config);
        for (i = 0; i < len; i++) {
                guint32 mss = nm_ip4_config_get_mss (config);
@@ -240,9 +231,8 @@ nm_system_device_set_from_ip4_config (const char *iface,
                nm_system_device_set_ip4_route (iface, config, route, saddr, 0xffffffff, mss);
        }               
 
-       named_mgr = nm_named_manager_get ();
-       nm_named_manager_add_ip4_config (named_mgr, config);
-       g_object_unref (named_mgr);
+       if (nm_ip4_config_get_mtu (config))
+               nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
 
        return TRUE;
 }
@@ -339,7 +329,6 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
        NMIP4Config *           ad_config = NULL;
        struct nl_handle *      nlh = NULL;
        struct rtnl_addr *      addr = NULL;
-       struct rtnl_link *      request = NULL;
        NMNamedManager *named_mgr;
        int iface_idx;
 
@@ -347,7 +336,7 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
 
        /* 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))) {
-               nm_system_device_set_ip4_route (nm_device_get_iface (active_device),
+               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),
@@ -376,28 +365,15 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
                nm_warning ("couldn't create rtnl address!\n");
 
        /* Set the MTU */
-       if ((request = rtnl_link_alloc ())) {
-               struct rtnl_link * old;
-               guint32 mtu;
-
-               old = nm_netlink_index_to_rtnl_link (iface_idx);
-               mtu = nm_ip4_config_get_mtu (config);
-               if (mtu == 0)
-                       mtu = 1412;  /* Default to 1412 (vpnc) */
-               rtnl_link_set_mtu (request, mtu);
-               rtnl_link_change (nlh, old, request, 0);
-
-               rtnl_link_put (old);
-               rtnl_link_put (request);
-       }
+       if (nm_ip4_config_get_mtu (config))
+               nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config));
 
        sleep (1);
 
        nm_system_device_flush_routes_with_iface (iface);
 
        if (g_slist_length (routes) == 0) {
-               nm_system_delete_default_route ();
-               nm_system_device_add_default_route_via_device_with_iface (iface);
+               nm_system_device_replace_default_route (iface, 0, 0);
        } else {
                GSList *iter;
 
@@ -421,7 +397,7 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
 
 out:
        named_mgr = nm_named_manager_get ();
-       nm_named_manager_add_ip4_config (named_mgr, config);
+       nm_named_manager_add_ip4_config (named_mgr, config, NM_NAMED_IP_CONFIG_TYPE_VPN);
        g_object_unref (named_mgr);
 
        return TRUE;
@@ -498,42 +474,37 @@ out:
 }
 
 
-/*
- * nm_system_set_mtu
- *
- * Set the MTU for a given device.
- */
-void nm_system_set_mtu (NMDevice *dev)
+gboolean
+nm_system_device_set_mtu (const char *iface, guint32 mtu)
 {
-       struct rtnl_link *      request;
-       struct rtnl_link *      old;
-       unsigned long           mtu;
-       struct nl_handle *      nlh;
-       guint32 idx;
-
-       mtu = nm_system_get_mtu (dev);
-       if (!mtu)
-               return;
+       struct rtnl_link *old;
+       struct rtnl_link *new;
+       gboolean success = FALSE;
+       struct nl_handle *nlh;
+       int iface_idx;
 
-       request = rtnl_link_alloc ();
-       if (!request)
-               return;
+       g_return_val_if_fail (iface != NULL, FALSE);
+       g_return_val_if_fail (mtu > 0, FALSE);
 
-       idx = nm_netlink_iface_to_index (nm_device_get_iface (dev));
-       old = nm_netlink_index_to_rtnl_link (idx);
-       if (!old)
-               goto out_request;
+       new = rtnl_link_alloc ();
+       if (!new)
+               return FALSE;
 
-       nm_info ("Setting MTU of interface '%s' to %ld",
-                nm_device_get_iface (dev),
-                mtu);
-       rtnl_link_set_mtu (request, mtu);
-       nlh = nm_netlink_get_default_handle ();
-       if (nlh)
-               rtnl_link_change (nlh, old, request, 0);
+       iface_idx = nm_netlink_iface_to_index (iface);
+       old = nm_netlink_index_to_rtnl_link (iface_idx);
+       if (old) {
+               rtnl_link_set_mtu (new, mtu);
+               nlh = nm_netlink_get_default_handle ();
+               if (nlh) {
+                       rtnl_link_change (nlh, old, new, 0);
+                       success = TRUE;
+               }
+               rtnl_link_put (old);
+       }
 
-       rtnl_link_put (old);
-out_request:
-       rtnl_link_put (request);
+       rtnl_link_put (new);
+       return success;
 }
 
+
+
index 5db80ad..aa21795 100644 (file)
@@ -38,8 +38,9 @@ gboolean              nm_system_device_has_active_routes                      (NMDevice *dev);
 void                   nm_system_device_flush_routes                           (NMDevice *dev);
 void                   nm_system_device_flush_routes_with_iface        (const char *iface);
 
-void                   nm_system_device_add_default_route_via_device(NMDevice *dev);
-void                   nm_system_device_add_default_route_via_device_with_iface(const char *iface);
+void                   nm_system_device_replace_default_route      (const char *iface,
+                                                             guint32 gw,
+                                                             guint32 mss);
 
 void                   nm_system_device_add_route_via_device_with_iface (const char *iface, const char *route);
 
@@ -82,8 +83,7 @@ void                  nm_system_set_hostname (NMIP4Config *config);
 void                   nm_system_activate_nis (NMIP4Config *config);
 void                   nm_system_shutdown_nis (void);
 
-void                   nm_system_set_mtu (NMDevice *dev);
-guint32                nm_system_get_mtu (NMDevice *dev);
+gboolean               nm_system_device_set_mtu (const char *iface, guint32 mtu);
 
 gboolean               nm_system_should_modify_resolv_conf (void);
 
index 373335e..e8550f5 100644 (file)
@@ -65,26 +65,17 @@ void nm_system_init (void)
 }
 
 /*
- * nm_system_device_add_default_route_via_device
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device (dev);
-}
-
-
-/*
- * nm_system_device_add_default_route_via_device_with_iface
- *
- * Add default route to the given device
- *
- */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
-{
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
 
 /*
@@ -686,14 +677,3 @@ void nm_system_set_hostname (NMIP4Config *config)
 {
 }
 
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-
-}
index 6be15f9..a9acbe8 100644 (file)
@@ -54,26 +54,17 @@ void nm_system_init (void)
 }
 
 /*
- * nm_system_device_add_default_route_via_device
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device (dev);
-}
-
-
-/*
- * nm_system_device_add_default_route_via_device_with_iface
- *
- * Add default route to the given device
- *
- */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
-{
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
 
 /*
@@ -405,14 +396,3 @@ gboolean nm_system_should_modify_resolv_conf (void)
        return TRUE;
 }
 
-
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
index d1cc6fb..78d2456 100644 (file)
@@ -243,37 +243,21 @@ void nm_system_device_add_route_via_device_with_iface (const char *iface, const
        g_free (buf);
 }
 
-/*
- * nm_system_device_add_default_route_via_device
- *
- * Flush all routes associated with a network device
- *
- */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
-{
-       g_return_if_fail (dev != NULL);
-
-       nm_system_device_add_default_route_via_device_with_iface (nm_device_get_iface (dev));
-}
 
 /*
- * nm_system_device_add_default_route_via_device_with_iface
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       char    *buf;
-
-       g_return_if_fail (iface != NULL);
-
-       /* Add default gateway */
-       buf = g_strdup_printf ("/usr/sbin/ip route add default dev %s", iface);
-       nm_spawn_process (buf);
-       g_free (buf);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
+
  
 /*
  * nm_system_flush_loopback_routes
@@ -372,17 +356,6 @@ gboolean nm_system_should_modify_resolv_conf (void)
 
 
 /*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
-
-/*
  * nm_system_device_get_system_config
  *
  * Read in the config file for a device.
index adc57ac..50dd60f 100644 (file)
@@ -50,33 +50,34 @@ void nm_generic_init (void)
 }
 
 /*
- * nm_generic_device_add_default_route_via_device
+ * nm_generic_replace_default_route
  *
- * Add default route to the given device
+ * Replace default route with one via the current device
  *
  */
-void nm_generic_device_add_default_route_via_device (NMDevice *dev)
+void
+nm_generic_device_replace_default_route (const char *iface, guint32 gw, guint32 mss)
 {
-       g_return_if_fail (dev != NULL);
+       char *buf, *addr_str = NULL, *mss_str = NULL;
 
-       nm_system_device_add_default_route_via_device_with_iface (nm_device_get_iface (dev));
-}
+       g_return_if_fail (iface != NULL);
 
+       if (gw > 0) {
+               struct in_addr addr = { .s_addr = gw };
+               char buf2[INET_ADDRSTRLEN + 1];
 
-/*
- * nm_generic_device_add_default_route_via_device_with_iface
- *
- * Add default route to the given device
- *
- */
-void nm_generic_device_add_default_route_via_device_with_iface (const char *iface)
-{
-       char    *buf;
+               memset (buf2, 0, sizeof (buf2));
+               inet_ntop (AF_INET, &addr, buf2, INET_ADDRSTRLEN);      
+               addr_str = g_strdup_printf ("via %s", buf2);
+       }
 
-       g_return_if_fail (iface != NULL);
+       if (mss > 0)
+               mss_str = g_strdup_printf ("advmss %d", mss);
 
-       /* Add default gateway */
-       buf = g_strdup_printf (IP_BINARY_PATH" route add default dev %s", iface);
+       buf = g_strdup_printf (IP_BINARY_PATH" route replace default %s %s dev %s",
+                              addr_str ? addr_str : "",
+                              mss_str ? mss_str : "",
+                              iface);
        nm_spawn_process (buf);
        g_free (buf);
 }
@@ -452,14 +453,3 @@ gboolean nm_generic_should_modify_resolv_conf (void)
        return TRUE;
 }
 
-
-/*
- * nm_generic_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_generic_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
index 9629443..f69b08c 100644 (file)
@@ -39,8 +39,7 @@ gboolean              nm_generic_device_has_active_routes                     (NMDevice *dev);
 void                   nm_generic_device_flush_routes                          (NMDevice *dev);
 void                   nm_generic_device_flush_routes_with_iface       (const char *iface);
 
-void                   nm_generic_device_add_default_route_via_device(NMDevice *dev);
-void                   nm_generic_device_add_default_route_via_device_with_iface(const char *iface);
+void            nm_generic_device_replace_default_route (const char *iface, guint32 gw, guint32 mss);
 
 void                   nm_generic_device_add_route_via_device_with_iface (const char *iface, const char *route);
 
@@ -78,9 +77,6 @@ void                  nm_generic_set_hostname (NMIP4Config *config);
 void                   nm_generic_activate_nis (NMIP4Config *config);
 void                   nm_generic_shutdown_nis (void);
 
-void                   nm_generic_set_mtu (NMDevice *dev);
-guint32                nm_generic_get_mtu (NMDevice *dev);
-
 gboolean               nm_generic_should_modify_resolv_conf (void);
 
 #endif
index c7469a2..944bb8c 100644 (file)
@@ -404,25 +404,17 @@ void *nm_system_device_get_system_config (NMDevice *dev)
 }
 
 /*
- * nm_system_device_add_default_route_via_device
- *
- * Flush all routes associated with a network device
- *
- */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
-{
-       nm_generic_device_add_default_route_via_device (dev);
-}
-/*
- * nm_system_device_add_default_route_via_device_with_iface
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
  
 void nm_system_device_free_system_config (NMDevice *dev, void *system_config_data)
@@ -491,13 +483,4 @@ gboolean nm_system_should_modify_resolv_conf (void)
        return TRUE;
 }
 
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
+
index cb96b7e..9e457df 100644 (file)
@@ -76,26 +76,17 @@ void nm_system_device_flush_routes_with_iface (const char *iface)
 
 
 /*
- * nm_system_device_add_default_route_via_device
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device (dev);
-}
-
-
-/*
- * nm_system_device_add_default_route_via_device_with_iface
- *
- * Add default route to the given device
- *
- */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
-{
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
 
 
@@ -527,13 +518,3 @@ gboolean nm_system_should_modify_resolv_conf (void)
        return TRUE;
 }
 
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-unsigned int nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
index 5f653f7..7e3ce24 100644 (file)
@@ -73,26 +73,17 @@ void nm_system_device_flush_routes_with_iface (const char *iface)
 
 
 /*
- * nm_system_device_add_default_route_via_device
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device (dev);
-}
-
-
-/*
- * nm_system_device_add_default_route_via_device_with_iface
- *
- * Add default route to the given device
- *
- */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
-{
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
 
 
@@ -543,14 +534,3 @@ gboolean nm_system_should_modify_resolv_conf (void)
        return TRUE;
 }
 
-
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
index ba6b67e..599534d 100644 (file)
@@ -219,25 +219,17 @@ void nm_system_device_add_route_via_device_with_iface (const char *iface, const
 }
 
 /*
- * nm_system_device_add_default_route_via_device
- *
- * Flush all routes associated with a network device
- *
- */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
-{
-       nm_generic_device_add_default_route_via_device (dev);
-}
-
-/*
- * nm_system_device_add_default_route_via_device_with_iface
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
  
  
@@ -322,14 +314,3 @@ gboolean nm_system_should_modify_resolv_conf (void)
        return TRUE;
 }
 
-
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       return 0;
-}
index e5afd61..eeefb66 100644 (file)
@@ -80,26 +80,17 @@ void nm_system_device_flush_routes_with_iface (const char *iface)
 
 
 /*
- * nm_system_device_add_default_route_via_device
+ * nm_system_device_replace_default_route
  *
  * Add default route to the given device
  *
  */
-void nm_system_device_add_default_route_via_device (NMDevice *dev)
+void
+nm_system_device_replace_default_route (const char *iface,
+                                        guint32 gw,
+                                        guint32 mss)
 {
-       nm_generic_device_add_default_route_via_device (dev);
-}
-
-
-/*
- * nm_system_device_add_default_route_via_device_with_iface
- *
- * Add default route to the given device
- *
- */
-void nm_system_device_add_default_route_via_device_with_iface (const char *iface)
-{
-       nm_generic_device_add_default_route_via_device_with_iface (iface);
+       nm_generic_device_replace_default_route (iface, gw, mss);
 }
 
 
@@ -724,20 +715,3 @@ out_gfree:
        return ret;
 }
 
-
-/*
- * nm_system_get_mtu
- *
- * Return a user-provided or system-mandated MTU for this device or zero if
- * no such MTU is provided.
- */
-guint32 nm_system_get_mtu (NMDevice *dev)
-{
-       SuSEDeviceConfigData *  sys_data;
-
-       sys_data = nm_device_get_system_config_data (dev);
-       if (!sys_data)
-               return 0;
-
-       return sys_data->mtu;
-}
index 2dfc0a9..e6cf1b4 100644 (file)
@@ -36,6 +36,8 @@
 #include <glib.h>
 #include <dbus/dbus.h>
 
+#include <glib/gi18n.h>
+
 #include "nm-ip4-config.h"
 #include "nm-utils.h"
 #include "NetworkManagerSystem.h"
@@ -61,19 +63,20 @@ G_DEFINE_TYPE(NMNamedManager, nm_named_manager, G_TYPE_OBJECT)
                                          NM_TYPE_NAMED_MANAGER, \
                                          NMNamedManagerPrivate))
 
-static NMIP4Config *get_last_default_domain (NMNamedManager *mgr);
-
 static gboolean add_all_ip4_configs_to_named (NMNamedManager *mgr);
 
-static gboolean rewrite_resolv_conf (NMNamedManager *mgr, NMIP4Config *config, GError **error);
+static gboolean rewrite_resolv_conf (NMNamedManager *mgr, GError **error);
 
 static gboolean remove_ip4_config_from_named (NMNamedManager *mgr, NMIP4Config *config);
 
 
 struct NMNamedManagerPrivate {
-       gboolean                use_named;
-       NMDBusManager * dbus_mgr;
-       GSList *                configs;
+       gboolean        use_named;
+       NMDBusManager * dbus_mgr;
+
+       NMIP4Config *   vpn_config;
+       NMIP4Config *   device_config;
+       GSList *        configs;
 
        gboolean disposed;
 };
@@ -145,7 +148,7 @@ nm_named_manager_name_owner_changed (NMDBusManager *dbus_mgr,
 
        if (handled) {
                GError *error = NULL;
-               if (!rewrite_resolv_conf (mgr, get_last_default_domain (mgr), &error)) {
+               if (!rewrite_resolv_conf (mgr, &error)) {
                        nm_warning ("Could not write resolv.conf.  Error: '%s'",
                                    error ? error->message : "(none)");
                        g_error_free (error);
@@ -177,7 +180,7 @@ nm_named_manager_dbus_connection_changed (NMDBusManager *dbus_mgr,
 
        if (handled) {
                GError *error = NULL;
-               if (!rewrite_resolv_conf (mgr, get_last_default_domain (mgr), &error)) {
+               if (!rewrite_resolv_conf (mgr, &error)) {
                        nm_warning ("Could not write resolv.conf.  Error: '%s'",
                                    error ? error->message : "(none)");
                        g_error_free (error);
@@ -186,87 +189,79 @@ nm_named_manager_dbus_connection_changed (NMDBusManager *dbus_mgr,
 }
 
 static char *
-compute_nameservers (NMNamedManager *mgr, NMIP4Config *config)
+compute_nameservers (NMIP4Config *config)
 {
-       int i, num_nameservers;
+       int i, num;
        GString *str = NULL;
 
-       g_return_val_if_fail (mgr != NULL, g_strdup (""));
-       g_return_val_if_fail (config != NULL, g_strdup (""));
+       g_return_val_if_fail (config != NULL, NULL);
+
+       num = nm_ip4_config_get_num_nameservers (config);
+       if (num == 0)
+               return NULL;
 
-       num_nameservers = nm_ip4_config_get_num_nameservers (config);
-       if (num_nameservers > 3)
-               num_nameservers = 3; /* 'man resolv.conf' says we can't have > 3 */
-       for (i = 0; i < num_nameservers; i++)
-       {
+       str = g_string_new ("");
+       for (i = 0; i < num; i++) {
                #define ADDR_BUF_LEN 50
                struct in_addr addr;
                char *buf;
 
-               if (!str)
-                       str = g_string_new ("");
-
                addr.s_addr = nm_ip4_config_get_nameserver (config, i);
                buf = g_malloc0 (ADDR_BUF_LEN);
+               if (!buf)
+                       continue;
+
                inet_ntop (AF_INET, &addr, buf, ADDR_BUF_LEN);
 
+               if (i == 3) {
+                       g_string_append (str, "# ");
+                       g_string_append (str, _("NOTE: the glibc resolver does not support more than 3 nameservers."));
+                       g_string_append (str, "\n# ");
+                       g_string_append (str, _("The nameservers listed below may not be recognized."));
+                       g_string_append_c (str, '\n');
+               }
+
                g_string_append (str, "nameserver ");
                g_string_append (str, buf);
                g_string_append_c (str, '\n');
                g_free (buf);
        }
 
-       if (!str)
-               return g_strdup ("");
-
        return g_string_free (str, FALSE);
 }
 
-static char *
-compute_searches (NMNamedManager *mgr, NMIP4Config *config)
+static void
+merge_one_ip4_config (NMIP4Config *dst, NMIP4Config *src)
 {
-       int i, num_searches;
-       GString *str = NULL;
-
-       g_return_val_if_fail (mgr != NULL, g_strdup (""));
-
-       /* config can be NULL */
-       if (!config)
-               return g_strdup ("");
-
-       num_searches = nm_ip4_config_get_num_domains (config);
-       for (i = 0; i < num_searches; i++)
-       {
-               if (!str)
-                       str = g_string_new ("search");
-
-               g_string_append_c (str, ' ');
-               g_string_append (str, nm_ip4_config_get_domain (config, i));            
-       }
+       guint32 num, i;
 
-       if (!str)
-               return g_strdup ("");
-       else
-               g_string_append_c (str, '\n');
+       num = nm_ip4_config_get_num_nameservers (src);
+       for (i = 0; i < num; i++)
+               nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
 
-       return g_string_free (str, FALSE);
+       num = nm_ip4_config_get_num_domains (src);
+       for (i = 0; i < num; i++)
+               nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
 }
 
 static gboolean
-rewrite_resolv_conf (NMNamedManager *mgr, NMIP4Config *config, GError **error)
+rewrite_resolv_conf (NMNamedManager *mgr, GError **error)
 {
-       const char *    tmp_resolv_conf = RESOLV_CONF ".tmp";
-       char *          searches = NULL;
-       FILE *          f;
-       NMIP4Config *ns_config = config;
+       NMNamedManagerPrivate *priv;
+       const char *tmp_resolv_conf = RESOLV_CONF ".tmp";
+       char *searches = NULL;
+       guint32 num_domains, i;
+       NMIP4Config *composite;
+       GSList *iter;
+       FILE *f;
 
-       /* If no config, we don't have anything to update, so exit silently */
-       if (!config)
-               return TRUE;
+       g_return_val_if_fail (error != NULL, FALSE);
+       g_return_val_if_fail (*error == NULL, FALSE);
+
+       priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
 
        /* If the sysadmin disabled modifying resolv.conf, exit silently */
-       if (!nm_system_should_modify_resolv_conf ())
-       {
+       if (!nm_system_should_modify_resolv_conf ()) {
                nm_info ("DHCP returned name servers but system has disabled dynamic modification!");
                return TRUE;
        }
@@ -290,85 +285,107 @@ rewrite_resolv_conf (NMNamedManager *mgr, NMIP4Config *config, GError **error)
                return FALSE;
        }
 
-       /* If the ip4 config is a secondary config and has no nameservers, use the
-        * nameservers from the primary config.
-        */
-       if (   nm_ip4_config_get_secondary (config)
-           && !nm_ip4_config_get_num_nameservers (config)) {
-               ns_config = mgr->priv->configs->data;
+       /* Construct the composite config from all the currently active IP4Configs */
+       composite = nm_ip4_config_new ();
+
+       if (priv->vpn_config)
+               merge_one_ip4_config (composite, priv->vpn_config);
+
+       if (priv->device_config)
+               merge_one_ip4_config (composite, priv->device_config);
+
+       for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
+               NMIP4Config *config = NM_IP4_CONFIG (iter->data);
+
+               if ((config == priv->vpn_config) || (config == priv->device_config))
+                       continue;
+
+               merge_one_ip4_config (composite, config);
        }
-       g_return_val_if_fail (ns_config != NULL, FALSE);
 
-       searches = compute_searches (mgr, ns_config);
+       /* Compute resolv.conf search domains */
+       num_domains = nm_ip4_config_get_num_domains (composite);
+       if (num_domains > 0) {
+               GString *str;
+
+               str = g_string_new ("search");
+               for (i = 0; i < num_domains; i++) {
+                       g_string_append_c (str, ' ');
+                       g_string_append (str, nm_ip4_config_get_domain (composite, i));         
+               }
+
+               g_string_append_c (str, '\n');
+               searches = g_string_free (str, FALSE);
+       }
 
        if (mgr->priv->use_named == TRUE) {
                /* Using caching-nameserver & local DNS */
                if (fprintf (f,
                             "%s%s%s",
                             "; Use a local caching nameserver controlled by NetworkManager\n\n",
-                            searches,
+                            searches ? searches : "",
                             "\nnameserver 127.0.0.1\n") < 0) {
                        g_set_error (error,
                                     NM_NAMED_MANAGER_ERROR,
                                     NM_NAMED_MANAGER_ERROR_SYSTEM,
                                     "Could not write " RESOLV_CONF ": %s\n",
                                     g_strerror (errno));
-                       fclose (f);
-                       g_free (searches);
-                       return FALSE;
                }
        } else {
                /* Using glibc resolver */
-               char *nameservers = compute_nameservers (mgr, ns_config);
+               char *nameservers = compute_nameservers (composite);
 
-               if ((fprintf (f, "%s\n\n", searches) < 0) ||
-                   (fprintf (f, "%s\n\n", nameservers) < 0)) {
+               if ((fprintf (f, "%s\n\n", searches ? searches : "") < 0) ||
+                   (fprintf (f, "%s\n\n", nameservers ? nameservers : "") < 0)) {
                        g_set_error (error,
                                     NM_NAMED_MANAGER_ERROR,
                                     NM_NAMED_MANAGER_ERROR_SYSTEM,
                                     "Could not write to " RESOLV_CONF ": %s\n",
                                     g_strerror (errno));
-                       g_free (nameservers);
-                       g_free (searches);
-                       fclose (f);
-                       return FALSE;
                }
                g_free (nameservers);
        }
-       g_free (searches);
 
        if (fclose (f) < 0) {
-               g_set_error (error,
-                            NM_NAMED_MANAGER_ERROR,
-                            NM_NAMED_MANAGER_ERROR_SYSTEM,
-                            "Could not close " RESOLV_CONF ": %s\n",
-                            g_strerror (errno));
-               return FALSE;
+               if (*error == NULL) {
+                       g_set_error (error,
+                                    NM_NAMED_MANAGER_ERROR,
+                                    NM_NAMED_MANAGER_ERROR_SYSTEM,
+                                    "Could not close " RESOLV_CONF ": %s\n",
+                                    g_strerror (errno));
+               }
        }
 
-       if (rename (tmp_resolv_conf, RESOLV_CONF) < 0) {
-               g_set_error (error,
-                            NM_NAMED_MANAGER_ERROR,
-                            NM_NAMED_MANAGER_ERROR_SYSTEM,
-                            "Could not replace " RESOLV_CONF ": %s\n",
-                            g_strerror (errno));
-               return FALSE;
+       g_free (searches);
+
+       if (*error == NULL) {
+               if (rename (tmp_resolv_conf, RESOLV_CONF) < 0) {
+                       g_set_error (error,
+                                    NM_NAMED_MANAGER_ERROR,
+                                    NM_NAMED_MANAGER_ERROR_SYSTEM,
+                                    "Could not replace " RESOLV_CONF ": %s\n",
+                                    g_strerror (errno));
+               } else {
+                       nm_system_update_dns ();
+               }
        }
-       nm_system_update_dns ();
-       return TRUE;
+
+       return *error ? FALSE : TRUE;
 }
 
 static const char *
-get_domain_for_config (NMIP4Config *config, gboolean *dflt)
+get_domain_for_config (NMNamedManager *mgr, NMIP4Config *config, gboolean *dflt)
 {
+       NMNamedManagerPrivate *priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
        gboolean is_dflt = FALSE;
        const char *domain;
 
        g_return_val_if_fail (config != NULL, NULL);
 
        /* Primary configs always use default domain */
-       if (!nm_ip4_config_get_secondary (config))
+       if (config == priv->vpn_config)
                is_dflt = TRUE;
+
        /* Any config without a domain becomes default */
        if (nm_ip4_config_get_num_domains (config) == 0)
                is_dflt = TRUE;
@@ -387,6 +404,7 @@ get_domain_for_config (NMIP4Config *config, gboolean *dflt)
 static gboolean
 add_ip4_config_to_named (NMNamedManager *mgr, NMIP4Config *config)
 {
+       NMNamedManagerPrivate *priv;
        const char *domain;
        NMIP4Config *ns_config = config;
        int i, num_nameservers;
@@ -400,15 +418,17 @@ add_ip4_config_to_named (NMNamedManager *mgr, NMIP4Config *config)
        g_return_val_if_fail (mgr != NULL, FALSE);
        g_return_val_if_fail (config != NULL, FALSE);
 
+       priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
        dbus_error_init (&error);
 
-       dbus_connection = nm_dbus_manager_get_dbus_connection (mgr->priv->dbus_mgr);
+       dbus_connection = nm_dbus_manager_get_dbus_connection (priv->dbus_mgr);
        if (!dbus_connection) {
                nm_warning ("could not get dbus connection.");
                goto out;
        }
 
-       if (!(domain = get_domain_for_config (config, &dflt)))
+       if (!(domain = get_domain_for_config (mgr, config, &dflt)))
                goto out;
 
        message = dbus_message_new_method_call (NAMED_DBUS_SERVICE,
@@ -427,9 +447,9 @@ add_ip4_config_to_named (NMNamedManager *mgr, NMIP4Config *config)
        /* If the ip4 config is a secondary config and has no nameservers, use the
         * nameservers from the primary config.
         */
-       if (   nm_ip4_config_get_secondary (config)
+       if (   (config == priv->vpn_config)
            && !nm_ip4_config_get_num_nameservers (config)) {
-               ns_config = mgr->priv->configs->data;
+               ns_config = priv->device_config;
        }
        g_return_val_if_fail (ns_config != NULL, FALSE);
 
@@ -486,12 +506,27 @@ out:
 static gboolean
 add_all_ip4_configs_to_named (NMNamedManager *mgr)
 {
-       GSList *elt = NULL;
+       NMNamedManagerPrivate *priv;
+       GSList *iter = NULL;
 
        g_return_val_if_fail (mgr != NULL, FALSE);
 
-       for (elt = mgr->priv->configs; elt; elt = g_slist_next (elt))
-               add_ip4_config_to_named (mgr, (NMIP4Config *)(elt->data));
+       priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
+       if (priv->vpn_config)
+               add_ip4_config_to_named (mgr, priv->vpn_config);
+
+       if (priv->device_config)
+               add_ip4_config_to_named (mgr, priv->device_config);
+
+       for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
+               NMIP4Config *config = NM_IP4_CONFIG (iter->data);
+
+               if ((config == priv->vpn_config) || (config == priv->device_config))
+                       continue;
+
+               add_ip4_config_to_named (mgr, config);
+       }
                
        return TRUE;
 }
@@ -581,7 +616,7 @@ remove_ip4_config_from_named (NMNamedManager *mgr, NMIP4Config *config)
        g_return_val_if_fail (mgr != NULL, FALSE);
        g_return_val_if_fail (config != NULL, FALSE);
 
-       if (!(domain = get_domain_for_config (config, NULL)))
+       if (!(domain = get_domain_for_config (mgr, config, NULL)))
                return FALSE;
 
        return remove_one_zone_from_named (mgr, domain);
@@ -675,32 +710,40 @@ out:
 }
 
 gboolean
-nm_named_manager_add_ip4_config (NMNamedManager *mgr, NMIP4Config *config)
+nm_named_manager_add_ip4_config (NMNamedManager *mgr,
+                                 NMIP4Config *config,
+                                 NMNamedIPConfigType cfg_type)
 {
-       GError *        error = NULL;
+       NMNamedManagerPrivate *priv;
+       GError *error = NULL;
 
        g_return_val_if_fail (mgr != NULL, FALSE);
        g_return_val_if_fail (config != NULL, FALSE);
 
+       priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
+       switch (cfg_type) {
+       case NM_NAMED_IP_CONFIG_TYPE_VPN:
+               priv->vpn_config = config;
+               break;
+       case NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE:
+               priv->device_config = config;
+               break;
+       default:
+               break;
+       }
+
        /* Don't allow the same zone added twice */
-       if (g_slist_find (mgr->priv->configs, config))
-               return FALSE;
+       if (!g_slist_find (priv->configs, config))
+               priv->configs = g_slist_append (priv->configs, g_object_ref (config));
 
        /* First clear out and reload configs in named */
-       if (mgr->priv->use_named)
-       {
+       if (priv->use_named) {
                remove_all_zones_from_named (mgr);
                add_all_ip4_configs_to_named (mgr);
        }
 
-       mgr->priv->configs = g_slist_append (mgr->priv->configs, g_object_ref (config));
-
-       /* Activate the zone config */
-       if (mgr->priv->use_named)
-               add_ip4_config_to_named (mgr, config);
-
-       if (!rewrite_resolv_conf (mgr, config, &error))
-       {
+       if (!rewrite_resolv_conf (mgr, &error)) {
                nm_warning ("Could not commit DNS changes.  Error: '%s'", error ? error->message : "(none)");
                g_error_free (error);
        }
@@ -708,60 +751,45 @@ nm_named_manager_add_ip4_config (NMNamedManager *mgr, NMIP4Config *config)
        return TRUE;
 }
 
-static NMIP4Config *
-get_last_default_domain (NMNamedManager *mgr)
-{
-       GSList *elt = NULL;
-       NMIP4Config *last_default = NULL;
-       NMIP4Config *last = NULL;
-
-       for (elt = mgr->priv->configs; elt; elt = g_slist_next (elt))
-       {
-               gboolean dflt = FALSE;
-               const char *domain = NULL;
-               NMIP4Config *config = (NMIP4Config *)(elt->data);
-
-               last = config;
-               domain = get_domain_for_config (config, &dflt);
-               if (dflt)
-                       last_default = config;
-       }
-
-       /* Fall back the last config added to the list if none are the default */
-       return (last_default ? last_default : last);
-}
-
 gboolean
 nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config)
 {
-       GError *        error = NULL;
+       NMNamedManagerPrivate *priv;
+       GError *error = NULL;
 
        g_return_val_if_fail (mgr != NULL, FALSE);
        g_return_val_if_fail (config != NULL, FALSE);
 
+       priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
        /* Can't remove it if it wasn't in the list to begin with */
-       if (!g_slist_find (mgr->priv->configs, config))
+       if (!g_slist_find (priv->configs, config))
                return FALSE;
 
        /* Deactivate the config */
-       if (mgr->priv->use_named)
+       if (priv->use_named)
                remove_ip4_config_from_named (mgr, config);
 
-       mgr->priv->configs = g_slist_remove (mgr->priv->configs, config);
+       priv->configs = g_slist_remove (priv->configs, config);
+
+       if (config == priv->vpn_config)
+               priv->vpn_config = NULL;
+
+       if (config == priv->device_config)
+               priv->device_config = NULL;
+
        g_object_unref (config);        
 
        /* Clear out and reload configs since we may need a new
         * default zone if the one we are removing was the old
         * default zone.
         */
-       if (mgr->priv->use_named)
-       {
+       if (mgr->priv->use_named) {
                remove_all_zones_from_named (mgr);
                add_all_ip4_configs_to_named (mgr);
        }
 
-       if (!rewrite_resolv_conf (mgr, get_last_default_domain (mgr), &error))
-       {
+       if (!rewrite_resolv_conf (mgr, &error)) {
                nm_warning ("Could not commit DNS changes.  Error: '%s'", error ? error->message : "(none)");
                if (error)
                        g_error_free (error);
index 431cd36..b610722 100644 (file)
 #include <dbus/dbus.h>
 #include "nm-ip4-config.h"
 
-typedef enum
-{
+typedef enum {
        NM_NAMED_MANAGER_ERROR_SYSTEM,
        NM_NAMED_MANAGER_ERROR_INVALID_NAMESERVER,
        NM_NAMED_MANAGER_ERROR_INVALID_HOST,
        NM_NAMED_MANAGER_ERROR_INVALID_ID
 } NMNamedManagerError;
 
+typedef enum {
+       NM_NAMED_IP_CONFIG_TYPE_DEFAULT = 0,
+       NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE,
+       NM_NAMED_IP_CONFIG_TYPE_VPN
+} NMNamedIPConfigType;
+
 #define NM_NAMED_MANAGER_ERROR nm_named_manager_error_quark ()
 GQuark nm_named_manager_error_quark (void);
 
@@ -64,7 +69,9 @@ GType nm_named_manager_get_type (void);
 
 NMNamedManager * nm_named_manager_get (void);
 
-gboolean nm_named_manager_add_ip4_config (NMNamedManager *mgr, NMIP4Config *config);
+gboolean nm_named_manager_add_ip4_config (NMNamedManager *mgr,
+                                          NMIP4Config *config,
+                                          NMNamedIPConfigType cfg_type);
 
 gboolean nm_named_manager_remove_ip4_config (NMNamedManager *mgr, NMIP4Config *config);
 
index 52bba03..7115ef7 100644 (file)
@@ -856,10 +856,19 @@ real_check_connection_conflicts (NMDevice *device,
        return FALSE;
 }
 
+static gboolean
+real_can_activate (NMDevice *dev, gboolean wireless_enabled)
+{
+       if (!wireless_enabled)
+               return FALSE;
+
+       return TRUE;
+}
+
 static NMConnection *
-real_get_best_connection (NMDevice *dev,
-                          GSList *connections,
-                          char **specific_object)
+real_get_best_auto_connection (NMDevice *dev,
+                               GSList *connections,
+                               char **specific_object)
 {
        NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (dev);
        NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
@@ -2756,31 +2765,40 @@ static NMActStageReturn
 real_act_stage4_get_ip4_config (NMDevice *dev,
                                 NMIP4Config **config)
 {
-       NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev);
-       NMAccessPoint *         ap = nm_device_802_11_wireless_get_activation_ap (self);
-       NMActStageReturn                ret = NM_ACT_STAGE_RETURN_FAILURE;
-       NMIP4Config *                   real_config = NULL;
+       NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (dev);
+       NMAccessPoint *ap = nm_device_802_11_wireless_get_activation_ap (self);
+       NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
 
        g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
        g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
        g_assert (ap);
-       if (nm_ap_get_user_created (ap))
-       {
-               real_config = nm_device_new_ip4_autoip_config (NM_DEVICE (self));
+       if (nm_ap_get_user_created (ap)) {
+               *config = nm_device_new_ip4_autoip_config (NM_DEVICE (self));
                ret = NM_ACT_STAGE_RETURN_SUCCESS;
-       }
-       else
-       {
+       } else {
                NMDevice80211WirelessClass *    klass;
                NMDeviceClass * parent_class;
 
                /* Chain up to parent */
                klass = NM_DEVICE_802_11_WIRELESS_GET_CLASS (self);
                parent_class = NM_DEVICE_CLASS (g_type_class_peek_parent (klass));
-               ret = parent_class->act_stage4_get_ip4_config (dev, &real_config);
+               ret = parent_class->act_stage4_get_ip4_config (dev, config);
+       }
+
+       if ((ret == NM_ACT_STAGE_RETURN_SUCCESS) && *config) {
+               NMConnection *connection;
+               NMSettingWireless *s_wireless;
+
+               connection = nm_act_request_get_connection (nm_device_get_act_request (dev));
+               g_assert (connection);
+               s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
+               g_assert (s_wireless);
+
+               /* MTU override */
+               if (s_wireless->mtu)
+                       nm_ip4_config_set_mtu (*config, s_wireless->mtu);
        }
-       *config = real_config;
 
        return ret;
 }
@@ -3065,7 +3083,8 @@ nm_device_802_11_wireless_class_init (NMDevice80211WirelessClass *klass)
        parent_class->bring_down = real_bring_down;
        parent_class->update_link = real_update_link;
        parent_class->set_hw_address = real_set_hw_address;
-       parent_class->get_best_connection = real_get_best_connection;
+       parent_class->get_best_auto_connection = real_get_best_auto_connection;
+       parent_class->can_activate = real_can_activate;
        parent_class->connection_secrets_updated = real_connection_secrets_updated;
        parent_class->check_connection_conflicts = real_check_connection_conflicts;
 
index 481395b..76a3126 100644 (file)
@@ -349,10 +349,20 @@ real_can_interrupt_activation (NMDevice *dev)
        return interrupt;
 }
 
+static gboolean
+real_can_activate (NMDevice *dev, gboolean wireless_enabled)
+{
+       /* Can't do anything if there isn't a carrier */
+       if (!nm_device_get_carrier (dev))
+               return FALSE;
+
+       return TRUE;
+}
+
 static NMConnection *
-real_get_best_connection (NMDevice *dev,
-                          GSList *connections,
-                          char **specific_object)
+real_get_best_auto_connection (NMDevice *dev,
+                               GSList *connections,
+                               char **specific_object)
 {
        NMDevice8023Ethernet *self = NM_DEVICE_802_3_ETHERNET (dev);
        NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (self);
@@ -385,6 +395,40 @@ real_get_best_connection (NMDevice *dev,
        return NULL;
 }
 
+static NMActStageReturn
+real_act_stage4_get_ip4_config (NMDevice *dev,
+                                NMIP4Config **config)
+{
+       NMDevice8023Ethernet *self = NM_DEVICE_802_3_ETHERNET (dev);
+       NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
+       NMDevice8023EthernetClass *klass;
+       NMDeviceClass *parent_class;
+
+       g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+       g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+       /* Chain up to parent */
+       klass = NM_DEVICE_802_3_ETHERNET_GET_CLASS (self);
+       parent_class = NM_DEVICE_CLASS (g_type_class_peek_parent (klass));
+       ret = parent_class->act_stage4_get_ip4_config (dev, config);
+
+       if ((ret == NM_ACT_STAGE_RETURN_SUCCESS) && *config) {
+               NMConnection *connection;
+               NMSettingWired *s_wired;
+
+               connection = nm_act_request_get_connection (nm_device_get_act_request (dev));
+               g_assert (connection);
+               s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
+               g_assert (s_wired);
+
+               /* MTU override */
+               if (s_wired->mtu)
+                       nm_ip4_config_set_mtu (*config, s_wired->mtu);
+       }
+
+       return ret;
+}
+
 static void
 nm_device_802_3_ethernet_dispose (GObject *object)
 {
@@ -468,7 +512,9 @@ nm_device_802_3_ethernet_class_init (NMDevice8023EthernetClass *klass)
        parent_class->update_link = real_update_link;
        parent_class->can_interrupt_activation = real_can_interrupt_activation;
        parent_class->set_hw_address = real_set_hw_address;
-       parent_class->get_best_connection = real_get_best_connection;
+       parent_class->get_best_auto_connection = real_get_best_auto_connection;
+       parent_class->can_activate = real_can_activate;
+       parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
 
        /* properties */
        g_object_class_install_property
index 1f3ece5..87ac1e3 100644 (file)
@@ -248,7 +248,7 @@ nm_device_get_iface (NMDevice *self)
 }
 
 
-static const char *
+const char *
 nm_device_get_ip_iface (NMDevice *self)
 {
        g_return_val_if_fail (self != NULL, NULL);
@@ -373,10 +373,19 @@ nm_device_set_carrier (NMDevice *self,
 }
 
 
+gboolean
+nm_device_can_activate (NMDevice *self, gboolean wireless_enabled)
+{
+       if (!NM_DEVICE_GET_CLASS (self)->can_activate)
+                       return TRUE;
+
+       return NM_DEVICE_GET_CLASS (self)->can_activate (self, wireless_enabled);
+}
+
 NMConnection *
-nm_device_get_best_connection (NMDevice *dev,
-                              GSList *connections,
-                               char **specific_object)
+nm_device_get_best_auto_connection (NMDevice *dev,
+                                    GSList *connections,
+                                    char **specific_object)
 {
        guint32 caps;
 
@@ -389,10 +398,10 @@ nm_device_get_best_connection (NMDevice *dev,
        if (!(caps & NM_DEVICE_CAP_NM_SUPPORTED))
                return NULL;
 
-       if (!NM_DEVICE_GET_CLASS (dev)->get_best_connection)
+       if (!NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection)
                return NULL;
 
-       return NM_DEVICE_GET_CLASS (dev)->get_best_connection (dev, connections, specific_object);
+       return NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection (dev, connections, specific_object);
 }
 
 /*
@@ -709,34 +718,25 @@ static NMActStageReturn
 real_act_stage4_get_ip4_config (NMDevice *self,
                                 NMIP4Config **config)
 {
-       NMIP4Config *           real_config = NULL;
-       NMActStageReturn        ret = NM_ACT_STAGE_RETURN_FAILURE;
+       NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
+       NMConnection *connection;
 
        g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
        g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-       if (nm_device_get_use_dhcp (self)) {
-               real_config = nm_dhcp_manager_get_ip4_config (NM_DEVICE_GET_PRIVATE (self)->dhcp_manager,
-                                                                                        nm_device_get_iface (self));
+       connection = nm_act_request_get_connection (nm_device_get_act_request (self));
 
-               if (real_config && nm_ip4_config_get_mtu (real_config) == 0) {
-                       /* If the DHCP server doesn't set the MTU, get it from backend. */
-                       // FIXME: let the NMConnection override the MTU
-                       nm_ip4_config_set_mtu (real_config, nm_system_get_mtu (self));
-               }
-       } else {
-               real_config = nm_ip4_config_new ();
-       }
-
-       if (real_config) {
-               NMActRequest *req;
+       if (nm_device_get_use_dhcp (self))
+               *config = nm_dhcp_manager_get_ip4_config (NM_DEVICE_GET_PRIVATE (self)->dhcp_manager,
+                                                                                        nm_device_get_iface (self));
+       else
+               *config = nm_ip4_config_new ();
 
-               req = nm_device_get_act_request (self);
-               merge_ip4_config (real_config, 
-                                          (NMSettingIP4Config *) nm_connection_get_setting (nm_act_request_get_connection (req),
-                                                                                                                          NM_TYPE_SETTING_IP4_CONFIG));
+       if (*config) {
+               NMSettingIP4Config *s_ip4;
 
-               *config = real_config;
+               s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
+               merge_ip4_config (*config, s_ip4);
                ret = NM_ACT_STAGE_RETURN_SUCCESS;
        } else {
                /* Make sure device is up even if config fails */
@@ -1397,7 +1397,6 @@ nm_device_set_ip4_config (NMDevice *self, NMIP4Config *config)
                nm_device_update_ip4_address (self);
                nm_system_device_add_ip6_link_address (self);
                nm_system_set_hostname (config);
-               nm_system_set_mtu (self);
                nm_system_activate_nis (config);
        }
 
index 38a7f00..6bd8e25 100644 (file)
@@ -90,9 +90,11 @@ struct _NMDeviceClass
        guint32         (* get_type_capabilities)       (NMDevice *self);
        guint32         (* get_generic_capabilities)    (NMDevice *self);
 
-       NMConnection * (* get_best_connection) (NMDevice *self,
-                                               GSList *connections,
-                                               char **specific_object);
+       gboolean        (* can_activate) (NMDevice *self, gboolean wireless_enabled);
+
+       NMConnection * (* get_best_auto_connection) (NMDevice *self,
+                                                    GSList *connections,
+                                                    char **specific_object);
 
        void        (* connection_secrets_updated) (NMDevice *self,
                                                    NMConnection *connection,
@@ -122,6 +124,7 @@ GType nm_device_get_type (void);
 
 const char *   nm_device_get_udi               (NMDevice *dev);
 const char *   nm_device_get_iface             (NMDevice *dev);
+const char *   nm_device_get_ip_iface  (NMDevice *dev);
 const char *   nm_device_get_driver    (NMDevice *dev);
 
 NMDeviceType   nm_device_get_device_type       (NMDevice *dev);
@@ -152,9 +155,11 @@ void *             nm_device_get_system_config_data        (NMDevice *dev);
 
 NMActRequest * nm_device_get_act_request       (NMDevice *dev);
 
-NMConnection * nm_device_get_best_connection (NMDevice *dev,
-                                             GSList *connections,
-                                              char **specific_object);
+gboolean               nm_device_can_activate  (NMDevice *dev, gboolean wireless_enabled);
+
+NMConnection * nm_device_get_best_auto_connection (NMDevice *dev,
+                                                   GSList *connections,
+                                                   char **specific_object);
 
 void                   nm_device_activate_schedule_stage1_device_prepare               (NMDevice *device);
 void                   nm_device_activate_schedule_stage2_device_config                (NMDevice *device);
index f76ee1d..6fb7058 100644 (file)
@@ -56,12 +56,6 @@ typedef struct {
        gchar * nis_domain;
        GArray *nis_servers;
        GArray *static_routes;
-
-       /* If this is a VPN/etc config that requires
-        * another device (like Ethernet) to already have
-        * an IP4Config before it can be used.
-        */
-       gboolean        secondary;
 } NMIP4ConfigPrivate;
 
 
@@ -144,20 +138,6 @@ NMIP4Config *nm_ip4_config_copy (NMIP4Config *src_config)
        return dst_config;
 }
 
-gboolean nm_ip4_config_get_secondary (NMIP4Config *config)
-{
-       g_return_val_if_fail (NM_IS_IP4_CONFIG (config), FALSE);
-
-       return NM_IP4_CONFIG_GET_PRIVATE (config)->secondary;
-}
-
-void nm_ip4_config_set_secondary (NMIP4Config *config, gboolean secondary)
-{
-       g_return_if_fail (NM_IS_IP4_CONFIG (config));
-
-       NM_IP4_CONFIG_GET_PRIVATE (config)->secondary = secondary;
-}
-
 guint32 nm_ip4_config_get_address (NMIP4Config *config)
 {
        g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
index 2492c0c..4528968 100644 (file)
@@ -59,9 +59,6 @@ GType nm_ip4_config_get_type (void);
 NMIP4Config *  nm_ip4_config_new                               (void);
 NMIP4Config *  nm_ip4_config_copy                              (NMIP4Config *config);
 
-gboolean               nm_ip4_config_get_secondary             (NMIP4Config *config);
-void                   nm_ip4_config_set_secondary             (NMIP4Config *config, gboolean secondary);
-
 guint32                nm_ip4_config_get_address               (NMIP4Config *config);
 void                   nm_ip4_config_set_address               (NMIP4Config *config, guint32 addr);
 
index 45457be..e22f973 100644 (file)
@@ -1262,6 +1262,9 @@ nm_manager_activate_device (NMManager *manager,
        if (!check_connection_allowed (manager, dev_iface, connection, specific_object, error))
                return FALSE;
 
+       if (nm_device_get_act_request (device))
+               nm_device_interface_deactivate (dev_iface);
+
        req = nm_act_request_new (connection, specific_object, user_requested);
        success = nm_device_interface_activate (dev_iface, req, error);
        g_object_unref (req);
@@ -1307,39 +1310,6 @@ wait_for_connection_expired (gpointer data)
        return FALSE;
 }
 
-/* ICK ICK ICK; should go away with multiple device support.  There is
- * corresponding code in NetworkManagerPolicy.c that handles this for
- * automatically activated connections.
- */
-static void
-deactivate_old_device (NMManager *manager)
-{
-       NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
-       NMDevice *device = NULL;
-       GSList *iter;
-
-       switch (priv->state) {
-       case NM_STATE_CONNECTED:
-               device = nm_manager_get_active_device (manager);
-               break;
-       case NM_STATE_CONNECTING:
-               for (iter = nm_manager_get_devices (manager); iter; iter = iter->next) {
-                       NMDevice *d = NM_DEVICE (iter->data);
-
-                       if (nm_device_is_activating (d)) {
-                               device = d;
-                               break;
-                       }
-               }
-               break;
-       default:
-               break;
-       }
-
-       if (device)
-               nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device));
-}
-
 static void
 connection_added_default_handler (NMManager *manager,
                                                    NMConnection *connection,
@@ -1362,9 +1332,6 @@ connection_added_default_handler (NMManager *manager,
        /* Will destroy below; can't be valid during the initial activation start */
        priv->pending_connection_info = NULL;
 
-       // FIXME: remove old_dev deactivation when multiple device support lands
-       deactivate_old_device (manager);
-
        success = nm_manager_activate_device (manager,
                                              info->device,
                                              connection,
@@ -1428,9 +1395,6 @@ impl_manager_activate_device (NMManager *manager,
        if (connection) {
                gboolean success;
 
-               // FIXME: remove old_dev deactivation when multiple device support lands
-               deactivate_old_device (manager);
-
                success = nm_manager_activate_device (manager,
                                                      device,
                                                      connection,
index 66b97a1..ed3ce15 100644 (file)
@@ -243,7 +243,6 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
        priv->ipconfig_timeout = 0;
 
        config = nm_ip4_config_new ();
-       nm_ip4_config_set_secondary (config, TRUE);
 
        val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY);
        if (val)