diff options
author | Dan Williams <dcbw@redhat.com> | 2008-03-07 19:41:32 +0000 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2008-03-07 19:41:32 +0000 |
commit | 3fec4814144c036d8560c1c332ffb137bd0f5dfc (patch) | |
tree | 3c551652128a36f637cf4ba4a3659d8b330b245f /src | |
parent | d84a51a145028901f7fc7dfe73bbe30bcfd1b0ae (diff) | |
download | NetworkManager-3fec4814144c036d8560c1c332ffb137bd0f5dfc.tar.gz |
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
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3391 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
Diffstat (limited to 'src')
-rw-r--r-- | src/NetworkManagerPolicy.c | 627 | ||||
-rw-r--r-- | src/NetworkManagerSystem.c | 103 | ||||
-rw-r--r-- | src/NetworkManagerSystem.h | 8 | ||||
-rw-r--r-- | src/backends/NetworkManagerArch.c | 32 | ||||
-rw-r--r-- | src/backends/NetworkManagerDebian.c | 32 | ||||
-rw-r--r-- | src/backends/NetworkManagerFrugalware.c | 41 | ||||
-rw-r--r-- | src/backends/NetworkManagerGeneric.c | 48 | ||||
-rw-r--r-- | src/backends/NetworkManagerGeneric.h | 6 | ||||
-rw-r--r-- | src/backends/NetworkManagerGentoo.c | 31 | ||||
-rw-r--r-- | src/backends/NetworkManagerPaldo.c | 31 | ||||
-rw-r--r-- | src/backends/NetworkManagerRedHat.c | 32 | ||||
-rw-r--r-- | src/backends/NetworkManagerSlackware.c | 31 | ||||
-rw-r--r-- | src/backends/NetworkManagerSuSE.c | 38 | ||||
-rw-r--r-- | src/named-manager/nm-named-manager.c | 324 | ||||
-rw-r--r-- | src/named-manager/nm-named-manager.h | 13 | ||||
-rw-r--r-- | src/nm-device-802-11-wireless.c | 51 | ||||
-rw-r--r-- | src/nm-device-802-3-ethernet.c | 54 | ||||
-rw-r--r-- | src/nm-device.c | 55 | ||||
-rw-r--r-- | src/nm-device.h | 17 | ||||
-rw-r--r-- | src/nm-ip4-config.c | 20 | ||||
-rw-r--r-- | src/nm-ip4-config.h | 3 | ||||
-rw-r--r-- | src/nm-manager.c | 42 | ||||
-rw-r--r-- | src/vpn-manager/nm-vpn-connection.c | 1 |
23 files changed, 678 insertions, 962 deletions
diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index b1e3eda99c..5d72fec606 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -35,22 +35,28 @@ #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); } diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index faec48e22d..603cd73ade 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -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; } + + diff --git a/src/NetworkManagerSystem.h b/src/NetworkManagerSystem.h index 5db80adcdc..aa21795160 100644 --- a/src/NetworkManagerSystem.h +++ b/src/NetworkManagerSystem.h @@ -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); diff --git a/src/backends/NetworkManagerArch.c b/src/backends/NetworkManagerArch.c index 373335ea58..e8550f59df 100644 --- a/src/backends/NetworkManagerArch.c +++ b/src/backends/NetworkManagerArch.c @@ -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; - -} diff --git a/src/backends/NetworkManagerDebian.c b/src/backends/NetworkManagerDebian.c index 6be15f91b5..a9acbe8cfe 100644 --- a/src/backends/NetworkManagerDebian.c +++ b/src/backends/NetworkManagerDebian.c @@ -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; -} diff --git a/src/backends/NetworkManagerFrugalware.c b/src/backends/NetworkManagerFrugalware.c index d1cc6fb8e0..78d245690a 100644 --- a/src/backends/NetworkManagerFrugalware.c +++ b/src/backends/NetworkManagerFrugalware.c @@ -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. diff --git a/src/backends/NetworkManagerGeneric.c b/src/backends/NetworkManagerGeneric.c index adc57acd9e..50dd60f038 100644 --- a/src/backends/NetworkManagerGeneric.c +++ b/src/backends/NetworkManagerGeneric.c @@ -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; -} diff --git a/src/backends/NetworkManagerGeneric.h b/src/backends/NetworkManagerGeneric.h index 962944311c..f69b08c673 100644 --- a/src/backends/NetworkManagerGeneric.h +++ b/src/backends/NetworkManagerGeneric.h @@ -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 diff --git a/src/backends/NetworkManagerGentoo.c b/src/backends/NetworkManagerGentoo.c index c7469a294e..944bb8c575 100644 --- a/src/backends/NetworkManagerGentoo.c +++ b/src/backends/NetworkManagerGentoo.c @@ -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; -} + diff --git a/src/backends/NetworkManagerPaldo.c b/src/backends/NetworkManagerPaldo.c index cb96b7e37c..9e457df449 100644 --- a/src/backends/NetworkManagerPaldo.c +++ b/src/backends/NetworkManagerPaldo.c @@ -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; -} diff --git a/src/backends/NetworkManagerRedHat.c b/src/backends/NetworkManagerRedHat.c index 5f653f79c7..7e3ce249da 100644 --- a/src/backends/NetworkManagerRedHat.c +++ b/src/backends/NetworkManagerRedHat.c @@ -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; -} diff --git a/src/backends/NetworkManagerSlackware.c b/src/backends/NetworkManagerSlackware.c index ba6b67e9d7..599534d6f4 100644 --- a/src/backends/NetworkManagerSlackware.c +++ b/src/backends/NetworkManagerSlackware.c @@ -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; -} diff --git a/src/backends/NetworkManagerSuSE.c b/src/backends/NetworkManagerSuSE.c index e5afd61ac5..eeefb66c7c 100644 --- a/src/backends/NetworkManagerSuSE.c +++ b/src/backends/NetworkManagerSuSE.c @@ -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; -} diff --git a/src/named-manager/nm-named-manager.c b/src/named-manager/nm-named-manager.c index 2dfc0a981f..e6cf1b4567 100644 --- a/src/named-manager/nm-named-manager.c +++ b/src/named-manager/nm-named-manager.c @@ -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); diff --git a/src/named-manager/nm-named-manager.h b/src/named-manager/nm-named-manager.h index 431cd36bb6..b610722d06 100644 --- a/src/named-manager/nm-named-manager.h +++ b/src/named-manager/nm-named-manager.h @@ -28,14 +28,19 @@ #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); diff --git a/src/nm-device-802-11-wireless.c b/src/nm-device-802-11-wireless.c index 52bba030cc..7115ef7e55 100644 --- a/src/nm-device-802-11-wireless.c +++ b/src/nm-device-802-11-wireless.c @@ -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; diff --git a/src/nm-device-802-3-ethernet.c b/src/nm-device-802-3-ethernet.c index 481395b672..76a3126139 100644 --- a/src/nm-device-802-3-ethernet.c +++ b/src/nm-device-802-3-ethernet.c @@ -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 diff --git a/src/nm-device.c b/src/nm-device.c index 1f3ece5ec0..87ac1e3d24 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -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); } diff --git a/src/nm-device.h b/src/nm-device.h index 38a7f005a8..6bd8e250f2 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -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); diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index f76ee1dc99..6fb7058162 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -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); diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 2492c0cf00..4528968e79 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -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); diff --git a/src/nm-manager.c b/src/nm-manager.c index 45457beb90..e22f973bb7 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -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, diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 66b97a1a47..ed3ce159d9 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -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) |