Commit e8bed13a authored by stevenjb@chromium.org's avatar stevenjb@chromium.org

Detect user initiated network connection failures.

This also recognizes additional Shill authentication errors.

BUG=168056


Review URL: https://chromiumcodereview.appspot.com/11824046

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176017 0039d316-1c4b-4281-b951-d872f2087c98
parent 692a806c
......@@ -838,6 +838,9 @@ ConnectionError NativeNetworkParser::ParseError(const std::string& error) {
{ flimflam::kErrorIpsecPskAuthFailed, ERROR_IPSEC_PSK_AUTH_FAILED },
{ flimflam::kErrorIpsecCertAuthFailed, ERROR_IPSEC_CERT_AUTH_FAILED },
{ flimflam::kErrorPppAuthFailed, ERROR_PPP_AUTH_FAILED },
{ shill::kErrorEapAuthenticationFailed, ERROR_EAP_AUTHENTICATION_FAILED },
{ shill::kErrorEapLocalTlsFailed, ERROR_EAP_LOCAL_TLS_FAILED },
{ shill::kErrorEapRemoteTlsFailed, ERROR_EAP_REMOTE_TLS_FAILED },
};
CR_DEFINE_STATIC_LOCAL(EnumMapper<ConnectionError>, parser,
(table, arraysize(table), ERROR_NO_ERROR));
......
......@@ -233,6 +233,14 @@ enum ConnectionState {
STATE_CONNECT_REQUESTED = 11, // Chrome only state
};
// Chrome only state set for user initiated connection attempts.
enum UserConnectState {
USER_CONNECT_NONE = 0,
USER_CONNECT_STARTED = 1,
USER_CONNECT_CONNECTED = 2,
USER_CONNECT_FAILED = 3
};
// Network enums (see flimflam/include/network.h)
enum NetworkTechnology {
NETWORK_TECHNOLOGY_UNKNOWN = 0,
......@@ -327,6 +335,9 @@ enum ConnectionError {
ERROR_IPSEC_PSK_AUTH_FAILED = 15,
ERROR_IPSEC_CERT_AUTH_FAILED = 16,
ERROR_PPP_AUTH_FAILED = 17,
ERROR_EAP_AUTHENTICATION_FAILED = 18,
ERROR_EAP_LOCAL_TLS_FAILED = 19,
ERROR_EAP_REMOTE_TLS_FAILED = 20,
ERROR_UNKNOWN = 255
};
......
......@@ -218,7 +218,7 @@ Network::Network(const std::string& service_path,
: state_(STATE_UNKNOWN),
error_(ERROR_NO_ERROR),
connectable_(true),
connection_started_(false),
user_connect_state_(USER_CONNECT_NONE),
is_active_(false),
priority_(kPriorityNotSet),
auto_connect_(false),
......@@ -311,22 +311,32 @@ void Network::SetState(ConnectionState new_state) {
error_ = ERROR_UNKNOWN;
}
}
} else if (new_state == STATE_IDLE && IsConnectingState(old_state)
&& connection_started()) {
if (user_connect_state() == USER_CONNECT_STARTED)
set_user_connect_state(USER_CONNECT_FAILED);
} else if (new_state == STATE_IDLE && IsConnectingState(old_state) &&
user_connect_state() == USER_CONNECT_STARTED) {
// If we requested a connect and never went through a connected state,
// treat it as a failure.
VLOG(1) << service_path() << ": Inferring Failure state.";
notify_failure_ = true;
error_ = ERROR_UNKNOWN;
if (user_connect_state() == USER_CONNECT_STARTED)
set_user_connect_state(USER_CONNECT_FAILED);
} else if (new_state != STATE_UNKNOWN) {
notify_failure_ = false;
// State changed, so refresh IP address.
InitIPAddress();
if (user_connect_state() == USER_CONNECT_STARTED) {
if (IsConnectedState(new_state)) {
set_user_connect_state(USER_CONNECT_CONNECTED);
} else if (!IsConnectingState(new_state)) {
LOG(WARNING) << "Connection started and State -> " << GetStateString();
set_user_connect_state(USER_CONNECT_FAILED);
}
}
}
VLOG(1) << name() << ".State [" << service_path() << "]: " << GetStateString()
<< " (was: " << ConnectionStateString(old_state) << ")";
if (!IsConnectingState(new_state) && new_state != STATE_UNKNOWN)
set_connection_started(false);
}
void Network::SetError(ConnectionError error) {
......@@ -492,6 +502,9 @@ std::string Network::GetErrorString() const {
return l10n_util::GetStringUTF8(
IDS_CHROMEOS_NETWORK_ERROR_IPSEC_CERT_AUTH_FAILED);
case ERROR_PPP_AUTH_FAILED:
case ERROR_EAP_AUTHENTICATION_FAILED:
case ERROR_EAP_LOCAL_TLS_FAILED:
case ERROR_EAP_REMOTE_TLS_FAILED:
return l10n_util::GetStringUTF8(
IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED);
case ERROR_UNKNOWN:
......@@ -1222,18 +1235,32 @@ bool WifiNetwork::IsPassphraseRequired() const {
if (encryption_ == SECURITY_NONE)
return false;
// A connection failure might be due to a bad passphrase.
if (error() == ERROR_BAD_PASSPHRASE || error() == ERROR_BAD_WEPKEY ||
error() == ERROR_UNKNOWN)
if (error() == ERROR_BAD_PASSPHRASE ||
error() == ERROR_BAD_WEPKEY ||
error() == ERROR_PPP_AUTH_FAILED ||
error() == ERROR_EAP_LOCAL_TLS_FAILED ||
error() == ERROR_EAP_REMOTE_TLS_FAILED ||
error() == ERROR_EAP_AUTHENTICATION_FAILED ||
error() == ERROR_CONNECT_FAILED ||
error() == ERROR_UNKNOWN) {
VLOG(1) << "Authentication Error: " << GetErrorString();
return true;
// For 802.1x networks, configuration is required if connectable is false
// unless we're using a certificate pattern.
if (encryption_ == SECURITY_8021X) {
if (eap_method_ != EAP_METHOD_TLS ||
client_cert_type() != CLIENT_CERT_TYPE_PATTERN)
return !connectable();
}
// If the user initiated a connection and it failed, request credentials in
// case it is a credentials error and Shill was unable to detect it.
if (user_connect_state() == USER_CONNECT_FAILED)
return true;
// WEP/WPA/RSN and PSK networks rely on the PassphraseRequired property.
if (encryption_ != SECURITY_8021X)
return passphrase_required_;
// For 802.1x networks, if we are using a certificate pattern we do not
// need any credentials.
if (eap_method_ == EAP_METHOD_TLS &&
client_cert_type() == CLIENT_CERT_TYPE_PATTERN) {
return false;
}
return passphrase_required_;
// Connectable will be false if 802.1x credentials are not set
return !connectable();
}
bool WifiNetwork::RequiresUserProfile() const {
......
......@@ -361,7 +361,10 @@ class Network {
bool connected() const { return IsConnectedState(state_); }
bool connecting_or_connected() const { return connecting() || connected(); }
// True when a user-initiated connection attempt is in progress
bool connection_started() const { return connection_started_; }
bool connection_started() const {
return user_connect_state_ == USER_CONNECT_STARTED;
}
UserConnectState user_connect_state() const { return user_connect_state_; }
bool failed() const { return state_ == STATE_FAILURE; }
bool disconnected() const { return IsDisconnectedState(state_); }
bool ready() const { return state_ == STATE_READY; }
......@@ -562,7 +565,9 @@ class Network {
state_ = STATE_IDLE;
}
void set_connectable(bool connectable) { connectable_ = connectable; }
void set_connection_started(bool started) { connection_started_ = started; }
void set_user_connect_state(UserConnectState user_connect_state) {
user_connect_state_ = user_connect_state;
}
void set_is_active(bool is_active) { is_active_ = is_active; }
void set_added(bool added) { added_ = added; }
void set_auto_connect(bool auto_connect) { auto_connect_ = auto_connect; }
......@@ -601,7 +606,7 @@ class Network {
ConnectionState state_;
ConnectionError error_;
bool connectable_;
bool connection_started_;
UserConnectState user_connect_state_;
bool is_active_;
int priority_; // determines order in network list.
bool auto_connect_;
......
......@@ -743,7 +743,7 @@ void NetworkLibraryImplBase::NetworkConnectStart(
network->set_connecting();
// Distinguish between user-initiated connection attempts
// and auto-connect.
network->set_connection_started(true);
network->set_user_connect_state(USER_CONNECT_STARTED);
NotifyNetworkManagerChanged(true); // Forced update.
VLOG(1) << "Requesting connect to network: " << network->name()
<< " profile type: " << profile_type;
......
......@@ -406,7 +406,7 @@ void NetworkLibraryImplStub::ConnectToNetwork(Network* network) {
// Set connected state.
network->set_connected();
network->set_connection_started(false);
network->set_user_connect_state(USER_CONNECT_CONNECTED);
// Make the connected network the highest priority network.
// Set all other networks of the same type to disconnected + inactive;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment