[PATCH v2] adhoc: fix missing call to va_end
by James Prestwood
Since only one switch case uses this, va_start/end were just
moved into that case specifically.
---
src/adhoc.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/adhoc.c b/src/adhoc.c
index 7f9ce765..506e596a 100644
--- a/src/adhoc.c
+++ b/src/adhoc.c
@@ -186,14 +186,15 @@ static void adhoc_handshake_event(struct handshake_state *hs,
struct adhoc_state *adhoc = sta->adhoc;
va_list args;
- va_start(args, user_data);
-
switch (event) {
case HANDSHAKE_EVENT_FAILED:
+ va_start(args, user_data);
+
l_error("handshake failed with STA "MAC" (%d)",
MAC_STR(sta->addr),
va_arg(args, int));
+ va_end(args);
/*
* eapol frees the state machines upon handshake failure. Since
* this is only a failure on one of the handshakes we need to
--
2.26.2
1 year, 3 months
[PATCH 1/5] display: use l_strlcpy to avoid potential overflow
by James Prestwood
If 'entry' exceeds the length of 'line' we could overflow. Instead
use l_strlcpy and pass in the remaining amount of data left in
the buffer.
---
client/display.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/display.c b/client/display.c
index 88bc913f..961ad419 100644
--- a/client/display.c
+++ b/client/display.c
@@ -419,7 +419,7 @@ static void display_completion_matches(char **matches, int num_matches,
}
entry = l_strdup_printf("%-*s ", max_length, matches[index]);
- strcpy(&line[line_used], entry);
+ l_strlcpy(&line[line_used], entry, sizeof(line) - line_used);
l_free(entry);
line_used += max_length + 1;
--
2.26.2
1 year, 3 months
[PATCH] diagnostics: check dbus variant parsing
by James Prestwood
If the diagnostics dictionary is invalid print an
error and do not continue parsing.
---
client/diagnostic.c | 43 ++++++++++++++++++++++++++++++-------------
1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/client/diagnostic.c b/client/diagnostic.c
index c94178d6..153598ed 100644
--- a/client/diagnostic.c
+++ b/client/diagnostic.c
@@ -31,7 +31,7 @@
#include "client/diagnostic.h"
#include "client/display.h"
-typedef void (*display_dict_custom_func_t)(struct l_dbus_message_iter *variant,
+typedef bool (*display_dict_custom_func_t)(struct l_dbus_message_iter *variant,
const char *key, const char *margin,
int name_column_width, int value_column_width);
@@ -64,16 +64,19 @@ static const struct diagnostic_dict_mapping *find_mapping(const char *key,
return NULL;
}
-static void display_bitrate_100kbps(struct l_dbus_message_iter *variant,
+static bool display_bitrate_100kbps(struct l_dbus_message_iter *variant,
const char *key, const char *margin,
int name_column_width, int value_column_width)
{
uint32_t rate;
- l_dbus_message_iter_get_variant(variant, "u", &rate);
+ if (!l_dbus_message_iter_get_variant(variant, "u", &rate))
+ return false;
display("%s%-*s%-*u Kbit/s\n", margin, name_column_width, key,
value_column_width, rate * 100);
+
+ return true;
}
static const struct diagnostic_dict_mapping diagnostic_mapping[] = {
@@ -115,39 +118,48 @@ void diagnostic_display(struct l_dbus_message_iter *dict,
if (!map->custom)
continue;
- map->custom(&variant, key, margin, name_column_width,
- value_column_width);
+ if (!map->custom(&variant, key, margin, name_column_width,
+ value_column_width))
+ goto parse_error;
/* custom should handle any units, so continue */
continue;
case 's':
- l_dbus_message_iter_get_variant(&variant, "s",
- &s_value);
+ if (!l_dbus_message_iter_get_variant(&variant, "s",
+ &s_value))
+ goto parse_error;
+
sprintf(display_text, "%s%-*s%-*s", margin,
name_column_width, key,
value_column_width, s_value);
break;
case 'u':
- l_dbus_message_iter_get_variant(&variant, "u",
- &u_value);
+ if (!l_dbus_message_iter_get_variant(&variant, "u",
+ &u_value))
+ goto parse_error;
+
sprintf(display_text, "%s%-*s%-*u", margin,
name_column_width, key,
value_column_width, u_value);
break;
case 'n':
- l_dbus_message_iter_get_variant(&variant, "n",
- &n_value);
+ if (!l_dbus_message_iter_get_variant(&variant, "n",
+ &n_value))
+ goto parse_error;
+
sprintf(display_text, "%s%-*s%-*i", margin,
name_column_width, key,
value_column_width, n_value);
break;
case 'y':
- l_dbus_message_iter_get_variant(&variant, "y",
- &y_value);
+ if (!l_dbus_message_iter_get_variant(&variant, "y",
+ &y_value))
+ goto parse_error;
+
sprintf(display_text, "%s%-*s%-*u", margin,
name_column_width, key,
value_column_width, y_value);
@@ -164,4 +176,9 @@ void diagnostic_display(struct l_dbus_message_iter *dict,
else
display("%s\n", display_text);
}
+
+ return;
+
+parse_error:
+ display_error("Error parsing dignostics");
}
--
2.26.2
1 year, 3 months
[PATCH] test-runner: clean up dbus path file properly
by James Prestwood
Dbus should be started as a multi-test process from the
TestContext, which leaves the dbus address file around for
the full test run. For Namespaces dbus-daemon should be
closed when the Namespace closes.
---
tools/test-runner | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/test-runner b/tools/test-runner
index d50d3abd..965b0a57 100755
--- a/tools/test-runner
+++ b/tools/test-runner
@@ -474,6 +474,7 @@ class Namespace:
dbus_address = None
processes = []
radios = []
+ dbus_pid = None
def __init__(self, args, name, radios):
self.name = name
@@ -484,7 +485,7 @@ class Namespace:
for r in radios:
Process(['iw', 'phy', r.name, 'set', 'netns', 'name', name], wait=True)
- self.start_dbus(multi_test=False)
+ self.dbus_pid = self.start_dbus(multi_test=False)
def reset(self):
self.radios = []
@@ -497,7 +498,8 @@ class Namespace:
print("Killing process %s" % p.name)
self.stop_process(p)
- os.remove(self.dbus_address.split('=')[1])
+ if self.dbus_pid and not self.dbus_pid.multi_test:
+ os.remove(self.dbus_address.split('=')[1])
def __del__(self):
print("Removing namespace %s" % self.name)
@@ -1119,7 +1121,7 @@ def print_results(results):
def run_auto_tests(ctx, args):
tests = build_test_list(args)
- ctx.start_dbus()
+ ctx.start_dbus(multi_test=True)
ctx.start_haveged()
# Copy autotests/misc/{certs,secrets,phonesim} so any test can refer to them
--
2.26.2
1 year, 3 months
[PATCH 1/2] auto-t: add API wait_for_object_change
by James Prestwood
This is similar to wait_for_object_condition, but will not allow
any intermediate state changes between the initial and expected
conditions. This is useful for roaming tests when the expected
state change is 'connected' --> 'roaming' with no changes in
between.
---
autotests/util/iwd.py | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py
index 6b153ea7..8ea1dfb9 100755
--- a/autotests/util/iwd.py
+++ b/autotests/util/iwd.py
@@ -1034,6 +1034,48 @@ class IWD(AsyncOpAbstract):
def wait_for_object_condition(self, *args, **kwargs):
self._wait_for_object_condition(*args, **kwargs)
+ def wait_for_object_change(self, obj, from_str, to_str, max_wait = 50):
+ '''
+ Expects condition 'from_str' to evaluate true while waiting for 'to_str'. If
+ at any point during the wait 'from_str' evaluates false, an exception is
+ raised.
+
+ This allows an object to be checked for a state transition without any
+ intermediate state changes.
+ '''
+ self._wait_timed_out = False
+
+ def wait_timeout_cb():
+ self._wait_timed_out = True
+ return False
+
+ # Does initial condition pass?
+ if not eval(from_str):
+ raise Exception("initial condition [%s] not met" % from_str)
+
+ try:
+ timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
+ context = ctx.mainloop.get_context()
+ while True:
+ context.iteration(may_block=True)
+
+ # If neither the initial or expected condition evaluate the
+ # object must be in another unexpected state.
+ if not eval(from_str) and not eval(to_str):
+ raise Exception('unexpected condition between [%s] and [%s]' % from_str, to_str)
+
+ # Initial condition does not evaluate but expected does, pass
+ if not eval(from_str) and eval(to_str):
+ break
+
+ if self._wait_timed_out and ctx.args.gdb == None:
+ raise TimeoutError('[' + to_str + ']'\
+ ' condition was not met in '\
+ + str(max_wait) + ' sec')
+ finally:
+ if not self._wait_timed_out:
+ GLib.source_remove(timeout)
+
def wait(self, time):
self._wait_timed_out = False
def wait_timeout_cb():
--
2.26.2
1 year, 3 months
[PATCH 1/3] test-runner: clean up temporary files
by James Prestwood
---
tools/test-runner | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/tools/test-runner b/tools/test-runner
index a9b13aa8..6fd4dd1f 100755
--- a/tools/test-runner
+++ b/tools/test-runner
@@ -497,6 +497,8 @@ class Namespace:
print("Killing process %s" % p.name)
self.stop_process(p)
+ os.remove(self.dbus_address.split('=')[0])
+
def __del__(self):
print("Removing namespace %s" % self.name)
self.reset()
@@ -1168,6 +1170,10 @@ def run_auto_tests(ctx, args):
finally:
post_test(ctx, copied)
+ shutil.rmtree('/tmp/certs')
+ shutil.rmtree('/tmp/secrets')
+ os.remove('/tmp/phonesim.conf')
+
# Write out kernel log
if ctx.args.log:
Process(["dmesg"], ctx=ctx, wait=True)
--
2.26.2
1 year, 3 months
[PATCH 1/3] test-runner: print Radio class path
by James Prestwood
---
tools/test-runner | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/test-runner b/tools/test-runner
index 3a766ef5..a9b13aa8 100755
--- a/tools/test-runner
+++ b/tools/test-runner
@@ -347,6 +347,8 @@ class VirtualRadio(Radio):
if self.disable_cipher:
ret += '\tDisabled ciphers: %s\n' % self.disable_cipher
+ ret += '\tPath: %s' % self._radio.path
+
ret += '\n'
return ret
--
2.26.2
1 year, 3 months
[PATCH v3 1/2] station: move scan cancelation to __station_connect_network
by James Prestwood
An earlier patch fixed a problem where a queued quick scan would
be triggered and fail once already connected, resulting in a state
transition from connected --> autoconnect_full. This fixed the
Connect() path but this could also happen via autoconnect. Starting
from a connected state, the sequence goes:
- DBus scan is triggered
- AP disconnects IWD
- State transition from disconnected --> autoconnect_quick
- Queue quick scan
- DBus scan results come in and used to autoconnect
- A connect work item is inserted ahead of all others, transition
from autoconnect_quick --> connecting.
- Connect completes, transition from connecting --> connected
- Quick scan can finally get triggered, which the kernel fails to
do since IWD is connected, transition from connected -->
autoconnect_full.
This can be fixed by checking for a pending quick scan in the
autoconnect path.
---
src/station.c | 7 +++++++
1 file changed, 7 insertions(+)
v3:
* Moved check into the autoconnect path rather than
__station_connect_network
diff --git a/src/station.c b/src/station.c
index 8288916f..2a7025ef 100644
--- a/src/station.c
+++ b/src/station.c
@@ -196,6 +196,13 @@ static void station_autoconnect_next(struct station *station)
if (!r) {
station_enter_state(station, STATION_STATE_CONNECTING);
+
+ if (station->quick_scan_id) {
+ scan_cancel(netdev_get_wdev_id(station->netdev),
+ station->quick_scan_id);
+ station->quick_scan_id = 0;
+ }
+
return;
}
}
--
2.26.2
1 year, 3 months
[PATCH v2 1/2] station: move scan cancelation to __station_connect_network
by James Prestwood
An earlier patch fixed a problem where a queued quick scan would
be triggered and fail once already connected, resulting in a state
transition from connected --> autoconnect_full. This fixed the
Connect() path but this could also happen via autoconnect. Starting
from a connected state, the sequence goes:
- DBus scan is triggered
- AP disconnects IWD
- State transition from disconnected --> autoconnect_quick
- Queue quick scan
- DBus scan results come in and used to autoconnect
- A connect work item is inserted ahead of all others, transition
from autoconnect_quick --> connecting.
- Connect completes, transition from connecting --> connected
- Quick scan can finally get triggered, which the kernel fails to
do since IWD is connected, transition from connected -->
autoconnect_full.
By moving the scan cancellation from station_connect_network into
__station_connect_network we handle both the explicit Connect()
path as well as autoconnect.
---
src/station.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
v2:
* Clarifed the exact sequence of events in description
diff --git a/src/station.c b/src/station.c
index 8288916f..1f59e270 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2497,6 +2497,25 @@ int __station_connect_network(struct station *station, struct network *network,
struct handshake_state *hs;
int r;
+ /*
+ * If a hidden scan is not completed, station_is_busy would not
+ * indicate anything is going on so we need to cancel the scan and
+ * fail the connection now.
+ */
+ if (station->hidden_network_scan_id) {
+ scan_cancel(netdev_get_wdev_id(station->netdev),
+ station->hidden_network_scan_id);
+
+ dbus_pending_reply(&station->hidden_pending,
+ 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;
+ }
+
hs = station_handshake_setup(station, network, bss);
if (!hs)
return -ENOTSUP;
@@ -2576,25 +2595,6 @@ void station_connect_network(struct station *station, struct network *network,
struct l_dbus *dbus = dbus_get_bus();
int err;
- /*
- * If a hidden scan is not completed, station_is_busy would not
- * indicate anything is going on so we need to cancel the scan and
- * fail the connection now.
- */
- if (station->hidden_network_scan_id) {
- scan_cancel(netdev_get_wdev_id(station->netdev),
- station->hidden_network_scan_id);
-
- dbus_pending_reply(&station->hidden_pending,
- 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/3] station: move scan cancelation to __station_connect_network
by James Prestwood
This handles connect-on-disconnect, as well as retrying other BSS's
on failures rather than only explicit Connect() calls.
---
src/station.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/src/station.c b/src/station.c
index 8c1e97d6..06c4d75e 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2497,6 +2497,25 @@ int __station_connect_network(struct station *station, struct network *network,
struct handshake_state *hs;
int r;
+ /*
+ * If a hidden scan is not completed, station_is_busy would not
+ * indicate anything is going on so we need to cancel the scan and
+ * fail the connection now.
+ */
+ if (station->hidden_network_scan_id) {
+ scan_cancel(netdev_get_wdev_id(station->netdev),
+ station->hidden_network_scan_id);
+
+ dbus_pending_reply(&station->hidden_pending,
+ 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;
+ }
+
hs = station_handshake_setup(station, network, bss);
if (!hs)
return -ENOTSUP;
@@ -2576,25 +2595,6 @@ void station_connect_network(struct station *station, struct network *network,
struct l_dbus *dbus = dbus_get_bus();
int err;
- /*
- * If a hidden scan is not completed, station_is_busy would not
- * indicate anything is going on so we need to cancel the scan and
- * fail the connection now.
- */
- if (station->hidden_network_scan_id) {
- scan_cancel(netdev_get_wdev_id(station->netdev),
- station->hidden_network_scan_id);
-
- dbus_pending_reply(&station->hidden_pending,
- 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