[PATCH v2] station: cancel quick scans on Connect()
by James Prestwood
At some point the non-interactive client tests began failing.
This was due to a bug in station where it would transition from
'connected' to 'autoconnect' due to a failed scan request. This
happened because a quick scan got scheduled during an ongoing
scan, then a Connect() gets issued. The work queue treats the
Connect as a priority so it delays the quick scan until after the
connection succeeds. This results in a failed quick scan which
IWD does not expect to happen when in a 'connected' state. This
failed scan actually triggers a state transition which then
gets IWD into a strange state where its connected from the
kernel point of view but does not think it is:
src/station.c:station_connect_cb() 13, result: 0
src/station.c:station_enter_state() Old State: connecting, new state: connected
src/wiphy.c:wiphy_radio_work_done() Work item 6 done
src/wiphy.c:wiphy_radio_work_next() Starting work item 5
src/station.c:station_quick_scan_triggered() Quick scan trigger failed: -95
src/station.c:station_enter_state() Old State: connected, new state: autoconnect_full
To fix this IWD should simply cancel any pending quick scans
if/when a Connect() call comes in.
---
src/station.c | 6 ++++++
1 file changed, 6 insertions(+)
v2:
* Rather than handle inside the triggered callback we can
just cancel the scan when the connection is attempted.
This prevents unneeded kernel round trips as well.
diff --git a/src/station.c b/src/station.c
index b600f37e..55368472 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2539,6 +2539,12 @@ void station_connect_network(struct station *station, struct network *network,
dbus_error_failed(station->hidden_pending));
}
+ if (station->quick_scan_id) {
+ scan_cancel(netdev_get_wdev_id(station->netdev),
+ station->quick_scan_id);
+ station->quick_scan_id = 0;
+ }
+
if (station_is_busy(station)) {
station_disconnect_onconnect(station, network, bss, message);
--
2.26.2
1 year, 3 months
[PATCH 1/4] test-runner: fix verbose arguments as single string
by James Prestwood
The verbose arguments come in from the QEMU command line as a
single string. This should have been split into an array immediately
but was not. This led to issues like hostapd debug being enabled
when "-v hostapd_cli" was passed in.
---
tools/test-runner | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/test-runner b/tools/test-runner
index 3ba49953..fba589e3 100755
--- a/tools/test-runner
+++ b/tools/test-runner
@@ -1212,6 +1212,9 @@ def run_tests():
if not args.debug:
sys.stdout = open(os.devnull, 'w')
+ if args.verbose != []:
+ args.verbose = args.verbose.split(',')
+
os.environ['PATH'] = '%s/src' % args.testhome
os.environ['PATH'] += ':%s/tools' % args.testhome
os.environ['PATH'] += ':%s/client' % args.testhome
--
2.26.2
1 year, 3 months
[PATCH 1/7] eap-tls: Drop EAP-{TTLS,PEAP}-Client{Cert,Key}
by Andrew Zaborowski
As requested move the client certificate and private key loading from
eap-tls-common.c to eap-tls.c. No man page change needed because those
two settings weren't documented in it in the first place.
---
src/eap-tls-common.c | 239 ++++---------------------------------------
src/eap-tls-common.h | 9 ++
src/eap-tls.c | 237 ++++++++++++++++++++++++++++++++++++++++--
3 files changed, 260 insertions(+), 225 deletions(-)
diff --git a/src/eap-tls-common.c b/src/eap-tls-common.c
index 68e2a10c..164115d8 100644
--- a/src/eap-tls-common.c
+++ b/src/eap-tls-common.c
@@ -867,8 +867,8 @@ static struct l_queue *eap_tls_load_ca_cert(struct l_settings *settings,
return l_pem_load_certificate_list_from_data(pem, strlen(pem));
}
-static struct l_certchain *eap_tls_load_client_cert(struct l_settings *settings,
- const char *value)
+struct l_certchain *eap_tls_load_client_cert(struct l_settings *settings,
+ const char *value)
{
const char *pem;
@@ -882,7 +882,7 @@ static struct l_certchain *eap_tls_load_client_cert(struct l_settings *settings,
return l_pem_load_certificate_chain_from_data(pem, strlen(pem));
}
-static struct l_key *eap_tls_load_priv_key(struct l_settings *settings,
+struct l_key *eap_tls_load_priv_key(struct l_settings *settings,
const char *value, const char *passphrase,
bool *is_encrypted)
{
@@ -905,186 +905,23 @@ int eap_tls_common_settings_check(struct l_settings *settings,
struct l_queue **out_missing)
{
char setting_key[72];
- char client_cert_setting[72];
- char passphrase_setting[72];
- struct l_queue *cacerts = NULL;
- struct l_certchain *cert = NULL;
- struct l_key *priv_key = NULL;
- bool is_encrypted, is_public;
- int ret;
- const char *error_str;
- size_t size;
- ssize_t result;
- uint8_t *encrypted, *decrypted;
- struct l_key *pub_key;
+ bool have_cacerts = false;
const char *domain_mask_str;
-
L_AUTO_FREE_VAR(char *, value);
- L_AUTO_FREE_VAR(char *, client_cert) = NULL;
- L_AUTO_FREE_VAR(char *, passphrase) = NULL;
snprintf(setting_key, sizeof(setting_key), "%sCACert", prefix);
value = l_settings_get_string(settings, "Security", setting_key);
if (value) {
- cacerts = eap_tls_load_ca_cert(settings, value);
+ struct l_queue *cacerts = eap_tls_load_ca_cert(settings, value);
if (!cacerts) {
l_error("Failed to load %s", value);
return -EIO;
}
- }
-
- snprintf(client_cert_setting, sizeof(client_cert_setting),
- "%sClientCert", prefix);
- client_cert = l_settings_get_string(settings, "Security",
- client_cert_setting);
- if (client_cert) {
- cert = eap_tls_load_client_cert(settings, client_cert);
-
- if (!cert) {
- l_error("Failed to load %s", client_cert);
- ret = -EIO;
- goto done;
- }
-
- /*
- * Sanity check that certchain provided is valid. We do not
- * verify the certchain against the provided CA, since the
- * CA that issued user certificates might be different from
- * the one that is used to verify the peer
- */
- if (!l_certchain_verify(cert, NULL, &error_str)) {
- l_error("Certificate chain %s fails verification: %s",
- client_cert, error_str);
- ret = -EINVAL;
- goto done;
- }
- }
-
- l_free(value);
- snprintf(setting_key, sizeof(setting_key), "%sClientKey", prefix);
- value = l_settings_get_string(settings, "Security", setting_key);
-
- if (value && !client_cert) {
- l_error("%s present but no client certificate (%s)",
- setting_key, client_cert_setting);
- ret = -ENOENT;
- goto done;
- } else if (!value && client_cert) {
- l_error("%s present but no client private key (%s)",
- client_cert_setting, setting_key);
- ret = -ENOENT;
- goto done;
- }
-
- snprintf(passphrase_setting, sizeof(passphrase_setting),
- "%sClientKeyPassphrase", prefix);
- passphrase = l_settings_get_string(settings, "Security",
- passphrase_setting);
-
- if (!passphrase) {
- const struct eap_secret_info *secret;
-
- secret = l_queue_find(secrets, eap_secret_info_match,
- passphrase_setting);
- if (secret)
- passphrase = l_strdup(secret->value);
- }
-
- if (!value) {
- if (passphrase) {
- l_error("%s present but no client private key"
- " value set (%s)", passphrase_setting,
- setting_key);
- ret = -ENOENT;
- goto done;
- }
-
- ret = 0;
- goto done;
- }
-
- priv_key = eap_tls_load_priv_key(settings, value, passphrase,
- &is_encrypted);
-
- if (!priv_key) {
- if (!is_encrypted) {
- l_error("Error loading client private key %s", value);
- ret = -EIO;
- goto done;
- }
-
- if (passphrase) {
- l_error("Error loading encrypted client private key %s",
- value);
- ret = -EACCES;
- goto done;
- }
-
- /*
- * We've got an encrypted key and passphrase was not saved
- * in the network settings, need to request the passphrase.
- */
- eap_append_secret(out_missing,
- EAP_SECRET_LOCAL_PKEY_PASSPHRASE,
- passphrase_setting, NULL, value,
- EAP_CACHE_TEMPORARY);
- ret = 0;
- goto done;
- }
-
- if (passphrase && !is_encrypted) {
- l_error("%s present but client private key %s is not encrypted",
- passphrase_setting, value);
- ret = -ENOENT;
- goto done;
- }
-
- if (!l_key_get_info(priv_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
- &size, &is_public) || is_public) {
- l_error("%s is not a private key or l_key_get_info fails",
- value);
- ret = -EINVAL;
- goto done;
- }
-
- size /= 8;
- encrypted = alloca(size);
- decrypted = alloca(size);
-
- pub_key = l_cert_get_pubkey(l_certchain_get_leaf(cert));
- if (!pub_key) {
- l_error("l_cert_get_pubkey fails for %s", client_cert);
- ret = -EIO;
- goto done;
- }
-
- result = l_key_encrypt(pub_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
- "", encrypted, 1, size);
- l_key_free(pub_key);
-
- if (result != (ssize_t) size) {
- l_error("l_key_encrypt fails with %s: %s", client_cert,
- strerror(-result));
- ret = result;
- goto done;
- }
-
- result = l_key_decrypt(priv_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
- encrypted, decrypted, size, size);
- if (result < 0) {
- l_error("l_key_decrypt fails with %s: %s", value,
- strerror(-result));
- ret = result;
- goto done;
- }
-
- if (result != 1 || decrypted[0] != 0) {
- l_error("Private key %s does not match certificate %s", value,
- client_cert);
- ret = -EINVAL;
- goto done;
+ l_queue_destroy(cacerts,
+ (l_queue_destroy_func_t) l_cert_free);
+ have_cacerts = true;
}
/*
@@ -1097,23 +934,12 @@ int eap_tls_common_settings_check(struct l_settings *settings,
prefix);
domain_mask_str = l_settings_get_value(settings, "Security",
setting_key);
- if (domain_mask_str && !cacerts) {
+ if (domain_mask_str && !have_cacerts) {
l_error("%s was set but no CA Certificates given", setting_key);
- ret = -EINVAL;
- goto done;
+ return -EINVAL;
}
- ret = 0;
-done:
- l_queue_destroy(cacerts,
- (l_queue_destroy_func_t) l_cert_free);
- l_certchain_free(cert);
- l_key_free(priv_key);
-
- if (passphrase)
- explicit_bzero(passphrase, strlen(passphrase));
-
- return ret;
+ return 0;
}
bool eap_tls_common_settings_load(struct eap_state *eap,
@@ -1124,8 +950,8 @@ bool eap_tls_common_settings_load(struct eap_state *eap,
struct eap_tls_state *eap_tls;
char setting_key[72];
char *domain_mask_str;
+
L_AUTO_FREE_VAR(char *, value) = NULL;
- L_AUTO_FREE_VAR(char *, passphrase) = NULL;
eap_tls = l_new(struct eap_tls_state, 1);
@@ -1143,37 +969,6 @@ bool eap_tls_common_settings_load(struct eap_state *eap,
}
}
- l_free(value);
-
- snprintf(setting_key, sizeof(setting_key), "%sClientCert", prefix);
- value = l_settings_get_string(settings, "Security", setting_key);
- if (value) {
- eap_tls->client_cert = eap_tls_load_client_cert(settings,
- value);
- if (!eap_tls->client_cert) {
- l_error("Could not load ClientCert %s", value);
- goto load_error;
- }
- }
-
- l_free(value);
-
- snprintf(setting_key, sizeof(setting_key), "%sClientKeyPassphrase",
- prefix);
- passphrase = l_settings_get_string(settings, "Security", setting_key);
-
- snprintf(setting_key, sizeof(setting_key), "%sClientKey", prefix);
- value = l_settings_get_string(settings, "Security", setting_key);
- if (value) {
- eap_tls->client_key = eap_tls_load_priv_key(settings, value,
- passphrase,
- NULL);
- if (!eap_tls->client_key) {
- l_error("Could not load ClientKey %s", value);
- goto load_error;
- }
- }
-
snprintf(setting_key, sizeof(setting_key), "%sServerDomainMask",
prefix);
domain_mask_str = l_settings_get_string(settings, "Security",
@@ -1194,6 +989,16 @@ load_error:
return false;
}
+void eap_tls_common_set_keys(struct eap_state *eap,
+ struct l_certchain *client_cert,
+ struct l_key *client_key)
+{
+ struct eap_tls_state *eap_tls = eap_get_data(eap);
+
+ eap_tls->client_cert = client_cert;
+ eap_tls->client_key = client_key;
+}
+
void eap_tls_common_set_completed(struct eap_state *eap)
{
struct eap_tls_state *eap_tls = eap_get_data(eap);
diff --git a/src/eap-tls-common.h b/src/eap-tls-common.h
index 88cac244..81c84c3e 100644
--- a/src/eap-tls-common.h
+++ b/src/eap-tls-common.h
@@ -48,6 +48,12 @@ void eap_tls_common_handle_request(struct eap_state *eap,
void eap_tls_common_handle_retransmit(struct eap_state *eap,
const uint8_t *pkt, size_t len);
+struct l_certchain *eap_tls_load_client_cert(struct l_settings *settings,
+ const char *value);
+struct l_key *eap_tls_load_priv_key(struct l_settings *settings,
+ const char *value, const char *passphrase,
+ bool *is_encrypted);
+
int eap_tls_common_settings_check(struct l_settings *settings,
struct l_queue *secrets,
const char *prefix,
@@ -56,6 +62,9 @@ bool eap_tls_common_settings_load(struct eap_state *eap,
struct l_settings *settings, const char *prefix,
const struct eap_tls_variant_ops *variant_ops,
void *variant_data);
+void eap_tls_common_set_keys(struct eap_state *eap,
+ struct l_certchain *client_cert,
+ struct l_key *client_key);
void eap_tls_common_send_empty_response(struct eap_state *eap);
enum eap_tls_version eap_tls_common_get_negotiated_version(
diff --git a/src/eap-tls.c b/src/eap-tls.c
index 136f5943..88e79147 100644
--- a/src/eap-tls.c
+++ b/src/eap-tls.c
@@ -60,17 +60,205 @@ static bool eap_tls_tunnel_ready(struct eap_state *eap,
return true;
}
+static int eap_tls_check_keys_match(struct l_key *priv_key, struct l_cert *cert,
+ const char *key_name,
+ const char *cert_name)
+{
+ bool is_public;
+ size_t size;
+ ssize_t result;
+ uint8_t *encrypted, *decrypted;
+ struct l_key *pub_key;
+
+ if (!l_key_get_info(priv_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
+ &size, &is_public) || is_public) {
+ l_error("%s is not a private key or l_key_get_info fails",
+ key_name);
+ return -EINVAL;
+ }
+
+ size /= 8;
+ encrypted = alloca(size);
+ decrypted = alloca(size);
+
+ pub_key = l_cert_get_pubkey(cert);
+ if (!pub_key) {
+ l_error("l_cert_get_pubkey fails for %s", cert_name);
+ return -EIO;
+ }
+
+ result = l_key_encrypt(pub_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
+ "", encrypted, 1, size);
+ l_key_free(pub_key);
+
+ if (result != (ssize_t) size) {
+ l_error("l_key_encrypt fails with %s: %s", cert_name,
+ strerror(-result));
+ return result;
+ }
+
+ result = l_key_decrypt(priv_key, L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
+ encrypted, decrypted, size, size);
+ if (result < 0) {
+ l_error("l_key_decrypt fails with %s: %s", key_name,
+ strerror(-result));
+ return result;
+ }
+
+ if (result != 1 || decrypted[0] != 0) {
+ l_error("Private key %s does not match certificate %s", key_name,
+ cert_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int eap_tls_settings_check(struct l_settings *settings,
struct l_queue *secrets,
const char *prefix,
struct l_queue **out_missing)
{
- char tls_prefix[72];
+ char tls_prefix[32];
+ char passphrase_setting[72];
+ char client_cert_setting[72];
+ char priv_key_setting[72];
+ L_AUTO_FREE_VAR(char *, passphrase) = NULL;
+ L_AUTO_FREE_VAR(char *, client_cert_value) = NULL;
+ L_AUTO_FREE_VAR(char *, priv_key_value) = NULL;
+ struct l_certchain *client_cert = NULL;
+ struct l_key *priv_key = NULL;
+ const char *error_str;
+ bool is_encrypted;
+ int ret;
snprintf(tls_prefix, sizeof(tls_prefix), "%sTLS-", prefix);
- return eap_tls_common_settings_check(settings, secrets, tls_prefix,
- out_missing);
+ ret = eap_tls_common_settings_check(settings, secrets, tls_prefix,
+ out_missing);
+ if (ret < 0)
+ goto done;
+
+ snprintf(client_cert_setting, sizeof(client_cert_setting),
+ "%sClientCert", tls_prefix);
+ client_cert_value = l_settings_get_string(settings, "Security",
+ client_cert_setting);
+
+ snprintf(priv_key_setting, sizeof(priv_key_setting), "%sClientKey",
+ tls_prefix);
+ priv_key_value = l_settings_get_string(settings, "Security",
+ priv_key_setting);
+
+ snprintf(passphrase_setting, sizeof(passphrase_setting),
+ "%sClientKeyPassphrase", tls_prefix);
+ passphrase = l_settings_get_string(settings, "Security",
+ passphrase_setting);
+
+ if (!passphrase) {
+ const struct eap_secret_info *secret;
+
+ secret = l_queue_find(secrets, eap_secret_info_match,
+ passphrase_setting);
+ if (secret)
+ passphrase = l_strdup(secret->value);
+ }
+
+ /*
+ * Check whether the combination of settings that are present/missing
+ * makes sense before validating each setting.
+ */
+ if (priv_key_value && !client_cert_value) {
+ l_error("%s present but no client certificate (%s)",
+ priv_key_setting, client_cert_setting);
+ ret = -ENOENT;
+ goto done;
+ } else if (!priv_key_value && client_cert) {
+ l_error("%s present but no client private key (%s)",
+ client_cert_setting, priv_key_setting);
+ ret = -ENOENT;
+ goto done;
+ }
+
+ if (!priv_key_value) {
+ if (passphrase) {
+ l_error("%s present but no client private key set (%s)",
+ passphrase_setting, priv_key_setting);
+ ret = -ENOENT;
+ goto done;
+ }
+
+ ret = 0;
+ goto done;
+ }
+
+ client_cert = eap_tls_load_client_cert(settings, client_cert_value);
+ if (!client_cert) {
+ l_error("Failed to load %s", client_cert_value);
+ ret = -EIO;
+ goto done;
+ }
+
+ /*
+ * Sanity check that certchain provided is valid. We do not verify
+ * the certchain against the provided CA since the CA that issued
+ * user certificates might be different from the one that is used
+ * to verify the peer.
+ */
+ if (!l_certchain_verify(client_cert, NULL, &error_str)) {
+ l_error("Certificate chain %s fails verification: %s",
+ client_cert_value, error_str);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ priv_key = eap_tls_load_priv_key(settings, priv_key_value, passphrase,
+ &is_encrypted);
+ if (!priv_key) {
+ if (!is_encrypted) {
+ l_error("Error loading client private key %s",
+ priv_key_value);
+ ret = -EIO;
+ goto done;
+ }
+
+ if (passphrase) {
+ l_error("Error loading encrypted client private key %s",
+ priv_key_value);
+ ret = -EACCES;
+ goto done;
+ }
+
+ /*
+ * We've got an encrypted key and passphrase was not saved
+ * in the network settings, need to request the passphrase.
+ */
+ eap_append_secret(out_missing,
+ EAP_SECRET_LOCAL_PKEY_PASSPHRASE,
+ passphrase_setting, NULL,
+ priv_key_value, EAP_CACHE_TEMPORARY);
+ ret = 0;
+ goto done;
+ }
+
+ if (passphrase && !is_encrypted) {
+ l_error("%s present but client private key %s is not encrypted",
+ passphrase_setting, priv_key_value);
+ ret = -ENOENT;
+ goto done;
+ }
+
+ ret = eap_tls_check_keys_match(priv_key,
+ l_certchain_get_leaf(client_cert),
+ priv_key_value, client_cert_value);
+
+done:
+ l_certchain_free(client_cert);
+ l_key_free(priv_key);
+
+ if (passphrase)
+ explicit_bzero(passphrase, strlen(passphrase));
+
+ return ret;
}
static const struct eap_tls_variant_ops eap_tls_ops = {
@@ -81,16 +269,49 @@ static bool eap_tls_settings_load(struct eap_state *eap,
struct l_settings *settings,
const char *prefix)
{
- char setting_key_prefix[72];
+ char tls_prefix[32];
+ char setting_key[72];
+ struct l_certchain *client_cert = NULL;
+ struct l_key *client_key = NULL;
- snprintf(setting_key_prefix, sizeof(setting_key_prefix), "%sTLS-",
- prefix);
+ L_AUTO_FREE_VAR(char *, value) = NULL;
+ L_AUTO_FREE_VAR(char *, passphrase) = NULL;
- if (!eap_tls_common_settings_load(eap, settings, setting_key_prefix,
- &eap_tls_ops, NULL))
+ snprintf(tls_prefix, sizeof(tls_prefix), "%sTLS-", prefix);
+
+ if (!eap_tls_common_settings_load(eap, settings, tls_prefix,
+ &eap_tls_ops, NULL))
return false;
+ snprintf(setting_key, sizeof(setting_key), "%sClientKeyPassphrase",
+ tls_prefix);
+ passphrase = l_settings_get_string(settings, "Security", setting_key);
+
+ snprintf(setting_key, sizeof(setting_key), "%sClientCert", tls_prefix);
+ value = l_settings_get_string(settings, "Security", setting_key);
+ if (value) {
+ client_cert = eap_tls_load_client_cert(settings, value);
+ if (!client_cert)
+ goto load_error;
+ }
+
+ l_free(value);
+
+ snprintf(setting_key, sizeof(setting_key), "%sClientKey", tls_prefix);
+ value = l_settings_get_string(settings, "Security", setting_key);
+ if (value) {
+ client_key = eap_tls_load_priv_key(settings, value,
+ passphrase, NULL);
+ if (!client_key)
+ goto load_error;
+ }
+
+ eap_tls_common_set_keys(eap, client_cert, client_key);
return true;
+
+load_error:
+ eap_tls_common_state_free(eap);
+ return false;
}
static struct eap_method eap_tls = {
--
2.27.0
1 year, 3 months
[PATCH] auto-t: fix wait_for_object_condition
by James Prestwood
After the re-write this was broken and not noticed until
recently. The issue appeared to be that the GLib timeout
callback retained no context of local variables. Previously
_wait_timed_out was set as a class variable, but this was
removed so multiple IWD instances could work. Without
_wait_timed_out being a class variable the GLib timeout
setting it had no effect on the wait loop.
To fix this we can set _wait_timed_out on the object being
passed in. This is preserved in the GLib timeout callback
and setting it gets honored in the wait loop.
---
autotests/util/iwd.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py
index 9e653575..4fa26517 100755
--- a/autotests/util/iwd.py
+++ b/autotests/util/iwd.py
@@ -1009,9 +1009,10 @@ class IWD(AsyncOpAbstract):
@staticmethod
def _wait_for_object_condition(obj, condition_str, max_wait = 50):
- _wait_timed_out = False
+ obj._wait_timed_out = False
+
def wait_timeout_cb():
- _wait_timed_out = True
+ obj._wait_timed_out = True
return False
try:
@@ -1019,12 +1020,12 @@ class IWD(AsyncOpAbstract):
context = ctx.mainloop.get_context()
while not eval(condition_str):
context.iteration(may_block=True)
- if _wait_timed_out and ctx.args.gdb == None:
+ if obj._wait_timed_out and ctx.args.gdb == None:
raise TimeoutError('[' + condition_str + ']'\
' condition was not met in '\
+ str(max_wait) + ' sec')
finally:
- if not _wait_timed_out:
+ if not obj._wait_timed_out:
GLib.source_remove(timeout)
def wait_for_object_condition(self, *args, **kwargs):
--
2.26.2
1 year, 3 months
[PATCH 1/3] station: retry roaming unless notified of a high RSSI
by Alvin Šipraga
Following a successful roaming sequence, schedule another attempt unless
the driver has sent a high RSSI notification. This makes the behaviour
analogous to a failed roaming attempt where we remained connected to the
same BSS.
This makes iwd compatible with wireless drivers which do not necessarily
send out a duplicate low RSSI notification upon reassociation. Without
this change, iwd risks getting indefinitely stuck to a BSS with low
signal strength, even though a better BSS might later become available.
In the case of a high RSSI notification, the minimum roam time will also
be reset to zero. This preserves the original behaviour in the case
where a high RSSI notification is processed after station_roamed().
Doing so also gives a chance for faster roaming action in the following
example scenario:
1. RSSI LOW
2. schedule roam in 5 seconds
(5 seconds pass)
3. try roaming
4. roaming fails, same BSS
5. schedule roam in 60 seconds
(20 seconds pass)
6. RSSI HIGH
7. cancel scheduled roam
(20 seconds pass)
8. RSSI LOW
9. schedule roam in 5 seconds or 20 seconds?
By resetting the minimum roam time, we can avoid waiting 20 seconds when
the station may have moved considerably. And since the high/low RSSI
notifications are configured with a hysteresis, we should still be
protected against too frequent spurious roaming attempts.
---
src/station.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/station.c b/src/station.c
index c65fc0cc..2e886a73 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1362,13 +1362,14 @@ static int station_roam_scan(struct station *station,
static void station_roamed(struct station *station)
{
+ station->roam_scan_full = false;
+
/*
- * New signal high/low notification should occur on the next
- * beacon from new AP.
+ * Schedule another roaming attempt in case the signal continues to
+ * remain low. A subsequent high signal notification will cancel it.
*/
- station->signal_low = false;
- station->roam_min_time.tv_sec = 0;
- station->roam_scan_full = false;
+ if (station->signal_low)
+ station_roam_timeout_rearm(station, 60);
if (station->netconfig)
netconfig_reconfigure(station->netconfig);
@@ -2227,6 +2228,7 @@ static void station_ok_rssi(struct station *station)
station->roam_trigger_timeout = NULL;
station->signal_low = false;
+ station->roam_min_time.tv_sec = 0;
}
static void station_rssi_level_changed(struct station *station,
--
2.29.2
1 year, 3 months
iwd reconnect issue
by KeithG
I am trying to figure this out, still. Connman has been recently modified
so that it allows iwd to scan and reconnect. I have built and installed the
latest git of connman and am using iwd 1.10 on Arch linux. I have been able
to confirm that this mod to connman seems to work on my Arch installs on
x86 with an Intel wireless AC 7260 card and also a Broadcom brcmsmac. On
the Rpi, though, I am still struggling and am looking for any information
that may help resolve it for the RPi. I am guessing that there may be a
driver issue or something else going on. To that end, I have updated the
driver on the RPi to use the latest brcmfmac driver from cypress
(20200925). Built and installed this driver, so it is as up to date as I
can get. This patched driver supposedly supports wpa3 as well though I have
not yet evaluated that. This driver behaves identically to the older
version on RPi with respect to reconnecting when the SSID radio is
restarted.
When I allow iwd to manage the network configuration and reboot the router
or restart the radio on the router, iwd reconnects almost immediately as
soon as the SSID is visible. If I allow connman to manage it, a reboot of
the router will some (many?) times allow a reconnect. If I restart the
radio on the router, though, it will never reconnect. Looking at the logs
of iwd, it does continue scanning and it does see the SSID I use, but it
never triggers connman to reconnect. If I restart iwd in this state, it
reconnects immediately. I am trying to figure out what is the difference
between the 2 modes: 'router reboot' versus 'radio restart'. I would think
they would appear the same to iwd, but am not certain as the RPi behaves
differently.
There are 2 attached logs from My RPi 3b+ running kernel 5.4.83 with the
latest brcmfmac driver. .
iwd_connman_restart.txt log shows the logs of iwd and connman from boot to
a radio restart and then restarting iwd. I restart the radio and iwd tells
connman that it is disconnected at 11:40:18. Connman then deletes the
addresses and routes and triggers iwd to scan. iwd then scans and finds my
SSID (spg3) many times but never tells connman to reconnect. I then restart
iwd at 11:42:51 and at 11:42:52, I get a "network_connect" event and it
connects. This only happens after I restart iwd even though it scanned and
found my spg3 SSID many times. On the x86 with either of the 2 wifi cards I
have here, it seems to reconnect with this same scenario. On the x86
machines, it gets a station_autoconnect_next after the first scan when it
sees the SSID and tells connman to connect.
iwd_restart.txt shows a similar scenario where I restart the radio, but it
reconnects.
I restart the radio at 11:48:46 and it deletes the address and starts
scanning. At 11:49:47, it gets 'station_autoconnect_next' and initiates a
connection and is connected with routes at 11:49:47.
1 year, 3 months
[PATCH v4 1/8] netdev: move netdev_station_info to diagnostic.h
by James Prestwood
With AP now getting its own diagnostic interface it made sense
to move the netdev_station_info struct definition into its own
header which eventually can be accompanied by utilities in
diagnostic.c. These utilities can then be shared with AP and
station as needed.
---
src/diagnostic.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
src/netdev.c | 23 ++++++++++++-----------
src/netdev.h | 34 ++++-----------------------------
src/station.c | 18 ++++++++++--------
4 files changed, 75 insertions(+), 49 deletions(-)
create mode 100644 src/diagnostic.h
v4:
* Fixed station.c so it complies
diff --git a/src/diagnostic.h b/src/diagnostic.h
new file mode 100644
index 00000000..8292d192
--- /dev/null
+++ b/src/diagnostic.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+enum diagnostic_mcs_type {
+ DIAGNOSTIC_MCS_TYPE_NONE,
+ DIAGNOSTIC_MCS_TYPE_HT,
+ DIAGNOSTIC_MCS_TYPE_VHT,
+ DIAGNOSTIC_MCS_TYPE_HE,
+};
+
+struct diagnostic_station_info {
+ uint8_t addr[6];
+ int8_t cur_rssi;
+
+ enum diagnostic_mcs_type rx_mcs_type;
+ uint32_t rx_bitrate;
+ uint8_t rx_mcs;
+ enum diagnostic_mcs_type tx_mcs_type;
+ uint32_t tx_bitrate;
+ uint8_t tx_mcs;
+
+ uint32_t expected_throughput;
+
+ bool have_cur_rssi : 1;
+ bool have_rx_mcs : 1;
+ bool have_tx_mcs : 1;
+ bool have_rx_bitrate : 1;
+ bool have_tx_bitrate : 1;
+ bool have_expected_throughput : 1;
+};
diff --git a/src/netdev.c b/src/netdev.c
index e3ce270a..a19270c0 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -61,6 +61,7 @@
#include "src/fils.h"
#include "src/auth-proto.h"
#include "src/frame-xchg.h"
+#include "src/diagnostic.h"
#ifndef ENOTSUPP
#define ENOTSUPP 524
@@ -369,7 +370,7 @@ int netdev_set_powered(struct netdev *netdev, bool powered,
}
static bool netdev_parse_bitrate(struct l_genl_attr *attr,
- enum netdev_mcs_type *type_out,
+ enum diagnostic_mcs_type *type_out,
uint32_t *rate_out,
uint8_t *mcs_out)
{
@@ -377,7 +378,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
const void *data;
uint32_t rate = 0;
uint8_t mcs = 0;
- enum netdev_mcs_type mcs_type = NETDEV_MCS_TYPE_NONE;
+ enum diagnostic_mcs_type mcs_type = DIAGNOSTIC_MCS_TYPE_NONE;
while (l_genl_attr_next(attr, &type, &len, &data)) {
switch (type) {
@@ -394,7 +395,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
return false;
mcs = l_get_u8(data);
- mcs_type = NETDEV_MCS_TYPE_HT;
+ mcs_type = DIAGNOSTIC_MCS_TYPE_HT;
break;
@@ -403,7 +404,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
return false;
mcs = l_get_u8(data);
- mcs_type = NETDEV_MCS_TYPE_VHT;
+ mcs_type = DIAGNOSTIC_MCS_TYPE_VHT;
break;
@@ -412,7 +413,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
return false;
mcs = l_get_u8(data);
- mcs_type = NETDEV_MCS_TYPE_HE;
+ mcs_type = DIAGNOSTIC_MCS_TYPE_HE;
break;
}
@@ -424,14 +425,14 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
*type_out = mcs_type;
*rate_out = rate;
- if (mcs_type != NETDEV_MCS_TYPE_NONE)
+ if (mcs_type != DIAGNOSTIC_MCS_TYPE_NONE)
*mcs_out = mcs;
return true;
}
static bool netdev_parse_sta_info(struct l_genl_attr *attr,
- struct netdev_station_info *info)
+ struct diagnostic_station_info *info)
{
uint16_t type, len;
const void *data;
@@ -458,7 +459,7 @@ static bool netdev_parse_sta_info(struct l_genl_attr *attr,
info->have_rx_bitrate = true;
- if (info->rx_mcs_type != NETDEV_MCS_TYPE_NONE)
+ if (info->rx_mcs_type != DIAGNOSTIC_MCS_TYPE_NONE)
info->have_rx_mcs = true;
break;
@@ -474,7 +475,7 @@ static bool netdev_parse_sta_info(struct l_genl_attr *attr,
info->have_tx_bitrate = true;
- if (info->tx_mcs_type != NETDEV_MCS_TYPE_NONE)
+ if (info->tx_mcs_type != DIAGNOSTIC_MCS_TYPE_NONE)
info->have_tx_mcs = true;
break;
@@ -511,7 +512,7 @@ static void netdev_rssi_poll_cb(struct l_genl_msg *msg, void *user_data)
uint16_t type, len;
const void *data;
bool found;
- struct netdev_station_info info;
+ struct diagnostic_station_info info;
uint8_t prev_rssi_level_idx = netdev->cur_rssi_level_idx;
netdev->rssi_poll_cmd_id = 0;
@@ -4156,7 +4157,7 @@ static void netdev_get_station_cb(struct l_genl_msg *msg, void *user_data)
struct l_genl_attr attr, nested;
uint16_t type, len;
const void *data;
- struct netdev_station_info info;
+ struct diagnostic_station_info info;
netdev->get_station_cmd_id = 0;
diff --git a/src/netdev.h b/src/netdev.h
index e7a1c060..d5adcf09 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -27,6 +27,7 @@ struct scan_bss;
struct handshake_state;
struct eapol_sm;
struct mmpdu_header;
+struct diagnostic_station_info;
enum netdev_result {
NETDEV_RESULT_OK,
@@ -114,36 +115,9 @@ typedef void (*netdev_station_watch_func_t)(struct netdev *netdev,
const uint8_t *mac, bool added,
void *user_data);
-enum netdev_mcs_type {
- NETDEV_MCS_TYPE_NONE,
- NETDEV_MCS_TYPE_HT,
- NETDEV_MCS_TYPE_VHT,
- NETDEV_MCS_TYPE_HE,
-};
-
-struct netdev_station_info {
- uint8_t addr[6];
- int8_t cur_rssi;
-
- enum netdev_mcs_type rx_mcs_type;
- uint32_t rx_bitrate;
- uint8_t rx_mcs;
- enum netdev_mcs_type tx_mcs_type;
- uint32_t tx_bitrate;
- uint8_t tx_mcs;
-
- uint32_t expected_throughput;
-
- bool have_cur_rssi : 1;
- bool have_rx_mcs : 1;
- bool have_tx_mcs : 1;
- bool have_rx_bitrate : 1;
- bool have_tx_bitrate : 1;
- bool have_expected_throughput : 1;
-};
-
-typedef void (*netdev_get_station_cb_t)(const struct netdev_station_info *info,
- void *user_data);
+typedef void (*netdev_get_station_cb_t)(
+ const struct diagnostic_station_info *info,
+ void *user_data);
struct wiphy *netdev_get_wiphy(struct netdev *netdev);
const uint8_t *netdev_get_address(struct netdev *netdev);
diff --git a/src/station.c b/src/station.c
index 558ecf9a..95dea92b 100644
--- a/src/station.c
+++ b/src/station.c
@@ -54,6 +54,7 @@
#include "src/netconfig.h"
#include "src/anqp.h"
#include "src/anqputil.h"
+#include "src/diagnostic.h"
static struct l_queue *station_list;
static uint32_t netdev_watch;
@@ -3459,8 +3460,9 @@ static void station_destroy_interface(void *user_data)
station_free(station);
}
-static void station_get_diagnostic_cb(const struct netdev_station_info *info,
- void *user_data)
+static void station_get_diagnostic_cb(
+ const struct diagnostic_station_info *info,
+ void *user_data)
{
struct station *station = user_data;
struct l_dbus_message *reply;
@@ -3488,19 +3490,19 @@ static void station_get_diagnostic_cb(const struct netdev_station_info *info,
if (info->have_rx_mcs) {
switch (info->rx_mcs_type) {
- case NETDEV_MCS_TYPE_HT:
+ case DIAGNOSTIC_MCS_TYPE_HT:
dbus_append_dict_basic(builder, "RxMode", 's',
"802.11n");
dbus_append_dict_basic(builder, "RxMCS", 'y',
&info->rx_mcs);
break;
- case NETDEV_MCS_TYPE_VHT:
+ case DIAGNOSTIC_MCS_TYPE_VHT:
dbus_append_dict_basic(builder, "RxMode", 's',
"802.11ac");
dbus_append_dict_basic(builder, "RxMCS", 'y',
&info->rx_mcs);
break;
- case NETDEV_MCS_TYPE_HE:
+ case DIAGNOSTIC_MCS_TYPE_HE:
dbus_append_dict_basic(builder, "RxMode", 's',
"802.11ax");
dbus_append_dict_basic(builder, "RxMCS", 'y',
@@ -3513,19 +3515,19 @@ static void station_get_diagnostic_cb(const struct netdev_station_info *info,
if (info->have_tx_mcs) {
switch (info->tx_mcs_type) {
- case NETDEV_MCS_TYPE_HT:
+ case DIAGNOSTIC_MCS_TYPE_HT:
dbus_append_dict_basic(builder, "TxMode", 's',
"802.11n");
dbus_append_dict_basic(builder, "TxMCS", 'y',
&info->tx_mcs);
break;
- case NETDEV_MCS_TYPE_VHT:
+ case DIAGNOSTIC_MCS_TYPE_VHT:
dbus_append_dict_basic(builder, "TxMode", 's',
"802.11ac");
dbus_append_dict_basic(builder, "TxMCS", 'y',
&info->tx_mcs);
break;
- case NETDEV_MCS_TYPE_HE:
+ case DIAGNOSTIC_MCS_TYPE_HE:
dbus_append_dict_basic(builder, "TxMode", 's',
"802.11ax");
dbus_append_dict_basic(builder, "TxMCS", 'y',
--
2.26.2
1 year, 3 months
[PATCH v2] build: add After=network-pre.target to service files
by Alvin Šipraga
systemd specifies a special passive target unit 'network-pre.target'
which may be pulled in by services that want to run before any network
interface is brought up or configured. Correspondingly, network
management services such as iwd and ead should specify
After=network-pre.target to ensure a proper ordering with respect to
this special target. For more information on network-pre.target, see
systemd.special(7).
Two examples to explain the rationale of this change:
1. On one of our embedded systems running iwd, a oneshot service is
run on startup to configure - among other things - the MAC address of
the wireless network interface based on some data in an EEPROM.
Following the systemd documentation, the oneshot service specifies:
Before=network-pre.target
Wants=network-pre.target
... to ensure that it is run before any network management software
starts. In practice, before this change, iwd was starting up and
connecting to an AP before the service had finished. iwd would then
get kicked off by the AP when the MAC address got changed. By
specifying After=network-pre.target, systemd will take care to avoid
this situation.
2. An administrator may wish to use network-pre.target to ensure
firewall rules are applied before any network management software is
started. This use-case is described in the systemd documentation[1].
Since iwd can be used for IP configuration, it should also respect
the After=network-pre.target convention.
Note that network-pre.target is a passive unit that is only pulled in if
another unit specifies e.g. Wants=network-pre.target. If no such unit
exists, this change will have no effect on the order in which systemd
starts iwd or ead.
[1] https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
---
src/iwd.service.in | 1 +
wired/ead.service.in | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/iwd.service.in b/src/iwd.service.in
index 77819eaf..96e4abac 100644
--- a/src/iwd.service.in
+++ b/src/iwd.service.in
@@ -1,5 +1,6 @@
[Unit]
Description=Wireless service
+After=network-pre.target
Before=network.target
Wants=network.target
diff --git a/wired/ead.service.in b/wired/ead.service.in
index 387fdb68..6403c9e4 100644
--- a/wired/ead.service.in
+++ b/wired/ead.service.in
@@ -1,5 +1,6 @@
[Unit]
Description=Ethernet service
+After=network-pre.target
Before=network.target
Wants=network.target
--
2.29.2
1 year, 3 months
[PATCH v3 1/7] netdev: move netdev_station_info to diagnostic.h
by James Prestwood
With AP now getting its own diagnostic interface it made sense
to move the netdev_station_info struct definition into its own
header which eventually can be accompanied by utilities in
diagnostic.c. These utilities can then be shared with AP and
station as needed.
---
src/diagnostic.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
src/netdev.c | 23 ++++++++++++-----------
src/netdev.h | 34 ++++-----------------------------
src/station.c | 6 ++++--
4 files changed, 69 insertions(+), 43 deletions(-)
create mode 100644 src/diagnostic.h
diff --git a/src/diagnostic.h b/src/diagnostic.h
new file mode 100644
index 00000000..8292d192
--- /dev/null
+++ b/src/diagnostic.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+enum diagnostic_mcs_type {
+ DIAGNOSTIC_MCS_TYPE_NONE,
+ DIAGNOSTIC_MCS_TYPE_HT,
+ DIAGNOSTIC_MCS_TYPE_VHT,
+ DIAGNOSTIC_MCS_TYPE_HE,
+};
+
+struct diagnostic_station_info {
+ uint8_t addr[6];
+ int8_t cur_rssi;
+
+ enum diagnostic_mcs_type rx_mcs_type;
+ uint32_t rx_bitrate;
+ uint8_t rx_mcs;
+ enum diagnostic_mcs_type tx_mcs_type;
+ uint32_t tx_bitrate;
+ uint8_t tx_mcs;
+
+ uint32_t expected_throughput;
+
+ bool have_cur_rssi : 1;
+ bool have_rx_mcs : 1;
+ bool have_tx_mcs : 1;
+ bool have_rx_bitrate : 1;
+ bool have_tx_bitrate : 1;
+ bool have_expected_throughput : 1;
+};
diff --git a/src/netdev.c b/src/netdev.c
index e3ce270a..a19270c0 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -61,6 +61,7 @@
#include "src/fils.h"
#include "src/auth-proto.h"
#include "src/frame-xchg.h"
+#include "src/diagnostic.h"
#ifndef ENOTSUPP
#define ENOTSUPP 524
@@ -369,7 +370,7 @@ int netdev_set_powered(struct netdev *netdev, bool powered,
}
static bool netdev_parse_bitrate(struct l_genl_attr *attr,
- enum netdev_mcs_type *type_out,
+ enum diagnostic_mcs_type *type_out,
uint32_t *rate_out,
uint8_t *mcs_out)
{
@@ -377,7 +378,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
const void *data;
uint32_t rate = 0;
uint8_t mcs = 0;
- enum netdev_mcs_type mcs_type = NETDEV_MCS_TYPE_NONE;
+ enum diagnostic_mcs_type mcs_type = DIAGNOSTIC_MCS_TYPE_NONE;
while (l_genl_attr_next(attr, &type, &len, &data)) {
switch (type) {
@@ -394,7 +395,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
return false;
mcs = l_get_u8(data);
- mcs_type = NETDEV_MCS_TYPE_HT;
+ mcs_type = DIAGNOSTIC_MCS_TYPE_HT;
break;
@@ -403,7 +404,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
return false;
mcs = l_get_u8(data);
- mcs_type = NETDEV_MCS_TYPE_VHT;
+ mcs_type = DIAGNOSTIC_MCS_TYPE_VHT;
break;
@@ -412,7 +413,7 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
return false;
mcs = l_get_u8(data);
- mcs_type = NETDEV_MCS_TYPE_HE;
+ mcs_type = DIAGNOSTIC_MCS_TYPE_HE;
break;
}
@@ -424,14 +425,14 @@ static bool netdev_parse_bitrate(struct l_genl_attr *attr,
*type_out = mcs_type;
*rate_out = rate;
- if (mcs_type != NETDEV_MCS_TYPE_NONE)
+ if (mcs_type != DIAGNOSTIC_MCS_TYPE_NONE)
*mcs_out = mcs;
return true;
}
static bool netdev_parse_sta_info(struct l_genl_attr *attr,
- struct netdev_station_info *info)
+ struct diagnostic_station_info *info)
{
uint16_t type, len;
const void *data;
@@ -458,7 +459,7 @@ static bool netdev_parse_sta_info(struct l_genl_attr *attr,
info->have_rx_bitrate = true;
- if (info->rx_mcs_type != NETDEV_MCS_TYPE_NONE)
+ if (info->rx_mcs_type != DIAGNOSTIC_MCS_TYPE_NONE)
info->have_rx_mcs = true;
break;
@@ -474,7 +475,7 @@ static bool netdev_parse_sta_info(struct l_genl_attr *attr,
info->have_tx_bitrate = true;
- if (info->tx_mcs_type != NETDEV_MCS_TYPE_NONE)
+ if (info->tx_mcs_type != DIAGNOSTIC_MCS_TYPE_NONE)
info->have_tx_mcs = true;
break;
@@ -511,7 +512,7 @@ static void netdev_rssi_poll_cb(struct l_genl_msg *msg, void *user_data)
uint16_t type, len;
const void *data;
bool found;
- struct netdev_station_info info;
+ struct diagnostic_station_info info;
uint8_t prev_rssi_level_idx = netdev->cur_rssi_level_idx;
netdev->rssi_poll_cmd_id = 0;
@@ -4156,7 +4157,7 @@ static void netdev_get_station_cb(struct l_genl_msg *msg, void *user_data)
struct l_genl_attr attr, nested;
uint16_t type, len;
const void *data;
- struct netdev_station_info info;
+ struct diagnostic_station_info info;
netdev->get_station_cmd_id = 0;
diff --git a/src/netdev.h b/src/netdev.h
index e7a1c060..d5adcf09 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -27,6 +27,7 @@ struct scan_bss;
struct handshake_state;
struct eapol_sm;
struct mmpdu_header;
+struct diagnostic_station_info;
enum netdev_result {
NETDEV_RESULT_OK,
@@ -114,36 +115,9 @@ typedef void (*netdev_station_watch_func_t)(struct netdev *netdev,
const uint8_t *mac, bool added,
void *user_data);
-enum netdev_mcs_type {
- NETDEV_MCS_TYPE_NONE,
- NETDEV_MCS_TYPE_HT,
- NETDEV_MCS_TYPE_VHT,
- NETDEV_MCS_TYPE_HE,
-};
-
-struct netdev_station_info {
- uint8_t addr[6];
- int8_t cur_rssi;
-
- enum netdev_mcs_type rx_mcs_type;
- uint32_t rx_bitrate;
- uint8_t rx_mcs;
- enum netdev_mcs_type tx_mcs_type;
- uint32_t tx_bitrate;
- uint8_t tx_mcs;
-
- uint32_t expected_throughput;
-
- bool have_cur_rssi : 1;
- bool have_rx_mcs : 1;
- bool have_tx_mcs : 1;
- bool have_rx_bitrate : 1;
- bool have_tx_bitrate : 1;
- bool have_expected_throughput : 1;
-};
-
-typedef void (*netdev_get_station_cb_t)(const struct netdev_station_info *info,
- void *user_data);
+typedef void (*netdev_get_station_cb_t)(
+ const struct diagnostic_station_info *info,
+ void *user_data);
struct wiphy *netdev_get_wiphy(struct netdev *netdev);
const uint8_t *netdev_get_address(struct netdev *netdev);
diff --git a/src/station.c b/src/station.c
index c65fc0cc..41f19b09 100644
--- a/src/station.c
+++ b/src/station.c
@@ -53,6 +53,7 @@
#include "src/netconfig.h"
#include "src/anqp.h"
#include "src/anqputil.h"
+#include "src/diagnostic.h"
static struct l_queue *station_list;
static uint32_t netdev_watch;
@@ -3455,8 +3456,9 @@ static void station_destroy_interface(void *user_data)
station_free(station);
}
-static void station_get_diagnostic_cb(const struct netdev_station_info *info,
- void *user_data)
+static void station_get_diagnostic_cb(
+ const struct diagnostic_station_info *info,
+ void *user_data)
{
struct station *station = user_data;
struct l_dbus_message *reply;
--
2.26.2
1 year, 3 months
[PATCH] build: add After=network-pre.target to service files
by Alvin Šipraga
systemd specifies a special passive target unit 'network-pre.target'
which may be pulled in by services that want to run before any network
interface is brought up or configured. Correspondingly, network
management services such as iwd and ead should specify
After=network-pre.target to ensure a proper ordering with respect to
this special target.
For more information, see systemd.special(7) and [1].
[1] https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
---
src/iwd.service.in | 1 +
wired/ead.service.in | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/iwd.service.in b/src/iwd.service.in
index 77819eaf..96e4abac 100644
--- a/src/iwd.service.in
+++ b/src/iwd.service.in
@@ -1,5 +1,6 @@
[Unit]
Description=Wireless service
+After=network-pre.target
Before=network.target
Wants=network.target
diff --git a/wired/ead.service.in b/wired/ead.service.in
index 387fdb68..6403c9e4 100644
--- a/wired/ead.service.in
+++ b/wired/ead.service.in
@@ -1,5 +1,6 @@
[Unit]
Description=Ethernet service
+After=network-pre.target
Before=network.target
Wants=network.target
--
2.29.2
1 year, 3 months