From bdd556fe4d7905f0807f9cde5eb9e3b1603f46b9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 9 Oct 2011 22:50:04 -0500 Subject: [PATCH] core: kill stage4 (IP Config Get) It was somewhat pointless since the IP config is always known when stage4 gets scheduled, so why not just pass the config to stage5 immediately? Also helps consolidate the v4/v6 failure handling logic and makes the operational flow clearer where both v4 and v6 are active and proceeding in parallel. --- src/modem-manager/nm-modem.c | 144 +---- src/modem-manager/nm-modem.h | 6 - src/nm-device-bt.c | 29 +- src/nm-device-ethernet.c | 88 +-- src/nm-device-modem.c | 19 +- src/nm-device-wifi.c | 44 +- src/nm-device.c | 1049 ++++++++++++++-------------------- src/nm-device.h | 26 +- 8 files changed, 514 insertions(+), 891 deletions(-) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index debfbdf7d7..65b9f98676 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -55,7 +55,6 @@ typedef struct { char *path; NMPPPManager *ppp_manager; - NMIP4Config *pending_ip4_config; guint32 ip_method; char *device; char *iface; @@ -129,21 +128,6 @@ nm_modem_get_proxy (NMModem *self, return priv->proxy; } -static void -merge_ip4_config (NMActRequest *req, NMIP4Config *config) -{ - NMConnection *connection; - NMSettingIP4Config *s_ip4; - - /* Merge user-defined overrides into the IP4Config to be applied */ - connection = nm_act_request_get_connection (req); - g_assert (connection); - - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - if (s_ip4) - nm_utils_merge_ip4_config (config, s_ip4); -} - /*****************************************************************************/ /* IP method PPP */ @@ -169,7 +153,6 @@ ppp_ip4_config (NMPPPManager *ppp_manager, gpointer user_data) { NMModem *self = NM_MODEM (user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); guint32 i, num; guint32 bad_dns1 = htonl (0x0A0B0C0D); guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */ @@ -213,7 +196,6 @@ ppp_ip4_config (NMPPPManager *ppp_manager, nm_ip4_config_add_nameserver (config, good_dns2); } - priv->pending_ip4_config = g_object_ref (config); g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, iface, config, NULL); } @@ -287,22 +269,6 @@ ppp_stage3_ip4_config_start (NMModem *self, return ret; } -static NMActStageReturn -ppp_stage4 (NMModem *self, - NMActRequest *req, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - - merge_ip4_config (req, *config); - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ /* IP method static */ @@ -336,9 +302,6 @@ static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) nm_ip4_config_add_nameserver (config, g_value_get_uint (value)); } g_value_array_free (ret_array); - - priv->pending_ip4_config = g_object_ref (config); - g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, NULL); } g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, error); @@ -368,32 +331,6 @@ static_stage3_ip4_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_POSTPONE; } -static NMActStageReturn -static_stage4 (NMModem *self, - NMActRequest *req, - NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - gboolean no_firmware = FALSE; - - if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) { - if (no_firmware) - *reason = NM_DEVICE_STATE_REASON_FIRMWARE_MISSING; - else - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - - merge_ip4_config (req, *config); - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ NMActStageReturn @@ -426,49 +363,7 @@ nm_modem_stage3_ip4_config_start (NMModem *self, ret = static_stage3_ip4_config_start (self, req, reason); break; case MM_MODEM_IP_METHOD_DHCP: - ret = device_class->act_stage3_ip4_config_start (device, reason); - break; - default: - nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); - ret = NM_ACT_STAGE_RETURN_FAILURE; - break; - } - - return ret; -} - -NMActStageReturn -nm_modem_stage4_get_ip4_config (NMModem *self, - NMDevice *device, - NMDeviceClass *device_class, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMModemPrivate *priv; - NMActRequest *req; - NMActStageReturn ret; - - g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - req = nm_device_get_act_request (device); - g_assert (req); - - priv = NM_MODEM_GET_PRIVATE (self); - switch (priv->ip_method) { - case MM_MODEM_IP_METHOD_PPP: - ret = ppp_stage4 (self, req, config, reason); - break; - case MM_MODEM_IP_METHOD_STATIC: - ret = static_stage4 (self, req, device, config, reason); - break; - case MM_MODEM_IP_METHOD_DHCP: - ret = device_class->act_stage4_get_ip4_config (device, config, reason); + ret = device_class->act_stage3_ip4_config_start (device, NULL, reason); break; default: nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); @@ -662,11 +557,6 @@ real_deactivate (NMModem *self, NMDevice *device) priv->call = NULL; } - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - priv->in_bytes = priv->out_bytes = 0; if (priv->ppp_manager) { @@ -758,44 +648,20 @@ nm_modem_device_state_changed (NMModem *self, } } -static gboolean -_state_is_active (NMDeviceState state) -{ - return (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_DEACTIVATING); -} - gboolean nm_modem_hw_is_up (NMModem *self, NMDevice *device) { - guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method; + int ifindex = nm_device_get_ip_ifindex (device); - if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - NMDeviceState state; - - state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); - if (priv->pending_ip4_config || _state_is_active (state)) - return nm_system_iface_is_up (nm_device_get_ip_ifindex (device)); - } - - return TRUE; + return ifindex > 0 ? nm_system_iface_is_up (ifindex) : TRUE; } gboolean nm_modem_hw_bring_up (NMModem *self, NMDevice *device, gboolean *no_firmware) { - guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method; + int ifindex = nm_device_get_ip_ifindex (device); - if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - NMDeviceState state; - - state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); - if (priv->pending_ip4_config || _state_is_active (state)) - return nm_system_iface_set_up (nm_device_get_ip_ifindex (device), TRUE, no_firmware); - } - - return TRUE; + return ifindex > 0 ? nm_system_iface_set_up (ifindex, TRUE, no_firmware) : TRUE; } const char * diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index bad19b043f..1afb4e7546 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -129,12 +129,6 @@ NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem, NMDeviceClass *device_class, NMDeviceStateReason *reason); -NMActStageReturn nm_modem_stage4_get_ip4_config (NMModem *modem, - NMDevice *device, - NMDeviceClass *device_class, - NMIP4Config **config, - NMDeviceStateReason *reason); - gboolean nm_modem_get_secrets (NMModem *modem, const char *setting_name, gboolean request_new, diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c index c36e0c0ba6..9765bc9ba4 100644 --- a/src/nm-device-bt.c +++ b/src/nm-device-bt.c @@ -543,7 +543,7 @@ modem_ip4_config_result (NMModem *self, if (iface) nm_device_set_ip_iface (device, iface); - nm_device_activate_schedule_stage4_ip4_config_get (device); + nm_device_activate_schedule_ip4_config_result (device, config); } } @@ -920,7 +920,9 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) } static NMActStageReturn -real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +real_act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMActStageReturn ret; @@ -931,27 +933,7 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) NM_DEVICE_CLASS (nm_device_bt_parent_class), reason); } else - ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, reason); - - return ret; -} - -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMActStageReturn ret; - - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - ret = nm_modem_stage4_get_ip4_config (NM_DEVICE_BT_GET_PRIVATE (device)->modem, - device, - NM_DEVICE_CLASS (nm_device_bt_parent_class), - config, - reason); - } else - ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage4_get_ip4_config (device, config, reason); + ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); return ret; } @@ -1148,7 +1130,6 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) device_class->deactivate = real_deactivate; device_class->act_stage2_config = real_act_stage2_config; device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; - device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; device_class->check_connection_compatible = real_check_connection_compatible; device_class->complete_connection = real_complete_connection; diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 8556c5bd5c..96a81b707a 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -1434,19 +1434,17 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ static void ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) + const char *iface, + NMIP4Config *config, + gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG) - return; - - nm_device_set_ip_iface (device, iface); - NM_DEVICE_ETHERNET_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); - nm_device_activate_schedule_stage4_ip4_config_get (device); + if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { + nm_device_set_ip_iface (device, iface); + nm_device_activate_schedule_ip4_config_result (device, config); + } } static NMActStageReturn @@ -1519,7 +1517,9 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) } static NMActStageReturn -real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +real_act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) { NMSettingConnection *s_con; const char *connection_type; @@ -1533,61 +1533,29 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) return pppoe_stage3_ip4_config_start (NM_DEVICE_ETHERNET (device), reason); - return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, reason); + return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, out_config, reason); } -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) +static void +real_ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) { - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMActStageReturn ret; + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; - 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_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + /* MTU only set for plain ethernet */ + if (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->ppp_manager) + return; - if (!priv->ppp_manager) { - /* Regular ethernet connection. */ + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + g_assert (connection); + s_wired = nm_connection_get_setting_wired (connection); + g_assert (s_wired); - /* Chain up to parent */ - ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage4_get_ip4_config (device, config, reason); - - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - NMConnection *connection; - NMSettingWired *s_wired; - guint32 mtu; - - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED)); - g_assert (s_wired); - - /* MTU override */ - mtu = nm_setting_wired_get_mtu (s_wired); - if (mtu) - nm_ip4_config_set_mtu (*config, mtu); - } - } else { - NMConnection *connection; - NMSettingIP4Config *s_ip4; - - /* PPPoE */ - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - - /* Merge user-defined overrides into the IP4Config to be applied */ - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - nm_utils_merge_ip4_config (*config, s_ip4); - - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } - - return ret; + /* MTU override */ + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu); } static void @@ -2011,7 +1979,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->act_stage1_prepare = real_act_stage1_prepare; parent_class->act_stage2_config = real_act_stage2_config; parent_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; - parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; + parent_class->ip4_config_pre_commit = real_ip4_config_pre_commit; parent_class->deactivate = real_deactivate; parent_class->spec_match_list = spec_match_list; parent_class->connection_match_config = connection_match_config; diff --git a/src/nm-device-modem.c b/src/nm-device-modem.c index 076bfa49ba..d54e20dc63 100644 --- a/src/nm-device-modem.c +++ b/src/nm-device-modem.c @@ -155,7 +155,7 @@ modem_ip4_config_result (NMModem *self, if (iface) nm_device_set_ip_iface (device, iface); - nm_device_activate_schedule_stage4_ip4_config_get (device); + nm_device_activate_schedule_ip4_config_result (device, config); } } @@ -275,7 +275,9 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) } static NMActStageReturn -real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +real_act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) { return nm_modem_stage3_ip4_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, @@ -283,18 +285,6 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) reason); } -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - return nm_modem_stage4_get_ip4_config (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, - device, - NM_DEVICE_CLASS (nm_device_modem_parent_class), - config, - reason); -} - /*****************************************************************************/ static gboolean @@ -469,7 +459,6 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass) device_class->act_stage1_prepare = real_act_stage1_prepare; device_class->act_stage2_config = real_act_stage2_config; device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; - device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; /* Properties */ g_object_class_install_property diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 4f6295b88d..a2230f3da9 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -2684,38 +2684,22 @@ out: return ret; } -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *dev, - NMIP4Config **config, - NMDeviceStateReason *reason) +static void +real_ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) { - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMDeviceClass *parent_class; + NMConnection *connection; + NMSettingWireless *s_wifi; + guint32 mtu; - g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + g_assert (connection); + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); - /* Chain up to parent */ - parent_class = NM_DEVICE_CLASS (nm_device_wifi_parent_class); - ret = parent_class->act_stage4_get_ip4_config (dev, config, reason); - - if ((ret == NM_ACT_STAGE_RETURN_SUCCESS) && *config) { - NMConnection *connection; - NMSettingWireless *s_wireless; - guint32 mtu; - - 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 */ - mtu = nm_setting_wireless_get_mtu (s_wireless); - if (mtu) - nm_ip4_config_set_mtu (*config, mtu); - } - - return ret; + /* MTU override */ + mtu = nm_setting_wireless_get_mtu (s_wifi); + if (mtu) + nm_ip4_config_set_mtu (config, mtu); } static gboolean @@ -3290,7 +3274,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->act_stage1_prepare = real_act_stage1_prepare; parent_class->act_stage2_config = real_act_stage2_config; - parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; + parent_class->ip4_config_pre_commit = real_ip4_config_pre_commit; parent_class->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout; parent_class->act_stage4_ip6_config_timeout = real_act_stage4_ip6_config_timeout; parent_class->deactivate = real_deactivate; diff --git a/src/nm-device.c b/src/nm-device.c index 7188e64779..87bd051916 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -58,8 +58,8 @@ #include "nm-marshal.h" #include "nm-rfkill.h" -#define NM_ACT_REQUEST_IP4_CONFIG "nm-act-request-ip4-config" -#define NM_ACT_REQUEST_IP6_CONFIG "nm-act-request-ip6-config" +#define PENDING_IP4_CONFIG "pending-ip4-config" +#define PENDING_IP6_CONFIG "pending-ip6-config" static void device_interface_init (NMDeviceInterface *device_interface_class); @@ -107,8 +107,8 @@ typedef struct { gulong secrets_updated_id; gulong secrets_failed_id; - gboolean ip4_ready; - gboolean ip6_ready; + gboolean ip4_done; + gboolean ip6_done; /* Generic DHCP stuff */ NMDHCPManager * dhcp_manager; @@ -130,7 +130,6 @@ typedef struct { GPid aipd_pid; guint aipd_watch; guint aipd_timeout; - guint32 aipd_addr; /* IP6 configuration info */ NMIP6Config * ip6_config; @@ -164,8 +163,6 @@ static gboolean spec_match_list (NMDeviceInterface *device, const GSList *specs) static NMConnection *connection_match_config (NMDeviceInterface *device, const GSList *connections); static gboolean can_assume_connections (NMDeviceInterface *device); -static gboolean nm_device_activate_stage5_ip_config_commit (gpointer user_data); - static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason); static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware); @@ -686,11 +683,11 @@ nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6) /* Fail the connection if the failed IP method is required to complete */ if (ip6) { - s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6 && !nm_setting_ip6_config_get_may_fail (s_ip6)) return TRUE; } else { - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4)) return TRUE; } @@ -704,7 +701,7 @@ ip6_method_matches (NMConnection *connection, const char *match) NMSettingIP6Config *s_ip6; const char *method = NULL; - s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) { method = nm_setting_ip6_config_get_method (s_ip6); g_assert (method); @@ -741,7 +738,7 @@ nm_device_activate_stage1_device_prepare (gpointer user_data) /* Clear the activation source ID now that this stage has run */ activation_source_clear (self, FALSE, 0); - priv->ip4_ready = priv->ip6_ready = FALSE; + priv->ip4_done = priv->ip6_done = FALSE; iface = nm_device_get_iface (self); nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface); @@ -902,28 +899,20 @@ aipd_cleanup (NMDevice *self) } aipd_timeout_remove (self); - - priv->aipd_addr = 0; } static NMIP4Config * -aipd_get_ip4_config (NMDevice *self, NMDeviceStateReason *reason) +aipd_get_ip4_config (NMDevice *self, struct in_addr lla) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMIP4Config *config = NULL; NMIP4Address *addr; NMIP4Route *route; - g_return_val_if_fail (priv->aipd_addr > 0, NULL); - config = nm_ip4_config_new (); - if (!config) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - return NULL; - } + g_assert (config); addr = nm_ip4_address_new (); - nm_ip4_address_set_address (addr, (guint32) priv->aipd_addr); + nm_ip4_address_set_address (addr, (guint32) lla.s_addr); nm_ip4_address_set_prefix (addr, 16); nm_ip4_config_take_address (config, addr); @@ -938,35 +927,19 @@ aipd_get_ip4_config (NMDevice *self, NMDeviceStateReason *reason) return config; } -static gboolean -handle_autoip_change (NMDevice *self, NMDeviceStateReason *reason) +static void +autoip_changed (NMDevice *self, + NMIP4Config *config, + NMSettingIP4Config *s_ip4) { - NMActRequest *req; - NMConnection *connection; - NMIP4Config *config; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - g_return_val_if_fail (reason != NULL, FALSE); - - config = aipd_get_ip4_config (self, reason); - if (!config) { - nm_log_err (LOGD_AUTOIP4, "failed to get autoip config for rebind"); - return FALSE; - } - - req = nm_device_get_act_request (self); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - - g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config); - - if (!nm_device_set_ip4_config (self, config, FALSE, reason)) { + nm_utils_merge_ip4_config (config, s_ip4); + if (!nm_device_set_ip4_config (self, config, FALSE, &reason)) { nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config in response to autoip event.", - nm_device_get_iface (self)); - return FALSE; + nm_device_get_iface (self)); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); } - - return TRUE; } #define IPV4LL_NETWORK (htonl (0xA9FE0000L)) @@ -977,7 +950,6 @@ nm_device_handle_autoip4_event (NMDevice *self, const char *event, const char *address) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActRequest *req; NMConnection *connection = NULL; NMSettingIP4Config *s_ip4 = NULL; @@ -995,57 +967,58 @@ nm_device_handle_autoip4_event (NMDevice *self, return; /* Ignore if the connection isn't an AutoIP connection */ - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4) method = nm_setting_ip4_config_get_method (s_ip4); - if (!s_ip4 || !method || strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) + if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0) return; iface = nm_device_get_iface (self); state = nm_device_get_state (self); if (strcmp (event, "BIND") == 0) { - struct in_addr ip; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + struct in_addr lla; + NMIP4Config *config; - if (inet_pton (AF_INET, address, &ip) <= 0) { + if (inet_pton (AF_INET, address, &lla) <= 0) { nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd.", iface, address); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); return; } - if ((ip.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { + if ((lla.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd (not link-local).", iface, address); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); return; } + config = aipd_get_ip4_config (self, lla); + if (config == NULL) { + nm_log_err (LOGD_AUTOIP4, "failed to get autoip config"); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + switch (state) { case NM_DEVICE_STATE_IP_CONFIG: - if (priv->aipd_addr) { - nm_log_warn (LOGD_AUTOIP4, "(%s): already have autoip address!", iface); - return; - } - - priv->aipd_addr = ip.s_addr; aipd_timeout_remove (self); - nm_device_activate_schedule_stage4_ip4_config_get (self); + nm_device_activate_schedule_ip4_config_result (self, config); break; case NM_DEVICE_STATE_IP_CHECK: case NM_DEVICE_STATE_SECONDARIES: case NM_DEVICE_STATE_ACTIVATED: - priv->aipd_addr = ip.s_addr; - if (!handle_autoip_change (self, &reason)) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + autoip_changed (self, config, s_ip4); break; default: nm_log_warn (LOGD_AUTOIP4, "(%s): unexpected avahi-autoip event %s for %s.", iface, event, address); break; } + g_object_unref (config); + } else { nm_log_warn (LOGD_AUTOIP4, "(%s): autoip address %s no longer valid because '%s'.", iface, address, event); @@ -1103,7 +1076,7 @@ aipd_timeout_cb (gpointer user_data) aipd_cleanup (self); if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_activate_schedule_stage4_ip4_config_timeout (self); + nm_device_activate_schedule_ip4_config_timeout (self); return FALSE; } @@ -1119,12 +1092,12 @@ aipd_child_setup (gpointer user_data G_GNUC_UNUSED) setpgid (pid, pid); } -static gboolean -aipd_exec (NMDevice *self, GError **error) +static NMActStageReturn +aipd_start (NMDevice *self, NMDeviceStateReason *reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (self); char *argv[6], *cmdline; - gboolean success = FALSE; const char **aipd_binary = NULL; static const char *aipd_paths[] = { "/usr/sbin/avahi-autoipd", @@ -1132,6 +1105,7 @@ aipd_exec (NMDevice *self, GError **error) NULL }; int i = 0; + GError *error = NULL; aipd_cleanup (self); @@ -1144,8 +1118,11 @@ aipd_exec (NMDevice *self, GError **error) } if (!*aipd_binary) { - g_set_error (error, 0, 0, "%s", "couldn't find avahi-autoipd"); - return FALSE; + nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" + " to start avahi-autoipd: not found", iface); + *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; } argv[i++] = (char *) (*aipd_binary); @@ -1157,13 +1134,24 @@ aipd_exec (NMDevice *self, GError **error) argv[i++] = NULL; cmdline = g_strjoinv (" ", argv); - nm_log_dbg(LOGD_AUTOIP4, "running: %s", cmdline); + nm_log_dbg (LOGD_AUTOIP4, "running: %s", cmdline); g_free (cmdline); - success = g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, - &aipd_child_setup, NULL, &(priv->aipd_pid), error); - if (!success) - return FALSE; + if (!g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, + &aipd_child_setup, NULL, &(priv->aipd_pid), &error)) { + nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" + " to start avahi-autoipd: %s", + iface, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + aipd_cleanup (self); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation (%s) Stage 3 of 5 (IP Configure Start) started" + " avahi-autoipd...", iface); /* Monitor the child process so we know when it dies */ priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self); @@ -1171,7 +1159,7 @@ aipd_exec (NMDevice *self, GError **error) /* Start a timeout to bound the address attempt */ priv->aipd_timeout = g_timeout_add_seconds (20, aipd_timeout_cb, self); - return TRUE; + return NM_ACT_STAGE_RETURN_POSTPONE; } /*********************************************/ @@ -1186,46 +1174,36 @@ dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data) } static void -dhcp4_lease_change (NMDevice *device) +dhcp4_lease_change (NMDevice *device, NMIP4Config *config) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMIP4Config *ip4_config; - NMSettingIP4Config *s_ip4; NMConnection *connection; NMActRequest *req; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - gboolean assumed; - req = nm_device_get_act_request (device); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - assumed = nm_act_request_get_assumed (req); - - ip4_config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE); - if (!ip4_config) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv4 config for rebind", + if (config == NULL) { + nm_log_warn (LOGD_DHCP4, "(%s): failed to get DHCPv4 config for rebind", nm_device_get_ip_iface (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); return; } - s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); - nm_utils_merge_ip4_config (ip4_config, s_ip4); + req = nm_device_get_act_request (device); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); - g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, ip4_config); + /* Merge with user overrides */ + nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection)); - if (nm_device_set_ip4_config (device, ip4_config, assumed, &reason)) { - nm_dhcp4_config_reset (priv->dhcp4_config); - nm_dhcp_client_foreach_option (priv->dhcp4_client, - dhcp4_add_option_cb, - priv->dhcp4_config); - nm_utils_call_dispatcher ("dhcp4-change", connection, device, NULL, NULL, NULL); - } else { + if (!nm_device_set_ip4_config (device, config, FALSE, &reason)) { nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv4 config in response to DHCP event.", nm_device_get_ip_iface (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + return; } + + /* Notify dispatcher scripts of new DHCP4 config */ + nm_utils_call_dispatcher ("dhcp4-change", connection, device, NULL, NULL, NULL); } static void @@ -1237,7 +1215,7 @@ dhcp4_fail (NMDevice *device, gboolean timeout) nm_dhcp4_config_reset (priv->dhcp4_config); if (timeout || (dev_state == NM_DEVICE_STATE_IP_CONFIG)) - nm_device_activate_schedule_stage4_ip4_config_timeout (device); + nm_device_activate_schedule_ip4_config_timeout (device); else if (dev_state == NM_DEVICE_STATE_ACTIVATED) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); } @@ -1248,7 +1226,9 @@ dhcp4_state_changed (NMDHCPClient *client, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); NMDeviceState dev_state; + NMIP4Config *config; g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE); @@ -1262,10 +1242,21 @@ dhcp4_state_changed (NMDHCPClient *client, case DHC_RENEW4: /* lease renewed */ case DHC_REBOOT: /* have valid lease, but now obtained a different one */ case DHC_REBIND4: /* new, different lease */ + config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE); if (dev_state == NM_DEVICE_STATE_IP_CONFIG) - nm_device_activate_schedule_stage4_ip4_config_get (device); + nm_device_activate_schedule_ip4_config_result (device, config); else if (dev_state == NM_DEVICE_STATE_ACTIVATED) - dhcp4_lease_change (device); + dhcp4_lease_change (device, config); + if (config) { + /* Update the DHCP4 config object with new DHCP options */ + nm_dhcp4_config_reset (priv->dhcp4_config); + nm_dhcp_client_foreach_option (priv->dhcp4_client, + dhcp4_add_option_cb, + priv->dhcp4_config); + g_object_notify (G_OBJECT (device), NM_DEVICE_INTERFACE_DHCP4_CONFIG); + + g_object_unref (config); + } break; case DHC_TIMEOUT: /* timed out contacting DHCP server */ dhcp4_fail (device, TRUE); @@ -1395,7 +1386,7 @@ reserve_shared_ip (void) } static NMIP4Config * -nm_device_new_ip4_shared_config (NMDevice *self, NMDeviceStateReason *reason) +shared4_new_config (NMDevice *self, NMDeviceStateReason *reason) { NMIP4Config *config = NULL; NMIP4Address *addr; @@ -1428,56 +1419,44 @@ nm_device_new_ip4_shared_config (NMDevice *self, NMDeviceStateReason *reason) /*********************************************/ static NMActStageReturn -real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason) +real_act_stage3_ip4_config_start (NMDevice *self, + NMIP4Config **out_config, + NMDeviceStateReason *reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; NMSettingIP4Config *s_ip4; NMActRequest *req; NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - const char *method = NULL; - int ifindex; + const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - /* Make sure the interface is up before trying to do anything with it */ - ifindex = nm_device_get_ip_ifindex (self); - if (!nm_system_iface_is_up (ifindex)) - nm_system_iface_set_up (ifindex, TRUE, NULL); - req = nm_device_get_act_request (self); connection = nm_act_request_get_connection (req); - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - /* If we did not receive IP4 configuration information, default to DHCP */ + s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4) method = nm_setting_ip4_config_get_method (s_ip4); - if (!s_ip4 || !method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + /* Start IPv4 addressing based on the method requested */ + if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) ret = dhcp4_start (self, connection, reason); - } else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { - GError *error = NULL; - const char *iface = nm_device_get_iface (self); - - /* Start avahi-autoipd */ - if (aipd_exec (self, &error)) { - nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation (%s) Stage 3 of 5 (IP Configure Start) started" - " avahi-autoipd...", iface); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation (%s) Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: %s", iface, error->message); - g_error_free (error); - aipd_cleanup (self); - *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; + else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) + ret = aipd_start (self, reason); + else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { + /* Use only IPv4 config from the connection data */ + *out_config = nm_ip4_config_new (); + g_assert (*out_config); + } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { + *out_config = shared4_new_config (self, reason); + if (*out_config) + priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self)); + else ret = NM_ACT_STAGE_RETURN_FAILURE; - } } else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { /* Nothing to do... */ - priv->ip4_ready = TRUE; ret = NM_ACT_STAGE_RETURN_STOP; } @@ -1496,7 +1475,7 @@ dhcp6_add_option_cb (gpointer key, gpointer value, gpointer user_data) } static void -merge_dhcp_config_to_master (NMIP6Config *dst, NMIP6Config *src) +merge_ip6_configs (NMIP6Config *dst, NMIP6Config *src) { guint32 i; @@ -1531,105 +1510,56 @@ merge_dhcp_config_to_master (NMIP6Config *dst, NMIP6Config *src) nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); } - -static gboolean -update_ip6_config_with_dhcp (NMDevice *device, NMIP6Config *ip6_config, NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMIP6Config *dhcp6_config; - NMActRequest *req; - NMConnection *connection; - NMSettingIP6Config *s_ip6; - gboolean assumed, need_dhcp; - - req = nm_device_get_act_request (device); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - assumed = nm_act_request_get_assumed (req); - - if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) - need_dhcp = TRUE; - else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { - need_dhcp = TRUE; - g_assert (priv->dhcp6_client); /* sanity check */ - } - - if (need_dhcp) { - dhcp6_config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, TRUE); - if (!dhcp6_config) { - *reason = NM_DEVICE_STATE_REASON_DHCP_ERROR; - return FALSE; - } - if (!ip6_config && dhcp6_config) - ip6_config = dhcp6_config; - else - merge_dhcp_config_to_master (ip6_config, dhcp6_config); - } - - s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG)); - nm_utils_merge_ip6_config (ip6_config, s_ip6); - - g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP6_CONFIG, ip6_config); - - if (nm_device_set_ip6_config (device, ip6_config, assumed, reason)) { - nm_dhcp6_config_reset (priv->dhcp6_config); - nm_dhcp_client_foreach_option (priv->dhcp6_client, - dhcp6_add_option_cb, - priv->dhcp6_config); - nm_utils_call_dispatcher ("dhcp6-change", connection, device, NULL, NULL, NULL); - g_object_notify (G_OBJECT (device), NM_DEVICE_INTERFACE_DHCP6_CONFIG); - } else { - nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.", - nm_device_get_ip_iface (device)); - *reason = NM_DEVICE_STATE_REASON_DHCP_ERROR; - return FALSE; - } - - return TRUE; -} - static void -dhcp6_lease_change (NMDevice *device) +dhcp6_lease_change (NMDevice *device, NMIP6Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - NMIP6Config *ip6_config = NULL; + NMIP6Config *ra_config = NULL; NMConnection *connection; NMActRequest *req; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - gboolean assumed; + + if (config == NULL) { + nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for rebind", + nm_device_get_ip_iface (device)); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + return; + } + + g_assert (priv->dhcp6_client); /* sanity check */ req = nm_device_get_act_request (device); g_assert (req); connection = nm_act_request_get_connection (req); g_assert (connection); - assumed = nm_act_request_get_assumed (req); - if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO) - || ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { - ip6_config = nm_ip6_manager_get_ip6_config (priv->ip6_manager, - nm_device_get_ip_ifindex (device)); - if (!ip6_config) { + /* May need to merge RA config and DHCPv6 config */ + if (priv->ip6_manager && ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + ra_config = nm_ip6_manager_get_ip6_config (priv->ip6_manager, + nm_device_get_ip_ifindex (device)); + if (ra_config == NULL) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return; } - } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { - ip6_config = nm_ip6_config_new (); - if (!ip6_config) { - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) - g_assert (priv->dhcp6_client); /* sanity check */ - if (!update_ip6_config_with_dhcp (device, ip6_config, &reason)) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for rebind", + /* Merge RA config with DHCPv6 config */ + merge_ip6_configs (config, ra_config); + g_object_unref (ra_config); + } + + /* Merge DHCPv6 and RA composite config with user overrides */ + nm_utils_merge_ip6_config (config, nm_connection_get_setting_ip6_config (connection)); + + if (nm_device_set_ip6_config (device, config, FALSE, &reason) == FALSE) { + nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.", nm_device_get_ip_iface (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); return; } + + /* Notify dispatcher scripts of new DHCP4 config */ + nm_utils_call_dispatcher ("dhcp6-change", connection, device, NULL, NULL, NULL); } static void @@ -1641,7 +1571,7 @@ dhcp6_fail (NMDevice *device, gboolean timeout) nm_dhcp6_config_reset (priv->dhcp6_config); if (timeout || (dev_state == NM_DEVICE_STATE_IP_CONFIG)) - nm_device_activate_schedule_stage4_ip6_config_timeout (device); + nm_device_activate_schedule_ip6_config_timeout (device); else if (dev_state == NM_DEVICE_STATE_ACTIVATED) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); } @@ -1654,6 +1584,7 @@ dhcp6_state_changed (NMDHCPClient *client, NMDevice *device = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); NMDeviceState dev_state; + NMIP6Config *config; g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE); @@ -1667,10 +1598,22 @@ dhcp6_state_changed (NMDHCPClient *client, case DHC_RENEW6: /* lease renewed */ case DHC_REBOOT: /* have valid lease, but now obtained a different one */ case DHC_REBIND6: /* new, different lease */ + config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE); if (dev_state == NM_DEVICE_STATE_IP_CONFIG) - nm_device_activate_schedule_stage4_ip6_config_get (device); + nm_device_activate_schedule_ip6_config_result (device, config); else if (dev_state == NM_DEVICE_STATE_ACTIVATED) - dhcp6_lease_change (device); + dhcp6_lease_change (device, config); + + if (config) { + /* Update the DHCP6 config object with new DHCP options */ + nm_dhcp6_config_reset (priv->dhcp6_config); + nm_dhcp_client_foreach_option (priv->dhcp6_client, + dhcp6_add_option_cb, + priv->dhcp6_config); + g_object_notify (G_OBJECT (device), NM_DEVICE_INTERFACE_DHCP6_CONFIG); + + g_object_unref (config); + } break; case DHC_TIMEOUT: /* timed out contacting DHCP server */ dhcp6_fail (device, TRUE); @@ -1796,6 +1739,7 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager, NMActStageReturn ret; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; NMDeviceState state; + NMIP6Config *config; if (ifindex != nm_device_get_ip_ifindex (self)) return; @@ -1811,7 +1755,7 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager, priv->ip6_waiting_for_config = FALSE; if (!success) { - nm_device_activate_schedule_stage4_ip6_config_timeout (self); + nm_device_activate_schedule_ip6_config_timeout (self); return; } @@ -1819,7 +1763,10 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager, /* If addrconf is all that's required, we're done */ if (priv->dhcp6_mode == IP6_DHCP_OPT_NONE) { - nm_device_activate_schedule_stage4_ip6_config_get (self); + config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); + nm_device_activate_schedule_ip6_config_result (self, config); + if (config) + g_object_unref (config); return; } @@ -1840,7 +1787,10 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager, case NM_ACT_STAGE_RETURN_SUCCESS: /* Shouldn't get this, but handle it anyway */ g_warn_if_reached (); - nm_device_activate_schedule_stage4_ip6_config_get (self); + config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); + nm_device_activate_schedule_ip6_config_result (self, config); + if (config) + g_object_unref (config); break; case NM_ACT_STAGE_RETURN_POSTPONE: /* Success; wait for DHCPv6 to complete */ @@ -1859,6 +1809,11 @@ ip6_config_changed (NMIP6Manager *ip6_manager, gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMIP6Config *config, *dhcp_config = NULL; + NMConnection *connection; + NMActRequest *req; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; if (ifindex != nm_device_get_ip_ifindex (self)) return; @@ -1874,11 +1829,39 @@ ip6_config_changed (NMIP6Manager *ip6_manager, return; } - nm_device_activate_schedule_stage4_ip6_config_get (self); + req = nm_device_get_act_request (self); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); + + config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex); + + /* May need to merge RA config and DHCPv6 config */ + if (priv->dhcp6_client) { + dhcp_config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE); + if (dhcp_config == NULL) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + + /* Merge DHCPv6 config with RA config */ + merge_ip6_configs (config, dhcp_config); + g_object_unref (dhcp_config); + } + + /* Merge DHCPv6 and RA composite config with user overrides */ + nm_utils_merge_ip6_config (config, nm_connection_get_setting_ip6_config (connection)); + + if (nm_device_set_ip6_config (self, config, FALSE, &reason) == FALSE) { + nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to Router Advertisement.", + nm_device_get_ip_iface (self)); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + } } static gboolean -addrconf6_setup (NMDevice *self) +addrconf6_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActRequest *req; @@ -1903,13 +1886,15 @@ addrconf6_setup (NMDevice *self) self); } - s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = nm_connection_get_setting_ip6_config (connection); success = nm_ip6_manager_prepare_interface (priv->ip6_manager, nm_device_get_ip_ifindex (self), s_ip6, priv->ip6_accept_ra_path); - if (success) + if (success) { priv->ip6_waiting_for_config = TRUE; + nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self)); + } return success; } @@ -1941,7 +1926,9 @@ addrconf6_cleanup (NMDevice *self) /******************************************/ static NMActStageReturn -real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason) +real_act_stage3_ip6_config_start (NMDevice *self, + NMIP6Config **out_config, + NMDeviceStateReason *reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *ip_iface; @@ -1964,12 +1951,11 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason) if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO) || ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { - if (!addrconf6_setup (self)) { + if (!addrconf6_start (self)) { *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - goto out; - } - nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self)); - ret = NM_ACT_STAGE_RETURN_POSTPONE; + ret = NM_ACT_STAGE_RETURN_FAILURE; + } else + ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { /* Router advertisements shouldn't be used in pure DHCP mode */ if (priv->ip6_accept_ra_path) @@ -1983,10 +1969,12 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason) nm_utils_do_sysctl (priv->ip6_accept_ra_path, priv->ip6_accept_ra_save ? "1\n" : "0\n"); } - - priv->ip6_ready = TRUE; ret = NM_ACT_STAGE_RETURN_STOP; } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { + /* New blank config */ + *out_config = nm_ip6_config_new (); + g_assert (*out_config); + /* Router advertisements shouldn't be used in manual mode */ if (priv->ip6_accept_ra_path) nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n"); @@ -1995,7 +1983,6 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason) /* Other methods (shared) aren't implemented yet */ -out: return ret; } @@ -2010,9 +1997,13 @@ static gboolean nm_device_activate_stage3_ip_config_start (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *iface; NMActStageReturn ret; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMIP4Config *ip4_config = NULL; + NMIP6Config *ip6_config = NULL; + int ifindex; /* Clear the activation source ID now that this stage has run */ activation_source_clear (self, FALSE, 0); @@ -2021,25 +2012,36 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data) nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface); nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) - nm_device_activate_schedule_stage4_ip4_config_get (self); - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + /* Make sure the interface is up before trying to do anything with it */ + ifindex = nm_device_get_ip_ifindex (self); + if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) + nm_system_iface_set_up (ifindex, TRUE, NULL); + + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + g_assert (ip4_config); + nm_device_activate_schedule_ip4_config_result (self, ip4_config); + g_object_unref (ip4_config); + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); goto out; } else if (ret == NM_ACT_STAGE_RETURN_STOP) { /* Nothing to do */ + priv->ip4_done = TRUE; } else g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) - nm_device_activate_schedule_stage4_ip6_config_get (self); - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + g_assert (ip6_config); + nm_device_activate_schedule_ip6_config_result (self, ip6_config); + g_object_unref (ip6_config); + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); goto out; } else if (ret == NM_ACT_STAGE_RETURN_STOP) { /* Nothing to do */ + priv->ip6_done = TRUE; } else g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); @@ -2070,162 +2072,13 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) nm_device_get_iface (self)); } -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *self, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMConnection *connection; - NMSettingIP4Config *s_ip4; - const char *ip_iface; - - 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_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - /* Use the IP interface (not the control interface) for IP stuff */ - ip_iface = nm_device_get_ip_iface (self); - - connection = nm_act_request_get_connection (nm_device_get_act_request (self)); - g_assert (connection); - - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - - if (priv->dhcp4_client) { - /* DHCP */ - *config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE); - if (*config) { - /* Merge user-defined overrides into the IP4Config to be applied */ - nm_utils_merge_ip4_config (*config, s_ip4); - - nm_dhcp4_config_reset (priv->dhcp4_config); - nm_dhcp_client_foreach_option (priv->dhcp4_client, - dhcp4_add_option_cb, - priv->dhcp4_config); - - /* Notify of new DHCP4 config */ - g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP4_CONFIG); - } else - *reason = NM_DEVICE_STATE_REASON_DHCP_ERROR; - } else { - /* Not DHCP */ - const char *method; - - g_assert (s_ip4); - - method = nm_setting_ip4_config_get_method (s_ip4); - g_assert (method); - - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { - *config = aipd_get_ip4_config (self, reason); - } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { - *config = nm_ip4_config_new (); - if (*config) { - /* Merge user-defined overrides into the IP4Config to be applied */ - nm_utils_merge_ip4_config (*config, s_ip4); - } else - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - *config = nm_device_new_ip4_shared_config (self, reason); - if (*config) - priv->dnsmasq_manager = nm_dnsmasq_manager_new (ip_iface); - } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } - - if (!*config) { - /* Make sure device is up even if config fails */ - nm_device_bring_up (self, FALSE, NULL); - } else - ret = NM_ACT_STAGE_RETURN_SUCCESS; - - return ret; -} - -/* - * nm_device_activate_stage4_ip4_config_get - * - * Retrieve the correct IPv4 config. - * - */ -static gboolean -nm_device_activate_stage4_ip4_config_get (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMIP4Config *ip4_config = NULL; - NMActStageReturn ret; - const char *iface = NULL; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IP4 Configure Get) started...", - iface); - - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip4_config (self, &ip4_config, &reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; - else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - - g_object_set_data (G_OBJECT (nm_device_get_act_request (self)), - NM_ACT_REQUEST_IP4_CONFIG, ip4_config); - - priv->ip4_ready = TRUE; - nm_device_activate_stage5_ip_config_commit (self); - -out: - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IP4 Configure Get) complete.", - iface); - return FALSE; -} - - -/* - * nm_device_activate_schedule_stage4_ip4_config_get - * - * Schedule creation of the IPv4 config - * - */ -void -nm_device_activate_schedule_stage4_ip4_config_get (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - activation_source_schedule (self, nm_device_activate_stage4_ip4_config_get, AF_INET); - - nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IP4 Configure Get) scheduled...", - nm_device_get_iface (self)); -} - - static NMActStageReturn real_act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) { - /* Notify of invalid DHCP4 config object */ - g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP4_CONFIG); - if (nm_device_ip_config_should_fail (self, FALSE)) { *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; return NM_ACT_STAGE_RETURN_FAILURE; } - return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -2237,7 +2090,7 @@ real_act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) * */ static gboolean -nm_device_activate_stage4_ip4_config_timeout (gpointer user_data) +nm_device_activate_ip4_config_timeout (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -2250,7 +2103,7 @@ nm_device_activate_stage4_ip4_config_timeout (gpointer user_data) iface = nm_device_get_iface (self); nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IP4 Configure Timeout) started...", + "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) started...", iface); ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason); @@ -2262,25 +2115,31 @@ nm_device_activate_stage4_ip4_config_timeout (gpointer user_data) } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - priv->ip4_ready = TRUE; - nm_device_activate_stage5_ip_config_commit (self); + priv->ip4_done = TRUE; + + /* If IPv4 failed and IPv6 failed, the activation fails */ + if (priv->ip6_done && priv->ip6_config == NULL) { + nm_device_state_changed (self, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } out: nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IP4 Configure Timeout) complete.", + "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) complete.", iface); return FALSE; } /* - * nm_device_activate_schedule_stage4_ip4_config_timeout + * nm_device_activate_schedule_ip4_config_timeout * * Deal with a timeout of the IPv4 configuration * */ void -nm_device_activate_schedule_stage4_ip4_config_timeout (NMDevice *self) +nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) { NMDevicePrivate *priv; @@ -2289,137 +2148,10 @@ nm_device_activate_schedule_stage4_ip4_config_timeout (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->act_request); - activation_source_schedule (self, nm_device_activate_stage4_ip4_config_timeout, AF_INET); + activation_source_schedule (self, nm_device_activate_ip4_config_timeout, AF_INET); nm_log_info (LOGD_DEVICE | LOGD_IP4, - "Activation (%s) Stage 4 of 5 (IP4 Configure Timeout) scheduled...", - nm_device_get_iface (self)); -} - -static NMActStageReturn -real_act_stage4_get_ip6_config (NMDevice *self, - NMIP6Config **config, - NMDeviceStateReason *reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - NMSettingIP6Config *s_ip6; - const char *ip_iface; - - 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_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - /* Use the IP interface (not the control interface) for IP stuff */ - ip_iface = nm_device_get_ip_iface (self); - - connection = nm_act_request_get_connection (nm_device_get_act_request (self)); - g_assert (connection); - - if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO) - || ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { - *config = nm_ip6_manager_get_ip6_config (priv->ip6_manager, - nm_device_get_ip_ifindex (self)); - if (!*config) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - goto out; - } - } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { - *config = nm_ip6_config_new (); - if (!*config) { - *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; - goto out; - } - } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) - g_assert (priv->dhcp6_client); /* sanity check */ - - /* Autoconf might have triggered DHCPv6 too */ - if (priv->dhcp6_client) { - if (!update_ip6_config_with_dhcp (self, *config, reason)) { - nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for bind", - nm_device_get_ip_iface (self)); - goto out; - } - } - - /* Merge user-defined overrides into the IP6Config to be applied */ - if (*config) { - s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); - nm_utils_merge_ip6_config (*config, s_ip6); - } - -out: - return *config ? NM_ACT_STAGE_RETURN_SUCCESS : NM_ACT_STAGE_RETURN_FAILURE; -} - -/* - * nm_device_activate_stage4_ip6_config_get - * - * Retrieve the correct IPv6 config. - * - */ -static gboolean -nm_device_activate_stage4_ip6_config_get (gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMIP6Config *ip6_config = NULL; - NMActStageReturn ret; - const char *iface = NULL; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET6); - - iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IP6 Configure Get) started...", - iface); - - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip6_config (self, &ip6_config, &reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) - { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - - g_object_set_data (G_OBJECT (nm_device_get_act_request (self)), - NM_ACT_REQUEST_IP6_CONFIG, ip6_config); - - priv->ip6_ready = TRUE; - nm_device_activate_stage5_ip_config_commit (self); - -out: - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IP6 Configure Get) complete.", - iface); - return FALSE; -} - - -/* - * nm_device_activate_schedule_stage4_ip6_config_get - * - * Schedule creation of the IPv6 config - * - */ -void -nm_device_activate_schedule_stage4_ip6_config_get (NMDevice *self) -{ - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request); - - activation_source_schedule (self, nm_device_activate_stage4_ip6_config_get, AF_INET6); - - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IP6 Configure Get) scheduled...", + "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) scheduled...", nm_device_get_iface (self)); } @@ -2427,9 +2159,6 @@ nm_device_activate_schedule_stage4_ip6_config_get (NMDevice *self) static NMActStageReturn real_act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) { - /* Notify of invalid DHCP4 config object */ - g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP6_CONFIG); - if (nm_device_ip_config_should_fail (self, TRUE)) { *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; return NM_ACT_STAGE_RETURN_FAILURE; @@ -2440,13 +2169,13 @@ real_act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) /* - * nm_device_activate_stage4_ip6_config_timeout + * nm_device_activate_ip6_config_timeout * * Time out on retrieving the IPv6 config. * */ static gboolean -nm_device_activate_stage4_ip6_config_timeout (gpointer user_data) +nm_device_activate_ip6_config_timeout (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -2459,7 +2188,7 @@ nm_device_activate_stage4_ip6_config_timeout (gpointer user_data) iface = nm_device_get_iface (self); nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IP6 Configure Timeout) started...", + "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) started...", iface); ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason); @@ -2471,25 +2200,31 @@ nm_device_activate_stage4_ip6_config_timeout (gpointer user_data) } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - priv->ip6_ready = TRUE; - nm_device_activate_stage5_ip_config_commit (self); + priv->ip6_done = TRUE; + + /* If IPv6 failed and IPv4 failed, the activation fails */ + if (priv->ip4_done && priv->ip4_config == NULL) { + nm_device_state_changed (self, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } out: nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IP6 Configure Timeout) complete.", + "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) complete.", iface); return FALSE; } /* - * nm_device_activate_schedule_stage4_ip6_config_timeout + * nm_device_activate_schedule_ip6_config_timeout * * Deal with a timeout of the IPv6 configuration * */ void -nm_device_activate_schedule_stage4_ip6_config_timeout (NMDevice *self) +nm_device_activate_schedule_ip6_config_timeout (NMDevice *self) { NMDevicePrivate *priv; @@ -2498,10 +2233,10 @@ nm_device_activate_schedule_stage4_ip6_config_timeout (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->act_request); - activation_source_schedule (self, nm_device_activate_stage4_ip6_config_timeout, AF_INET6); + activation_source_schedule (self, nm_device_activate_ip6_config_timeout, AF_INET6); nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 4 of 5 (IP6 Configure Timeout) scheduled...", + "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) scheduled...", nm_device_get_iface (self)); } @@ -2629,103 +2364,209 @@ start_sharing (NMDevice *self) return TRUE; } -/* - * nm_device_activate_stage5_ip_config_commit - * - * Commit the IP config on the device - * - */ static gboolean -nm_device_activate_stage5_ip_config_commit (gpointer user_data) +nm_device_activate_ip4_config_commit (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActRequest *act_request; - NMIP4Config *ip4_config = NULL; - NMIP6Config *ip6_config = NULL; + NMActRequest *req; + NMIP4Config *config = NULL; const char *iface, *method = NULL; NMConnection *connection; NMSettingIP4Config *s_ip4; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; gboolean assumed; - - /* Get the new IP4 and IP6 configs; since this stage gets rerun - * when automatic configuration changes (DHCP lease renewal, new - * IPv6 router advertisement, etc), it's possible that only one of - * them will be set. - */ - act_request = nm_device_get_act_request (self); - if (priv->ip4_ready) - ip4_config = g_object_get_data (G_OBJECT (act_request), - NM_ACT_REQUEST_IP4_CONFIG); - - if (priv->ip6_ready) - ip6_config = g_object_get_data (G_OBJECT (act_request), - NM_ACT_REQUEST_IP6_CONFIG); + int ifindex; /* Clear the activation source ID now that this stage has run */ activation_source_clear (self, FALSE, 0); + req = nm_device_get_act_request (self); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); + + config = g_object_get_data (G_OBJECT (req), PENDING_IP4_CONFIG); + g_assert (config); + iface = nm_device_get_iface (self); - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IP Configure Commit) started...", + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) started...", iface); + /* Make sure the interface is up again just because */ + ifindex = nm_device_get_ip_ifindex (self); + if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) + nm_system_iface_set_up (ifindex, TRUE, NULL); + + /* Allow setting MTU etc */ + if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) + NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, config); + assumed = nm_act_request_get_assumed (priv->act_request); - - if (!ip6_config && !ip4_config) { - nm_log_info (LOGD_DEVICE, - "Activation (%s) Stage 5 of 5 (IP Configure Commit) failed (no IP configuration found)", - iface); - nm_device_state_changed (self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - goto out; - } - - if (ip4_config && !nm_device_set_ip4_config (self, ip4_config, assumed, &reason)) { + if (!nm_device_set_ip4_config (self, config, assumed, &reason)) { + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 5 of 5 (IPv4 Commit) failed", + iface); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); goto out; } - if (ip6_config && !nm_device_set_ip6_config (self, ip6_config, assumed, &reason)) { - nm_log_info (LOGD_DEVICE | LOGD_IP6, - "Activation (%s) Stage 5 of 5 (IP Configure Commit) IPv6 failed", - iface); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; - } + /* Start IPv4 sharing if we need it */ + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (s_ip4) + method = nm_setting_ip4_config_get_method (s_ip4); - connection = nm_act_request_get_connection (nm_device_get_act_request (self)); - - if (ip4_config) { - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - if (s_ip4) - method = nm_setting_ip4_config_get_method (s_ip4); - - if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - if (!start_sharing (self)) { - nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IP Configure Commit) start sharing failed.", iface); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - goto out; - } + if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { + if (!start_sharing (self)) { + nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IPv4 Commit) start sharing failed.", iface); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + goto out; } } - nm_device_state_changed (self, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); + /* Enter the ACTIVATED state if this is the first method to complete */ + priv->ip4_done = TRUE; + if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) + nm_device_state_changed (self, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); out: - nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IP Configure Commit) complete.", + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) complete.", iface); - /* Balance IP config creation; device takes ownership in set_ip*_config() */ - if (ip4_config) - g_object_unref (ip4_config); - if (ip6_config) - g_object_unref (ip6_config); + /* Balance IP config creation; nm_device_set_ip4_config() takes a reference */ + g_object_set_data (G_OBJECT (req), PENDING_IP4_CONFIG, NULL); return FALSE; } +void +nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config) +{ + NMDevicePrivate *priv; + NMConnection *connection; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + if (config == NULL) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + + connection = nm_act_request_get_connection (priv->act_request); + g_assert (connection); + + /* Merge with user overrides and save the pending config */ + nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection)); + g_object_set_data_full (G_OBJECT (priv->act_request), + PENDING_IP4_CONFIG, + g_object_ref (config), + g_object_unref); + + activation_source_schedule (self, nm_device_activate_ip4_config_commit, AF_INET); + + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 5 of 5 (IPv4 Configure Commit) scheduled...", + nm_device_get_iface (self)); +} + +static gboolean +nm_device_activate_ip6_config_commit (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActRequest *req; + NMIP6Config *config = NULL; + const char *iface; + NMConnection *connection; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + gboolean assumed; + int ifindex; + + /* Clear the activation source ID now that this stage has run */ + activation_source_clear (self, FALSE, 0); + + req = nm_device_get_act_request (self); + g_assert (req); + connection = nm_act_request_get_connection (req); + g_assert (connection); + + config = g_object_get_data (G_OBJECT (req), PENDING_IP6_CONFIG); + g_assert (config); + + iface = nm_device_get_iface (self); + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...", + iface); + + /* Make sure the interface is up again just because */ + ifindex = nm_device_get_ip_ifindex (self); + if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) + nm_system_iface_set_up (ifindex, TRUE, NULL); + + /* Allow setting MTU etc */ + if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit) + NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, config); + + assumed = nm_act_request_get_assumed (priv->act_request); + if (!nm_device_set_ip6_config (self, config, assumed, &reason)) { + nm_log_info (LOGD_DEVICE | LOGD_IP6, + "Activation (%s) Stage 5 of 5 (IPv6 Commit) failed", + iface); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + goto out; + } + + /* Enter the ACTIVATED state if this is the first method to complete */ + priv->ip6_done = TRUE; + if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) + nm_device_state_changed (self, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); + +out: + nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.", + iface); + + /* Balance IP config creation; nm_device_set_ip6_config() takes a reference */ + g_object_set_data (G_OBJECT (req), PENDING_IP6_CONFIG, NULL); + + return FALSE; +} + +/* Takes ownership of IP6Config */ +void +nm_device_activate_schedule_ip6_config_result (NMDevice *self, NMIP6Config *config) +{ + NMDevicePrivate *priv; + NMConnection *connection; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + g_return_if_fail (priv->act_request); + + if (config == NULL) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + + connection = nm_act_request_get_connection (priv->act_request); + g_assert (connection); + + /* Merge with user overrides and save the pending config */ + nm_utils_merge_ip6_config (config, nm_connection_get_setting_ip6_config (connection)); + g_object_set_data_full (G_OBJECT (priv->act_request), + PENDING_IP6_CONFIG, + g_object_ref (config), + g_object_unref); + + activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6); + + nm_log_info (LOGD_DEVICE | LOGD_IP4, + "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...", + nm_device_get_iface (self)); +} + static void clear_act_request (NMDevice *self) { @@ -3607,8 +3448,6 @@ nm_device_class_init (NMDeviceClass *klass) klass->act_stage2_config = real_act_stage2_config; klass->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; klass->act_stage3_ip6_config_start = real_act_stage3_ip6_config_start; - klass->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; - klass->act_stage4_get_ip6_config = real_act_stage4_get_ip6_config; klass->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout; klass->act_stage4_ip6_config_timeout = real_act_stage4_ip6_config_timeout; diff --git a/src/nm-device.h b/src/nm-device.h index 89abbea020..b5df483d76 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -99,19 +99,20 @@ typedef struct { NMActStageReturn (* act_stage2_config) (NMDevice *self, NMDeviceStateReason *reason); NMActStageReturn (* act_stage3_ip4_config_start) (NMDevice *self, + NMIP4Config **out_config, NMDeviceStateReason *reason); NMActStageReturn (* act_stage3_ip6_config_start) (NMDevice *self, + NMIP6Config **out_config, NMDeviceStateReason *reason); - NMActStageReturn (* act_stage4_get_ip4_config) (NMDevice *self, - NMIP4Config **config, - NMDeviceStateReason *reason); - NMActStageReturn (* act_stage4_get_ip6_config) (NMDevice *self, - NMIP6Config **config, - NMDeviceStateReason *reason); NMActStageReturn (* act_stage4_ip4_config_timeout) (NMDevice *self, NMDeviceStateReason *reason); NMActStageReturn (* act_stage4_ip6_config_timeout) (NMDevice *self, NMDeviceStateReason *reason); + + /* Called right before IP config is set; use for setting MTU etc */ + void (* ip4_config_pre_commit) (NMDevice *self, NMIP4Config *config); + void (* ip6_config_pre_commit) (NMDevice *self, NMIP6Config *config); + void (* deactivate) (NMDevice *self); gboolean (* can_interrupt_activation) (NMDevice *self); @@ -150,8 +151,6 @@ NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *dev); NMIP4Config * nm_device_get_ip4_config (NMDevice *dev); NMIP6Config * nm_device_get_ip6_config (NMDevice *dev); -void * nm_device_get_system_config_data (NMDevice *dev); - NMActRequest * nm_device_get_act_request (NMDevice *dev); gboolean nm_device_is_available (NMDevice *dev); @@ -168,10 +167,13 @@ gboolean nm_device_complete_connection (NMDevice *device, void nm_device_activate_schedule_stage1_device_prepare (NMDevice *device); void nm_device_activate_schedule_stage2_device_config (NMDevice *device); -void nm_device_activate_schedule_stage4_ip4_config_get (NMDevice *device); -void nm_device_activate_schedule_stage4_ip4_config_timeout (NMDevice *device); -void nm_device_activate_schedule_stage4_ip6_config_get (NMDevice *device); -void nm_device_activate_schedule_stage4_ip6_config_timeout (NMDevice *device); + +void nm_device_activate_schedule_ip4_config_result (NMDevice *device, NMIP4Config *config); +void nm_device_activate_schedule_ip4_config_timeout (NMDevice *device); + +void nm_device_activate_schedule_ip6_config_result (NMDevice *device, NMIP6Config *config); +void nm_device_activate_schedule_ip6_config_timeout (NMDevice *device); + gboolean nm_device_is_activating (NMDevice *dev); gboolean nm_device_can_interrupt_activation (NMDevice *self); gboolean nm_device_autoconnect_allowed (NMDevice *self);