core: allow selective failure of IP configuration (rh #567978)

As long as at least one IP config method completes, and as long as
methods that the user required to complete do complete, allow the
connection to complete.
This commit is contained in:
Dan Williams
2010-05-03 01:19:54 -07:00
parent 3fb8cdb35f
commit 8aef7ef411
5 changed files with 158 additions and 53 deletions

View File

@@ -275,10 +275,16 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
case NM_DEVICE_STATE_PREPARE:
case NM_DEVICE_STATE_CONFIG:
case NM_DEVICE_STATE_NEED_AUTH:
case NM_DEVICE_STATE_IP_CONFIG:
case NM_DEVICE_STATE_ACTIVATED:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
break;
case NM_DEVICE_STATE_IP_CONFIG:
if (nm_device_ip_config_should_fail (device, FALSE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
}
break;
default:
break;
}

View File

@@ -72,10 +72,16 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
case NM_DEVICE_STATE_PREPARE:
case NM_DEVICE_STATE_CONFIG:
case NM_DEVICE_STATE_NEED_AUTH:
case NM_DEVICE_STATE_IP_CONFIG:
case NM_DEVICE_STATE_ACTIVATED:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
break;
case NM_DEVICE_STATE_IP_CONFIG:
if (nm_device_ip_config_should_fail (device, FALSE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
}
break;
default:
break;
}

View File

@@ -40,4 +40,6 @@ void nm_device_handle_autoip4_event (NMDevice *self,
const char *event,
const char *address);
gboolean nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6);
#endif /* NM_DEVICE_PRIVATE_H */

View File

@@ -2676,7 +2676,11 @@ handle_auth_or_fail (NMDeviceWifi *self,
NMConnection *connection;
g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
if (!req) {
req = nm_device_get_act_request (NM_DEVICE (self));
g_assert (req);
}
connection = nm_act_request_get_connection (req);
g_assert (connection);
@@ -3187,21 +3191,19 @@ real_act_stage4_get_ip4_config (NMDevice *dev,
static NMActStageReturn
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
handle_ip_config_timeout (NMDeviceWifi *self,
NMConnection *connection,
gboolean may_fail,
gboolean *chain_up,
NMDeviceStateReason *reason)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self);
NMAccessPoint *ap;
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
NMIP4Config *real_config = NULL;
NMActRequest *req = nm_device_get_act_request (dev);
NMConnection *connection;
gboolean auth_enforced = FALSE, encrypted = FALSE;
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 (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
ap = nm_device_wifi_get_activation_ap (self);
g_assert (ap);
/* If nothing checks the security authentication information (as in
@@ -3209,9 +3211,8 @@ real_act_stage4_ip4_config_timeout (NMDevice *dev,
* the encryption key is likely wrong. Ask the user for a new one.
* Otherwise the failure likely happened after a successful authentication.
*/
connection = nm_act_request_get_connection (req);
auth_enforced = ap_auth_enforced (connection, ap, &encrypted);
if (encrypted && !auth_enforced) {
if (encrypted && !auth_enforced && !may_fail) {
NMSettingConnection *s_con;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
@@ -3220,39 +3221,83 @@ real_act_stage4_ip4_config_timeout (NMDevice *dev,
nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
"Activation (%s/wireless): could not get IP configuration for "
"connection '%s'.",
nm_device_get_iface (dev), nm_setting_connection_get_id (s_con));
nm_device_get_iface (NM_DEVICE (self)),
nm_setting_connection_get_id (s_con));
ret = handle_auth_or_fail (self, req, TRUE);
ret = handle_auth_or_fail (self, NULL, TRUE);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
nm_log_info (LOGD_DEVICE | LOGD_WIFI,
"Activation (%s/wireless): asking for new secrets",
nm_device_get_iface (dev));
nm_device_get_iface (NM_DEVICE (self)));
} else {
*reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
}
} else if (nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) {
NMDeviceWifiClass *klass;
NMDeviceClass * parent_class;
/* For Ad-Hoc networks, chain up to parent to get a Zeroconf IP */
klass = NM_DEVICE_WIFI_GET_CLASS (self);
parent_class = NM_DEVICE_CLASS (g_type_class_peek_parent (klass));
ret = parent_class->act_stage4_ip4_config_timeout (dev, &real_config, reason);
} else {
/* Non-encrypted network or authentication is enforced by some
* entity (AP, RADIUS server, etc), but IP configure failed. Alert
* the user.
* entity (AP, RADIUS server, etc), but IP configure failed. Let the
* superclass handle it.
*/
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
ret = NM_ACT_STAGE_RETURN_FAILURE;
*chain_up = TRUE;
}
*config = real_config;
return ret;
}
static NMActStageReturn
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
gboolean may_fail = FALSE, chain_up = FALSE;
NMActStageReturn ret;
req = nm_device_get_act_request (dev);
g_assert (req);
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)
may_fail = nm_setting_ip4_config_get_may_fail (s_ip4);
ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason);
if (chain_up)
ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (dev, config, reason);
return ret;
}
static NMActStageReturn
real_act_stage4_ip6_config_timeout (NMDevice *dev,
NMIP6Config **config,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMConnection *connection;
NMSettingIP6Config *s_ip6;
gboolean may_fail = FALSE, chain_up = FALSE;
NMActStageReturn ret;
req = nm_device_get_act_request (dev);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6)
may_fail = nm_setting_ip6_config_get_may_fail (s_ip6);
ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason);
if (chain_up)
ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (dev, config, reason);
return ret;
}
static void
activation_success_handler (NMDevice *dev)
{
@@ -3725,6 +3770,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
parent_class->act_stage2_config = real_act_stage2_config;
parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
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;
parent_class->deactivate_quickly = real_deactivate_quickly;
parent_class->can_interrupt_activation = real_can_interrupt_activation;

View File

@@ -177,6 +177,11 @@ static NMActStageReturn dhcp6_start (NMDevice *self,
guint32 dhcp_opt,
NMDeviceStateReason *reason);
static void addrconf6_cleanup (NMDevice *self);
static void dhcp6_cleanup (NMDevice *self, gboolean stop);
static void dhcp4_cleanup (NMDevice *self, gboolean stop);
static void
device_interface_init (NMDeviceInterface *device_interface_class)
{
@@ -574,6 +579,35 @@ activation_source_schedule (NMDevice *self, GSourceFunc func, int family)
}
}
gboolean
nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6)
{
NMActRequest *req;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
g_return_val_if_fail (self != NULL, TRUE);
req = nm_device_get_act_request (self);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
/* 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);
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);
if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4))
return TRUE;
}
return FALSE;
}
static void
ip6_addrconf_complete (NMIP6Manager *ip6_manager,
int ifindex,
@@ -1318,9 +1352,12 @@ dhcp_state_changed (NMDHCPClient *client,
nm_dhcp4_config_reset (priv->dhcp4_config);
/* dhclient quit and can't get/renew a lease; so kill the connection */
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DHCP_FAILED);
else if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) {
if (ipv6)
nm_device_activate_schedule_stage4_ip6_config_timeout (device);
else
nm_device_activate_schedule_stage4_ip4_config_timeout (device);
} else if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
break;
case DHC_STOP:
@@ -1797,8 +1834,7 @@ nm_device_activate_stage4_ip4_config_get (gpointer user_data)
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))
{
else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
@@ -1852,9 +1888,12 @@ real_act_stage4_ip4_config_timeout (NMDevice *self,
/* Notify of invalid DHCP4 config object */
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP4_CONFIG);
/* DHCP failed; connection must fail */
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
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;
}
@@ -1882,17 +1921,18 @@ nm_device_activate_stage4_ip4_config_timeout (gpointer user_data)
iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &ip4_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
} else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) {
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_assert (ip4_config);
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
if (ip4_config) {
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
}
nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET);
@@ -2125,11 +2165,15 @@ real_act_stage4_ip6_config_timeout (NMDevice *self,
g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
/* Notify of invalid DHCP6 config object */
/* Notify of invalid DHCP4 config object */
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP6_CONFIG);
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
if (nm_device_ip_config_should_fail (self, TRUE)) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@@ -2157,17 +2201,18 @@ nm_device_activate_stage4_ip6_config_timeout (gpointer user_data)
iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &ip6_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
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_assert (ip6_config);
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG, ip6_config);
if (ip6_config) {
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG, ip6_config);
}
nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET6);