[PATCH 1/2] frame-xchg: Fix frame_watch_remove_by_handler for group 0
by Andrew Zaborowski
Don't match the default group's (group_id 0) wdev_id against the
provided wdev_id because the default group can be used on all wdevs and
its wdev_id is 0. Also match individual item's wdev_id in the group to
make up for this although it normally wouldn't matter.
---
src/frame-xchg.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/frame-xchg.c b/src/frame-xchg.c
index 4c950fd3..44711997 100644
--- a/src/frame-xchg.c
+++ b/src/frame-xchg.c
@@ -661,6 +661,7 @@ bool frame_watch_wdev_remove(uint64_t wdev_id)
}
struct frame_watch_handler_check_info {
+ uint64_t wdev_id;
frame_watch_cb_t handler;
void *user_data;
};
@@ -671,7 +672,8 @@ static bool frame_watch_item_remove_by_handler(void *data, void *user_data)
l_container_of(data, struct frame_watch, super);
struct frame_watch_handler_check_info *info = user_data;
- if (watch->super.notify != info->handler ||
+ if (watch->wdev_id != info->wdev_id ||
+ watch->super.notify != info->handler ||
watch->super.notify_data != info->user_data)
return false;
@@ -702,9 +704,9 @@ static bool frame_watch_remove_by_handler(uint64_t wdev_id, uint32_t group_id,
void *user_data)
{
struct watch_group_match_info group_info =
- { wdev_id, group_id };
+ { group_id == 0 ? 0 : wdev_id, group_id };
struct frame_watch_handler_check_info handler_info =
- { handler, user_data };
+ { wdev_id, handler, user_data };
struct watch_group *group = l_queue_find(watch_groups,
frame_watch_group_match,
&group_info);
--
2.25.1
2 years
[PATCH] scan: don't send the same scan request twice
by Alvin Šipraga
If start_scan_next_request() is called while a scan request
(NL80211_CMD_GET_SCAN) is still running, the same scan request will be
sent again by mistake. Add a check in the function to avoid sending a
request if one is already in progress.
This also fixes a crash that occurs if the following conditions are met:
- the duplicated request is the only request in the scan request
queue, and
- both scan requests fail with an error not EBUSY.
In this case, the first callback to scan_request_triggered() will delete
the request from the scan request queue. The second callback will find
an empty queue and consequently pass a NULL scan_request pointer to
scan_request_failed(), causing a segmentation fault.
---
src/scan.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/scan.c b/src/scan.c
index 718f7497..106fa81c 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -839,6 +839,9 @@ static bool start_next_scan_request(struct scan_context *sc)
if (sc->state != SCAN_STATE_NOT_RUNNING)
return true;
+ if (sc->start_cmd_id)
+ return true;
+
while (sr) {
if (!scan_request_send_trigger(sc, sr))
return true;
--
2.26.2
2 years
Scanning while in AP mode
by Erik Botö
Hi,
I want to scan for networks while having an active AP. From what I
understand this can be achieved by using NL80211_SCAN_FLAG_AP.
The documentation for it say:
* @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured
* as AP and the beaconing has already been configured. This attribute is
* dangerous because will destroy stations performance as a lot of frames
* will be lost while scanning off-channel, therefore it must be used only
* when really needed
So I suppose it's not something that should be enabled by default, but
it would be useful to be able to start a scan with this if explicitly
requested.
My use case for this is initial device setup. A new device would be
configured to start up in AP-mode and a inital setup service would run
that e.g. a phone could connect to and be presented with a list of
found networks. Then a network can be selected and credentials setup,
then the device will shut down the AP and instead connect as a client
to the selected network. Like many IoT devices etc let's you do when
configuring.
What do you think, is it something that could fit into iwd or is there
some reasons to not support this?
Cheers,
Erik
2 years
[PATCH 1/2] anqp: refactor to use frame-xchg
by James Prestwood
The new frame-xchg module now handles a lot of what ANQP used to do. ANQP
now does not need to depend on nl80211/netdev for building and sending
frames. It also no longer needs any of the request lookups or frame
watches because frame-xchg filters this for us. The request queue did
need to remain in ANQP because station fires off ANQP requests all in
a row, and frame-xchg cannot handle this. Now ANQP just sends out the
first request, and queue's the rest. As the responses come in it will
send out the next frame in the queue until there are no more left.
The anqp_request API was changed to only return a bool, as well as
take the wdev_id rather than ifindex. Station was updated to remove
the 'pending' member since it was not actually used, as well as fix
a bug on the timeout path where the request queue would get popped
twice.
There is somewhat of a TODO that was overlooked initially with ANQP
and was realized when testing these patches. Since the network_info
depends on ANQP completing there is a race condition between scanning
finishing and being ready to connect to networks which require ANQP.
The autoconnect case does not have this issue, but explicit Dbus
connects do. In practice this may not matter since the user would have
to issue a connect at just the right time, but it could still happen.
This may need to be fixed in network where we see if there are any
pending ANQP requests before we return NotConfigured. If there are
pending requests we should wait for those, then attempt to connect.
---
src/anqp.c | 438 +++++++++++++-------------------------------------
src/anqp.h | 2 +-
src/station.c | 16 +-
3 files changed, 114 insertions(+), 342 deletions(-)
diff --git a/src/anqp.c b/src/anqp.c
index 6627bd81..504b5bdf 100644
--- a/src/anqp.c
+++ b/src/anqp.c
@@ -31,105 +31,63 @@
#include "src/module.h"
#include "src/anqp.h"
#include "src/util.h"
-#include "src/eap-private.h"
#include "src/ie.h"
-#include "src/nl80211util.h"
-#include "src/nl80211cmd.h"
#include "src/scan.h"
-#include "src/netdev.h"
#include "src/iwd.h"
#include "src/mpdu.h"
-#include "src/wiphy.h"
+#include "src/frame-xchg.h"
#include "linux/nl80211.h"
+#define ANQP_GROUP 1
+
struct anqp_request {
- uint32_t ifindex;
+ uint64_t wdev_id;
anqp_response_func_t anqp_cb;
anqp_destroy_func_t anqp_destroy;
void *anqp_data;
- uint64_t anqp_cookie;
uint8_t anqp_token;
+ uint32_t frequency;
+ uint8_t *frame;
+ size_t frame_len;
};
-static struct l_genl_family *nl80211 = NULL;
-
static struct l_queue *anqp_requests;
static uint8_t anqp_token = 0;
-static uint32_t netdev_watch;
-static uint32_t unicast_watch;
-
static void anqp_destroy(void *user_data)
{
struct anqp_request *request = user_data;
if (request->anqp_destroy)
request->anqp_destroy(request->anqp_data);
-}
-
-static void netdev_gas_request_cb(struct l_genl_msg *msg, void *user_data)
-{
- struct anqp_request *request = user_data;
-
- if (l_genl_msg_get_error(msg) != 0)
- goto error;
-
- if (nl80211_parse_attrs(msg, NL80211_ATTR_COOKIE, &request->anqp_cookie,
- NL80211_ATTR_UNSPEC) < 0)
- goto error;
-
- return;
-
-error:
- l_debug("Error sending CMD_FRAME (%d)", l_genl_msg_get_error(msg));
-
- if (request->anqp_cb)
- request->anqp_cb(ANQP_FAILED, NULL, 0, request->anqp_data);
-
- if (request->anqp_destroy)
- request->anqp_destroy(request->anqp_data);
+ l_free(request->frame);
l_free(request);
}
-static bool match_token(const void *a, const void *b)
-{
- const struct anqp_request *request = a;
- const struct token_match {
- uint32_t ifindex;
- uint8_t token;
-
- } *match = b;
+static void anqp_request_next(void);
- if (request->ifindex != match->ifindex)
- return false;
-
- if (request->anqp_token != match->token)
- return false;
-
- return true;
-}
-
-static void anqp_response_frame_event(uint32_t ifindex,
- const struct mmpdu_header *hdr,
- const void *body, size_t body_len)
+/*
+ * By using frame-xchg we should get called back here for any frame matching our
+ * prefix until the duration expires. If frame-xchg is never signalled 'done'
+ * (returning true) we should get a timeout in anqp_frame_timeout. This is
+ * why we drop any improperly formatted frames without cleaning up the request.
+ */
+static bool anqp_response_frame_event(const struct mmpdu_header *hdr,
+ const void *body, size_t body_len,
+ int rssi, void *user_data)
{
- struct anqp_request *request;
+ struct anqp_request *request = user_data;
const uint8_t *ptr = body;
uint16_t status_code;
uint16_t delay;
uint16_t qrlen;
uint8_t adv_proto_len;
uint8_t token;
- struct token_match {
- uint32_t ifindex;
- uint8_t token;
-
- } match;
if (body_len < 9)
- return;
+ return false;
/* Skip past category/action since this frame was prefixed matched */
ptr += 2;
@@ -138,12 +96,8 @@ static void anqp_response_frame_event(uint32_t ifindex,
/* dialog token */
token = *ptr++;
- match.ifindex = ifindex;
- match.token = token;
-
- request = l_queue_find(anqp_requests, match_token, &match);
- if (!request)
- return;
+ if (request->anqp_token != token)
+ return false;
status_code = l_get_le16(ptr);
ptr += 2;
@@ -151,7 +105,7 @@ static void anqp_response_frame_event(uint32_t ifindex,
if (status_code != 0) {
l_error("Bad status code on GAS response %u", status_code);
- return;
+ return false;
}
delay = l_get_le16(ptr);
@@ -166,12 +120,12 @@ static void anqp_response_frame_event(uint32_t ifindex,
*/
if (delay != 0) {
l_error("GAS comeback delay was not zero");
- return;
+ return false;
}
if (*ptr != IE_TYPE_ADVERTISEMENT_PROTOCOL) {
l_error("GAS request not advertisement protocol");
- return;
+ return false;
}
ptr++;
@@ -181,339 +135,163 @@ static void anqp_response_frame_event(uint32_t ifindex,
body_len--;
if (body_len < adv_proto_len)
- return;
+ return false;
ptr += adv_proto_len;
body_len -= adv_proto_len;
if (body_len < 2)
- return;
+ return false;
qrlen = l_get_le16(ptr);
ptr += 2;
if (body_len < qrlen)
- return;
-
- l_queue_remove(anqp_requests, request);
+ return false;
l_debug("ANQP response received from "MAC, MAC_STR(hdr->address_2));
if (request->anqp_cb)
- request->anqp_cb(ANQP_SUCCESS, ptr, qrlen,
- request->anqp_data);
+ request->anqp_cb(ANQP_SUCCESS, ptr, qrlen, request->anqp_data);
- if (request->anqp_destroy)
- request->anqp_destroy(request->anqp_data);
+ l_queue_remove(anqp_requests, request);
+ anqp_destroy(request);
- l_free(request);
+ if (l_queue_isempty(anqp_requests))
+ return true;
- return;
+ anqp_request_next();
+
+ return false;
}
-static void netdev_gas_timeout_cb(void *user_data)
+static const struct frame_xchg_prefix anqp_frame_prefix = {
+ .data = (uint8_t []) {
+ 0x04, 0x0b,
+ },
+ .len = 2,
+};
+
+static void anqp_frame_timeout(int error, void *user_data)
{
struct anqp_request *request = user_data;
+ enum anqp_result result = ANQP_TIMEOUT;
- l_debug("GAS request timed out");
+ if (error < 0) {
+ result = ANQP_FAILED;
+ l_error("Sending ANQP request failed: %s (%i)",
+ strerror(-error), -error);
+ }
if (request->anqp_cb)
- request->anqp_cb(ANQP_TIMEOUT, NULL, 0,
- request->anqp_data);
+ request->anqp_cb(result, NULL, 0, request->anqp_data);
- /* allows anqp_request to be re-entrant */
if (request->anqp_destroy)
request->anqp_destroy(request->anqp_data);
l_queue_remove(anqp_requests, request);
- l_free(request);
-}
-
-static bool match_cookie(const void *a, const void *b)
-{
- const struct anqp_request *request = a;
- const struct cookie_match {
- uint64_t cookie;
- uint32_t ifindex;
- } *match = b;
-
- if (match->ifindex != request->ifindex)
- return false;
-
- if (match->cookie != request->anqp_cookie)
- return false;
+ anqp_destroy(request);
- return true;
-}
-
-static void anqp_frame_wait_cancel_event(struct l_genl_msg *msg,
- uint32_t ifindex)
-{
- uint64_t cookie;
- struct anqp_request *request;
- struct cookie_match {
- uint64_t cookie;
- uint32_t ifindex;
- } match;
-
- l_debug("");
-
- if (nl80211_parse_attrs(msg, NL80211_ATTR_COOKIE, &cookie,
- NL80211_ATTR_UNSPEC) < 0)
- return;
-
- match.cookie = cookie;
- match.ifindex = ifindex;
-
- request = l_queue_find(anqp_requests, match_cookie, &match);
- if (!request)
- return;
-
- if (cookie != request->anqp_cookie)
+ if (l_queue_isempty(anqp_requests))
return;
- netdev_gas_timeout_cb(request);
+ anqp_request_next();
}
-uint32_t anqp_request(uint32_t ifindex, const uint8_t *addr,
- struct scan_bss *bss, const uint8_t *anqp,
- size_t len, anqp_response_func_t cb,
- void *user_data, anqp_destroy_func_t destroy)
+static void anqp_request_next(void)
{
struct anqp_request *request;
- uint8_t frame[512];
- struct l_genl_msg *msg;
struct iovec iov[2];
- uint32_t id;
- uint32_t duration = 300;
- struct netdev *netdev = netdev_find(ifindex);
-
- if (!netdev)
- return 0;
-
- /*
- * TODO: Netdev dependencies will eventually be removed so we need
- * another way to figure out wiphy capabilities.
- */
- if (!wiphy_can_offchannel_tx(netdev_get_wiphy(netdev))) {
- l_error("ANQP failed, driver does not support offchannel TX");
- return 0;
- }
-
- frame[0] = 0x04; /* Category: Public */
- frame[1] = 0x0a; /* Action: GAS initial Request */
- frame[2] = anqp_token; /* Dialog Token */
- frame[3] = IE_TYPE_ADVERTISEMENT_PROTOCOL;
- frame[4] = 2;
- frame[5] = 0x7f;
- frame[6] = IE_ADVERTISEMENT_ANQP;
- l_put_le16(len, frame + 7);
-
- iov[0].iov_base = frame;
- iov[0].iov_len = 9;
- iov[1].iov_base = (void *)anqp;
- iov[1].iov_len = len;
-
- request = l_new(struct anqp_request, 1);
-
- request->ifindex = ifindex;
- request->anqp_cb = cb;
- request->anqp_destroy = destroy;
- request->anqp_token = anqp_token++;
- request->anqp_data = user_data;
-
- msg = nl80211_build_cmd_frame(ifindex, addr, bss->addr,
- bss->frequency, iov, 2);
- l_genl_msg_append_attr(msg, NL80211_ATTR_OFFCHANNEL_TX_OK, 0, "");
- l_genl_msg_append_attr(msg, NL80211_ATTR_DURATION, 4, &duration);
+ if (l_queue_isempty(anqp_requests))
+ return;
- id = l_genl_family_send(nl80211, msg, netdev_gas_request_cb,
- request, NULL);
+ request = l_queue_peek_head(anqp_requests);
- if (!id) {
- l_debug("Failed to send ANQP request");
- l_genl_msg_unref(msg);
- l_free(request);
- return 0;
- }
+ iov[0].iov_base = request->frame;
+ iov[0].iov_len = request->frame_len;
+ iov[1].iov_base = NULL;
- l_debug("ANQP request sent to "MAC, MAC_STR(bss->addr));
-
- l_queue_push_head(anqp_requests, request);
+ l_debug("Sending ANQP request\n");
- return id;
+ frame_xchg_start(request->wdev_id, iov, request->frequency, 0, 300, 0,
+ ANQP_GROUP, anqp_frame_timeout, request,
+ &anqp_frame_prefix, anqp_response_frame_event,
+ NULL);
}
-static void netdev_frame_cb(struct l_genl_msg *msg, void *user_data)
+static uint8_t *anqp_build_frame(const uint8_t *addr, struct scan_bss *bss,
+ const uint8_t *anqp, size_t len,
+ size_t *len_out)
{
- if (l_genl_msg_get_error(msg) < 0)
- l_error("Could not register frame watch type %04x: %i",
- L_PTR_TO_UINT(user_data), l_genl_msg_get_error(msg));
-}
-
-static void anqp_register_frame(uint32_t ifindex)
-{
- struct l_genl_msg *msg;
- uint16_t frame_type = 0x00d0;
- uint8_t prefix[] = { 0x04, 0x0b };
-
- msg = l_genl_msg_new_sized(NL80211_CMD_REGISTER_FRAME, 34);
+ uint8_t *frame = l_malloc(len + 33);
+ uint8_t *ptr;
- l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &ifindex);
- l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME_TYPE, 2, &frame_type);
- l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME_MATCH,
- sizeof(prefix), prefix);
+ memset(frame, 0, len + 33);
- l_genl_family_send(nl80211, msg, netdev_frame_cb,
- L_UINT_TO_PTR(frame_type), NULL);
-}
+ l_put_le16(0x00d0, frame + 0);
+ memcpy(frame + 4, bss->addr, 6);
+ memcpy(frame + 10, addr, 6);
+ memcpy(frame + 16, bss->addr, 6);
-static void anqp_netdev_watch(struct netdev *netdev,
- enum netdev_watch_event event, void *user_data)
-{
- switch (event) {
- case NETDEV_WATCH_EVENT_NEW:
- if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION)
- anqp_register_frame(netdev_get_ifindex(netdev));
+ ptr = frame + 24;
- return;
- default:
- break;
- }
-}
+ *ptr++ = 0x04; /* Category: Public */
+ *ptr++ = 0x0a; /* Action: GAS initial Request */
+ *ptr++ = anqp_token++; /* Dialog Token */
+ *ptr++ = IE_TYPE_ADVERTISEMENT_PROTOCOL;
+ *ptr++ = 2;
-static void anqp_unicast_notify(struct l_genl_msg *msg, void *user_data)
-{
- const struct mmpdu_header *mpdu = NULL;
- const uint8_t *body;
- struct l_genl_attr attr;
- uint16_t type, len;
- uint16_t frame_len = 0;
- const void *data;
- uint8_t cmd;
- uint32_t ifindex = 0;
-
- if (l_queue_isempty(anqp_requests))
- return;
-
- cmd = l_genl_msg_get_command(msg);
- if (!cmd)
- return;
-
- if (!l_genl_attr_init(&attr, msg))
- return;
-
- while (l_genl_attr_next(&attr, &type, &len, &data)) {
- switch (type) {
- case NL80211_ATTR_IFINDEX:
- if (len != sizeof(uint32_t)) {
- l_warn("Invalid interface index attribute");
- return;
- }
-
- ifindex = *((uint32_t *) data);
-
- break;
- case NL80211_ATTR_FRAME:
- if (mpdu)
- return;
-
- mpdu = mpdu_validate(data, len);
- if (!mpdu)
- l_error("Frame didn't validate as MMPDU");
-
- frame_len = len;
- break;
- }
- }
+ *ptr++ = 0x7f;
+ *ptr++ = IE_ADVERTISEMENT_ANQP;
+ l_put_le16(len, ptr);
+ ptr += 2;
- if (!ifindex || !mpdu)
- return;
+ memcpy(ptr, anqp, len);
+ ptr += len;
- body = mmpdu_body(mpdu);
+ *len_out = ptr - frame;
- anqp_response_frame_event(ifindex, mpdu, body,
- (const uint8_t *) mpdu + frame_len - body);
+ return frame;
}
-static void anqp_mlme_notify(struct l_genl_msg *msg, void *user_data)
+bool anqp_request(uint64_t wdev_id, const uint8_t *addr,
+ struct scan_bss *bss, const uint8_t *anqp,
+ size_t len, anqp_response_func_t cb,
+ void *user_data, anqp_destroy_func_t destroy)
{
- struct l_genl_attr attr;
- uint16_t type, len;
- const void *data;
- uint8_t cmd;
- uint32_t ifindex = 0;
-
- if (l_queue_isempty(anqp_requests))
- return;
+ struct anqp_request *request;
- cmd = l_genl_msg_get_command(msg);
+ request = l_new(struct anqp_request, 1);
- l_debug("MLME notification %s(%u)", nl80211cmd_to_string(cmd), cmd);
+ request->wdev_id = wdev_id;
+ request->frequency = bss->frequency;
+ request->anqp_cb = cb;
+ request->anqp_destroy = destroy;
+ request->anqp_token = anqp_token;
+ request->anqp_data = user_data;
- if (!l_genl_attr_init(&attr, msg))
- return;
+ request->frame = anqp_build_frame(addr, bss, anqp, len,
+ &request->frame_len);
- while (l_genl_attr_next(&attr, &type, &len, &data)) {
- switch (type) {
- case NL80211_ATTR_IFINDEX:
- if (len != sizeof(uint32_t)) {
- l_warn("Invalid interface index attribute");
- return;
- }
-
- ifindex = *((uint32_t *) data);
- break;
- }
- }
+ l_queue_push_head(anqp_requests, request);
- if (!ifindex) {
- l_warn("MLME notification is missing ifindex attribute");
- return;
- }
+ if (l_queue_length(anqp_requests) == 1)
+ anqp_request_next();
- switch (cmd) {
- case NL80211_CMD_FRAME_WAIT_CANCEL:
- anqp_frame_wait_cancel_event(msg, ifindex);
- break;
- }
+ return true;
}
static int anqp_init(void)
{
- struct l_genl *genl = iwd_get_genl();
-
- nl80211 = l_genl_family_new(genl, NL80211_GENL_NAME);
-
anqp_requests = l_queue_new();
- netdev_watch = netdev_watch_add(anqp_netdev_watch, NULL, NULL);
-
- unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
- anqp_unicast_notify,
- NULL, NULL);
-
- if (!l_genl_family_register(nl80211, "mlme", anqp_mlme_notify,
- NULL, NULL))
- l_error("Registering for MLME notification failed");
-
return 0;
}
static void anqp_exit(void)
{
- struct l_genl *genl = iwd_get_genl();
-
- l_genl_family_free(nl80211);
- nl80211 = NULL;
-
l_queue_destroy(anqp_requests, anqp_destroy);
-
- netdev_watch_remove(netdev_watch);
-
- l_genl_remove_unicast_watch(genl, unicast_watch);
}
IWD_MODULE(anqp, anqp_init, anqp_exit);
-IWD_MODULE_DEPENDS(anqp, netdev);
diff --git a/src/anqp.h b/src/anqp.h
index 998277dd..99af76d5 100644
--- a/src/anqp.h
+++ b/src/anqp.h
@@ -34,7 +34,7 @@ typedef void (*anqp_response_func_t)(enum anqp_result result,
const void *anqp, size_t len,
void *user_data);
-uint32_t anqp_request(uint32_t ifindex, const uint8_t *addr,
+bool anqp_request(uint64_t wdev_id, const uint8_t *addr,
struct scan_bss *bss, const uint8_t *anqp, size_t len,
anqp_response_func_t cb, void *user_data,
anqp_destroy_func_t destroy);
diff --git a/src/station.c b/src/station.c
index c532319a..29f94e3b 100644
--- a/src/station.c
+++ b/src/station.c
@@ -104,7 +104,6 @@ struct station {
struct anqp_entry {
struct station *station;
struct network *network;
- uint32_t pending;
};
struct wiphy *station_get_wiphy(struct station *station)
@@ -447,12 +446,9 @@ static void station_anqp_response_cb(enum anqp_result result,
char **realms = NULL;
struct nai_search search;
- entry->pending = 0;
-
l_debug("");
- if (result == ANQP_TIMEOUT) {
- l_queue_remove(station->anqp_pending, entry);
+ if (result != ANQP_SUCCESS) {
/* TODO: try next BSS */
goto request_done;
}
@@ -551,12 +547,10 @@ static bool station_start_anqp(struct station *station, struct network *network,
* these are checked in hs20_find_settings_file.
*/
- entry->pending = anqp_request(netdev_get_ifindex(station->netdev),
- netdev_get_address(station->netdev),
- bss, anqp, ptr - anqp,
- station_anqp_response_cb,
- entry, l_free);
- if (!entry->pending) {
+ if (!anqp_request(netdev_get_wdev_id(station->netdev),
+ netdev_get_address(station->netdev), bss, anqp,
+ ptr - anqp, station_anqp_response_cb,
+ entry, l_free)) {
l_free(entry);
return false;
}
--
2.21.1
2 years
Re: Wifi Tethering
by Daniel Wagner
[Cc: iwd mailing list]
On Tue, Apr 28, 2020 at 06:45:25AM -0500, KeithG wrote:
> Daniel,
>
> I built the kernel/modules (I am on Arch on an RPi and the kernel I am
> using is 4.19.114) and tried to diagnose the ap mode problem with nlmon and
> get this, though I am sure I am doing it wrong:
> # modprobe nlmon
> # ip link add name nlmon type nlmon
> # ip link set dev nlmon allmulticast on
> # ip link set dev nlmon up
> # tcpdump -i nlmon -w trace-file.pcap
> tcpdump: listening on nlmon, link-type NETLINK (Linux netlink), capture
> size 262144 bytes
> ^C158 packets captured
> 163 packets received by filter
> 0 packets dropped by kernel
> # iwmon -r trace-file.pcap
> Wireless monitor ver 1.6
> Invalid packet format
Could you upload the pcap file somewhere? I suppose the iwd developers might
be interested to inspect it.
> In another window, I did this to see what was going on:
> ~# connmanctl tether wifi on myssid password
> Wifi SSID set
> Wifi passphrase set
> Enabled tethering for wifi
> # ip addr
> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
> default qlen 1000
> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
> inet 127.0.0.1/8 scope host lo
> valid_lft forever preferred_lft forever
> inet6 ::1/128 scope host
> valid_lft forever preferred_lft forever
> 2: eth0: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc fq_codel
> state UP group default qlen 1000
> link/ether a0:ce:c8:12:ed:05 brd ff:ff:ff:ff:ff:ff
> inet 192.168.2.25/24 brd 192.168.2.255 scope global eth0
> valid_lft forever preferred_lft forever
> inet6 fe80::a2ce:c8ff:fe12:ed05/64 scope link
> valid_lft forever preferred_lft forever
> 3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
> fq_codel master tether state DORMANT group default qlen 1000
> link/ether b8:27:eb:28:18:48 brd ff:ff:ff:ff:ff:ff
> 4: nlmon: <NOARP,ALLMULTI,UP,LOWER_UP> mtu 3904 qdisc noqueue state UNKNOWN
> group default qlen 1000
> link/netlink
> 5: tether: <NO-CARRIER,BROADCAST,MULTICAST,DYNAMIC,UP> mtu 1500 qdisc
> noqueue state DOWN group default qlen 1000
> link/ether 9a:69:3a:48:c1:32 brd ff:ff:ff:ff:ff:ff
> inet 192.168.0.1/24 brd 192.168.0.255 scope global tether
> valid_lft forever preferred_lft forever
> inet6 fe80::c20:faff:fec4:92b9/64 scope link
> valid_lft forever preferred_lft forever
>
> I tried to connect to this AP with my Win10 laptop and get the response:
> "Can't connect to this network". My Arch Laptop likewise will not connect.
>
> Now, when I run iwd -d, I get this:
> # /usr/lib/iwd/iwd -d
> No Diffie-Hellman support found, WPS will not be available
> No asymmetric key support found.
> TLS based WPA-Enterprise authentication methods will not function.
> Kernel 4.20+ is required for this feature.
> The following options are missing in the kernel:
> CONFIG_ASYMMETRIC_KEY_TYPE
> CONFIG_KEY_DH_OPERATIONS
> CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE
> CONFIG_PKCS7_MESSAGE_PARSER
> CONFIG_X509_CERTIFICATE_PARSER
> CONFIG_PKCS8_PRIVATE_KEY_PARSER
> Wireless daemon version 1.6
> src/main.c:main() Using configuration directory /etc/iwd
> src/storage.c:storage_create_dirs() Using state directory /var/lib/iwd
> src/main.c:nl80211_appeared() Found nl80211 interface
> src/module.c:iwd_modules_init()
> src/netdev.c:netdev_init() Opening route netlink socket
> netconfig: Network configuration is disabled.
> src/wsc.c:wsc_init()
> src/eap.c:__eap_method_enable()
> src/eap-wsc.c:eap_wsc_init()
> src/eap-md5.c:eap_md5_init()
> src/eap-tls.c:eap_tls_init()
> src/eap-ttls.c:eap_ttls_init()
> src/eap-mschapv2.c:eap_mschapv2_init()
> src/eap-sim.c:eap_sim_init()
> src/eap-aka.c:eap_aka_prime_init()
> src/eap-aka.c:eap_aka_init()
> src/eap-peap.c:eap_peap_init()
> src/eap-gtc.c:eap_gtc_init()
> src/eap-pwd.c:eap_pwd_init()
> plugins/sim_hardcoded.c:sim_hardcoded_init() IWD_SIM_KEYS not set in env
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/wiphy.c:parse_supported_frequencies()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/wiphy.c:parse_supported_bands()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/manager.c:manager_wiphy_dump_callback()
> src/wiphy.c:wiphy_update_from_genl()
> src/agent.c:agent_register() agent register called
> src/agent.c:agent_register() agent :1.7 path /net/connman/iwd_agent
> Wiphy: 0, Name: phy0
> Permanent Address: b8:27:eb:28:18:48
> Bands: 2.4 GHz
> Ciphers: CCMP TKIP
> Supported iftypes: ad-hoc station ap p2p-client p2p-go p2p-device
> Wiphy phy0 will only use the default interface
> src/manager.c:manager_interface_dump_callback()
> src/manager.c:manager_get_interface_cb()
> src/manager.c:manager_use_default()
> src/netdev.c:netdev_create_from_genl() Created interface wlan0[3 1]
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_set_4addr() netdev: 3 use_4addr: 0
> src/netdev.c:netdev_initial_up_cb() Interface 3 initialized
>
> strange thing is that most of those features are built in the kernel. My
> kernel is 4.19.114 and the config specifies:
> # CONFIG_CRYPTO_HW is not set
> CONFIG_ASYMMETRIC_KEY_TYPE=y
> CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
> CONFIG_X509_CERTIFICATE_PARSER=y
> CONFIG_PKCS7_MESSAGE_PARSER=y
> I am currently re-building the kernel with:
> CONFIG_KEY_DH_OPERATIONS=y
> as it was previously not set.
> There does not seem to be any reference to PKCS8 for this kernel.
>
> Thanks!
>
> Keith
>
> On Mon, Apr 27, 2020 at 2:36 AM Daniel Wagner <wagi(a)monom.org> wrote:
>
> > On Sat, Apr 25, 2020 at 11:20:45AM -0500, KeithG wrote:
> > > I looked at the IWD readme and cannot enable this on the RPi:
> > >
> > > # ip link set dev nlmon allmulticast on
> > > > Cannot find device "nlmon"
> >
> > The RPi kernel has no support for nlmon enabled. If you want to debug this
> > you
> > propably need to compile your own RPi kernel with nlmon enabled.
> >
> > > I did verify a couple things. I do have iwd set explicitly when I start
> > > connman
> > > /usr/bin/connmand --wifi=iwd_agent -n --nodnsproxy
> >
> > --wifi=iwd_agent is wrong. If you want iwd support you need to define this
> > at compile time only:
> >
> > ./configure --enable-iwd --disable-wifi
> >
> > which adds the iwd plugin and disables the wpa_supplicant plugin. But I
> > don't
> > think it matter. --iwfi-iwd_agent will be ignored and ConnMan will
> > dynamically
> > discover iwd. Just make sure wpa_supplicant is not running. With the above
> > command line you would make sure wpa_supplicant is not accidentally used.
> >
> > > When I issue the command from connman, the mode changes in iwd:
> > >
> > > > # connmanctl tether wifi on myssid password
> > > > Wifi SSID set
> > > > Wifi passphrase set
> > > > Enabled tethering for wifi
> > > > # ip addr
> > > > 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
> > group
> > > > default qlen 1000
> > > > link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
> > > > inet 127.0.0.1/8 scope host lo
> > > > valid_lft forever preferred_lft forever
> > > > inet6 ::1/128 scope host
> > > > valid_lft forever preferred_lft forever
> > > > 2: eth0: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 qdisc
> > fq_codel
> > > > state UP group default qlen 1000
> > > > link/ether a0:ce:c8:12:ed:05 brd ff:ff:ff:ff:ff:ff
> > > > inet 192.168.2.25/24 brd 192.168.2.255 scope global eth0
> > > > valid_lft forever preferred_lft forever
> > > > inet6 fe80::a2ce:c8ff:fe12:ed05/64 scope link
> > > > valid_lft forever preferred_lft forever
> > > > 3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
> > > > fq_codel master tether state DORMANT group default qlen 1000
> > > > link/ether b8:27:eb:28:18:48 brd ff:ff:ff:ff:ff:ff
> > > > 4: tether: <NO-CARRIER,BROADCAST,MULTICAST,DYNAMIC,UP> mtu 1500 qdisc
> > > > noqueue state DOWN group default qlen 1000
> > > > link/ether 9a:69:3a:48:c1:32 brd ff:ff:ff:ff:ff:ff
> > > > inet 192.168.0.1/24 brd 192.168.0.255 scope global tether
> > > > valid_lft forever preferred_lft forever
> > > > inet6 fe80::d024:5eff:fe80:1a57/64 scope link
> > > > valid_lft forever preferred_lft forever
> > > > # iwctl device wlan0 show
> > > > Device: wlan0
> > > >
> > > >
> > --------------------------------------------------------------------------------
> > > > Settable Property Value
> > > >
> > > >
> > --------------------------------------------------------------------------------
> > > > Name wlan0
> > > > * Mode ap
> > > > * Powered on
> > > > Address b8:27:eb:28:18:48
> > > > Adapter phy0
> > > >
> > >
> > > I get these responses in the journal when I try to connect but it never
> > > connects:
> > >
> > > > src/netdev.c:netdev_mlme_notify() MLME notification New Station(19)
> > > > src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
> > > > src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
> > > >
> >
> > Did you try to run iwd with debug enabled 'iwd -d'? Maybe there is more
> > info. And if there isn't any clue, the best way forward is to get
> > nlmon running and provide the information the iwd developers. From what I
> > see ConnMan is talking to iwd and setups the AP mode.
> >
> > > I currently use hostapd and dnsmasq to have this headless RPi audio
> > > appliance work as an AP for initial setup, but want to remove hostapd and
> > > dnsmasq if I can get connman/iwd to do the same thing. I tried to get iwd
> > > to go into ap mode and connect, but cannot do it there, either. I do get
> > > some messages at startup of iwd. I do not think these are the problem,
> > but
> > > they are missing kernel modules:
> > >
> > > No Diffie-Hellman support found, WPS will not be available
> > > > No asymmetric key support found.
> > > > TLS based WPA-Enterprise authentication methods will not function.
> > > > Kernel 4.20+ is required for this feature.
> > > > The following options are missing in the kernel:
> > > > CONFIG_ASYMMETRIC_KEY_TYPE
> > > > CONFIG_KEY_DH_OPERATIONS
> > > > CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE
> > > > CONFIG_PKCS7_MESSAGE_PARSER
> > > > CONFIG_X509_CERTIFICATE_PARSER
> > > > CONFIG_PKCS8_PRIVATE_KEY_PARSER
> > > > Wireless daemon version 1.6
> >
> > I don't know but I would suggest to address this in the same go when you
> > build
> > a new kernel with nlmon support.
> >
> > Thanks,
> > Daniel
> >
2 years
[PATCH v2] auto-t: Test Agent ops
by Tim Kourt
---
autotests/testAgent/agent_test.py | 100 ++++++++++++++++++++++++++++++++++++++
autotests/testAgent/hw.conf | 7 +++
autotests/testAgent/ssid1.conf | 7 +++
autotests/testAgent/ssid2.conf | 7 +++
4 files changed, 121 insertions(+)
create mode 100644 autotests/testAgent/agent_test.py
create mode 100644 autotests/testAgent/hw.conf
create mode 100644 autotests/testAgent/ssid1.conf
create mode 100644 autotests/testAgent/ssid2.conf
diff --git a/autotests/testAgent/agent_test.py b/autotests/testAgent/agent_test.py
new file mode 100644
index 00000000..80d2ce83
--- /dev/null
+++ b/autotests/testAgent/agent_test.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python3
+
+import unittest
+import sys
+
+sys.path.append('../util')
+import iwd
+from iwd import IWD
+from iwd import PSKAgent
+from iwd import NetworkType
+import testutil
+import subprocess
+
+class Test(unittest.TestCase):
+
+ def check_connection(self, wd, ssid):
+
+ device = wd.list_devices(1)[0]
+ ordered_network = device.get_ordered_network(ssid, scan_if_needed=True)
+
+ ordered_network.network_object.connect()
+
+ condition = 'obj.state == DeviceState.connected'
+ wd.wait_for_object_condition(device, condition)
+
+ condition = 'obj.connected_network is not None'
+ wd.wait_for_object_condition(device, condition)
+
+ testutil.test_iface_operstate(device.name)
+ device.disconnect()
+
+ condition = 'obj.state == DeviceState.disconnected'
+ wd.wait_for_object_condition(device, condition)
+
+ def test_connection_with_no_agent(self):
+
+ wd = IWD()
+
+ with self.assertRaises(iwd.NoAgentEx):
+ self.check_connection(wd, 'ssid1')
+
+ IWD.clear_storage()
+
+ def test_connection_with_own_agent(self):
+
+ wd = IWD()
+
+ psk_agent = PSKAgent("secret_ssid1")
+ wd.register_psk_agent(psk_agent)
+
+ self.check_connection(wd, 'ssid1')
+
+ wd.unregister_psk_agent(psk_agent)
+
+ IWD.clear_storage()
+
+ def test_connection_with_other_agent(self):
+ wd = IWD()
+
+ iwctl = subprocess.Popen(['iwctl', '-P', 'secret_ssid2'])
+ # Let iwctl to start and register its agent.
+ wd.wait(2)
+
+ self.check_connection(wd, 'ssid2')
+
+ iwctl.terminate()
+ iwctl.communicate()
+
+ IWD.clear_storage()
+
+ def test_connection_use_own_agent_from_multiple_registered(self):
+
+ wd = IWD()
+
+ iwctl = subprocess.Popen(['iwctl', '-P', 'secret_ssid2'])
+ # Let iwctl to start and register its agent.
+ wd.wait(2)
+
+ psk_agent = PSKAgent("secret_ssid1")
+ wd.register_psk_agent(psk_agent)
+
+ self.check_connection(wd, 'ssid1')
+
+ wd.unregister_psk_agent(psk_agent)
+
+ iwctl.terminate()
+ iwctl.communicate()
+
+ IWD.clear_storage()
+
+ @classmethod
+ def setUpClass(cls):
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ IWD.clear_storage()
+
+if __name__ == '__main__':
+ unittest.main(exit=True)
diff --git a/autotests/testAgent/hw.conf b/autotests/testAgent/hw.conf
new file mode 100644
index 00000000..53249c9c
--- /dev/null
+++ b/autotests/testAgent/hw.conf
@@ -0,0 +1,7 @@
+[SETUP]
+num_radios=3
+max_test_exec_interval_sec=40
+
+[HOSTAPD]
+rad0=ssid1.conf
+rad1=ssid2.conf
diff --git a/autotests/testAgent/ssid1.conf b/autotests/testAgent/ssid1.conf
new file mode 100644
index 00000000..2416d53a
--- /dev/null
+++ b/autotests/testAgent/ssid1.conf
@@ -0,0 +1,7 @@
+hw_mode=g
+channel=1
+ssid=ssid1
+
+wpa=1
+wpa_pairwise=TKIP
+wpa_passphrase=secret_ssid1
diff --git a/autotests/testAgent/ssid2.conf b/autotests/testAgent/ssid2.conf
new file mode 100644
index 00000000..69b4f000
--- /dev/null
+++ b/autotests/testAgent/ssid2.conf
@@ -0,0 +1,7 @@
+hw_mode=g
+channel=1
+ssid=ssid2
+
+wpa=1
+wpa_pairwise=TKIP
+wpa_passphrase=secret_ssid2
--
2.13.6
2 years, 1 month
[PATCH] auto-t: Test Agent ops
by Tim Kourt
---
autotests/testAgent/agent_test.py | 100 ++++++++++++++++++++++++++++++++++++++
autotests/testAgent/hw.conf | 7 +++
autotests/testAgent/ssid1.conf | 7 +++
autotests/testAgent/ssid2.conf | 8 +++
4 files changed, 122 insertions(+)
create mode 100644 autotests/testAgent/agent_test.py
create mode 100644 autotests/testAgent/hw.conf
create mode 100644 autotests/testAgent/ssid1.conf
create mode 100644 autotests/testAgent/ssid2.conf
diff --git a/autotests/testAgent/agent_test.py b/autotests/testAgent/agent_test.py
new file mode 100644
index 00000000..80d2ce83
--- /dev/null
+++ b/autotests/testAgent/agent_test.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python3
+
+import unittest
+import sys
+
+sys.path.append('../util')
+import iwd
+from iwd import IWD
+from iwd import PSKAgent
+from iwd import NetworkType
+import testutil
+import subprocess
+
+class Test(unittest.TestCase):
+
+ def check_connection(self, wd, ssid):
+
+ device = wd.list_devices(1)[0]
+ ordered_network = device.get_ordered_network(ssid, scan_if_needed=True)
+
+ ordered_network.network_object.connect()
+
+ condition = 'obj.state == DeviceState.connected'
+ wd.wait_for_object_condition(device, condition)
+
+ condition = 'obj.connected_network is not None'
+ wd.wait_for_object_condition(device, condition)
+
+ testutil.test_iface_operstate(device.name)
+ device.disconnect()
+
+ condition = 'obj.state == DeviceState.disconnected'
+ wd.wait_for_object_condition(device, condition)
+
+ def test_connection_with_no_agent(self):
+
+ wd = IWD()
+
+ with self.assertRaises(iwd.NoAgentEx):
+ self.check_connection(wd, 'ssid1')
+
+ IWD.clear_storage()
+
+ def test_connection_with_own_agent(self):
+
+ wd = IWD()
+
+ psk_agent = PSKAgent("secret_ssid1")
+ wd.register_psk_agent(psk_agent)
+
+ self.check_connection(wd, 'ssid1')
+
+ wd.unregister_psk_agent(psk_agent)
+
+ IWD.clear_storage()
+
+ def test_connection_with_other_agent(self):
+ wd = IWD()
+
+ iwctl = subprocess.Popen(['iwctl', '-P', 'secret_ssid2'])
+ # Let iwctl to start and register its agent.
+ wd.wait(2)
+
+ self.check_connection(wd, 'ssid2')
+
+ iwctl.terminate()
+ iwctl.communicate()
+
+ IWD.clear_storage()
+
+ def test_connection_use_own_agent_from_multiple_registered(self):
+
+ wd = IWD()
+
+ iwctl = subprocess.Popen(['iwctl', '-P', 'secret_ssid2'])
+ # Let iwctl to start and register its agent.
+ wd.wait(2)
+
+ psk_agent = PSKAgent("secret_ssid1")
+ wd.register_psk_agent(psk_agent)
+
+ self.check_connection(wd, 'ssid1')
+
+ wd.unregister_psk_agent(psk_agent)
+
+ iwctl.terminate()
+ iwctl.communicate()
+
+ IWD.clear_storage()
+
+ @classmethod
+ def setUpClass(cls):
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ IWD.clear_storage()
+
+if __name__ == '__main__':
+ unittest.main(exit=True)
diff --git a/autotests/testAgent/hw.conf b/autotests/testAgent/hw.conf
new file mode 100644
index 00000000..53249c9c
--- /dev/null
+++ b/autotests/testAgent/hw.conf
@@ -0,0 +1,7 @@
+[SETUP]
+num_radios=3
+max_test_exec_interval_sec=40
+
+[HOSTAPD]
+rad0=ssid1.conf
+rad1=ssid2.conf
diff --git a/autotests/testAgent/ssid1.conf b/autotests/testAgent/ssid1.conf
new file mode 100644
index 00000000..2416d53a
--- /dev/null
+++ b/autotests/testAgent/ssid1.conf
@@ -0,0 +1,7 @@
+hw_mode=g
+channel=1
+ssid=ssid1
+
+wpa=1
+wpa_pairwise=TKIP
+wpa_passphrase=secret_ssid1
diff --git a/autotests/testAgent/ssid2.conf b/autotests/testAgent/ssid2.conf
new file mode 100644
index 00000000..e1555c31
--- /dev/null
+++ b/autotests/testAgent/ssid2.conf
@@ -0,0 +1,8 @@
+hw_mode=g
+channel=1
+ssid=ssid2
+
+wpa=1
+wpa_pairwise=TKIP
+wpa_passphrase=secret_ssid2
+
--
2.13.6
2 years, 1 month
[PATCH v2 1/2] netdev: unify ft/auth_proto authenticate builders
by James Prestwood
build_cmd_ft_authenticate and build_cmd_authenticate were virtually
identical. These have been unified into a single builder.
We were also incorrectly including ATTR_IE to every authenticate
command, which violates the spec for certain protocols, This was
removed and any auth protocols will now add any IEs that they require.
---
src/netdev.c | 46 ++++++++--------------------------------------
1 file changed, 8 insertions(+), 38 deletions(-)
diff --git a/src/netdev.c b/src/netdev.c
index b3c3bf73..e469fb1c 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -2129,8 +2129,7 @@ static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
}
static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
- uint32_t auth_type,
- const uint8_t *addr)
+ uint32_t auth_type)
{
struct handshake_state *hs = netdev->handshake;
struct l_genl_msg *msg;
@@ -2139,13 +2138,11 @@ static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
4, &netdev->frequency);
- l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+ l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN,
+ netdev->handshake->aa);
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
- l_genl_msg_append_attr(msg, NL80211_ATTR_IE, hs->supplicant_ie[1] + 2,
- hs->supplicant_ie);
-
return msg;
}
@@ -2181,8 +2178,7 @@ static void netdev_sae_tx_authenticate(const uint8_t *body,
struct netdev *netdev = user_data;
struct l_genl_msg *msg;
- msg = netdev_build_cmd_authenticate(netdev, NL80211_AUTHTYPE_SAE,
- netdev->handshake->aa);
+ msg = netdev_build_cmd_authenticate(netdev, NL80211_AUTHTYPE_SAE);
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_DATA, body_len, body);
@@ -2228,8 +2224,7 @@ static void netdev_owe_tx_authenticate(void *user_data)
struct l_genl_msg *msg;
msg = netdev_build_cmd_authenticate(netdev,
- NL80211_AUTHTYPE_OPEN_SYSTEM,
- netdev->handshake->aa);
+ NL80211_AUTHTYPE_OPEN_SYSTEM);
if (!l_genl_family_send(nl80211, msg, netdev_auth_cb,
netdev, NULL)) {
@@ -2265,8 +2260,7 @@ static void netdev_fils_tx_authenticate(const uint8_t *body,
struct netdev *netdev = user_data;
struct l_genl_msg *msg;
- msg = netdev_build_cmd_authenticate(netdev, NL80211_AUTHTYPE_FILS_SK,
- netdev->handshake->aa);
+ msg = netdev_build_cmd_authenticate(netdev, NL80211_AUTHTYPE_FILS_SK);
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_DATA, body_len, body);
@@ -2941,30 +2935,6 @@ static uint32_t netdev_send_action_frame(struct netdev *netdev,
return netdev_send_action_framev(netdev, to, iov, 1, freq, callback);
}
-/*
- * Build an FT Authentication Request frame according to 12.5.2 / 12.5.4:
- * RSN or non-RSN Over-the-air FT Protocol, with the IE contents
- * according to 12.8.2: FT authentication sequence: contents of first message.
- */
-static struct l_genl_msg *netdev_build_cmd_ft_authenticate(
- struct netdev *netdev,
- const struct handshake_state *hs)
-{
- uint32_t auth_type = NL80211_AUTHTYPE_FT;
- struct l_genl_msg *msg;
-
- msg = l_genl_msg_new_sized(NL80211_CMD_AUTHENTICATE, 512);
- l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
- l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
- 4, &netdev->frequency);
- l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
- l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
- l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
-
- return msg;
-
-}
-
static void netdev_cmd_authenticate_ft_cb(struct l_genl_msg *msg,
void *user_data)
{
@@ -2984,8 +2954,8 @@ static void netdev_ft_tx_authenticate(struct iovec *iov,
struct netdev *netdev = user_data;
struct l_genl_msg *cmd_authenticate;
- cmd_authenticate = netdev_build_cmd_ft_authenticate(netdev,
- netdev->handshake);
+ cmd_authenticate = netdev_build_cmd_authenticate(netdev,
+ NL80211_AUTHTYPE_FT);
if (!cmd_authenticate)
goto restore_snonce;
--
2.21.1
2 years, 1 month
[PATCH 1/5] auto-t: Remove unnecessary disconnect calls
by Tim Kourt
With the introduction of AutoConnect=False network setting the
initial disconnect calls are no longer needed
---
autotests/testAP/failure_test.py | 2 --
autotests/testAP/test.py | 2 --
2 files changed, 4 deletions(-)
diff --git a/autotests/testAP/failure_test.py b/autotests/testAP/failure_test.py
index cad7bf6e..d419c05b 100644
--- a/autotests/testAP/failure_test.py
+++ b/autotests/testAP/failure_test.py
@@ -58,8 +58,6 @@ class Test(unittest.TestCase):
wd = IWD()
dev1, dev2 = wd.list_devices(2)
- dev1.disconnect()
- dev2.disconnect()
self.client_connect(wd, dev1)
diff --git a/autotests/testAP/test.py b/autotests/testAP/test.py
index 39161981..455c9916 100644
--- a/autotests/testAP/test.py
+++ b/autotests/testAP/test.py
@@ -51,8 +51,6 @@ class Test(unittest.TestCase):
wd = IWD()
dev1, dev2 = wd.list_devices(2)
- dev1.disconnect()
- dev2.disconnect()
self.client_connect(wd, dev1)
--
2.13.6
2 years, 1 month
[PATCH] netdev: don't include ATTR_IE for SAE
by James Prestwood
The spec outlines what fields/elements can be included with different
auth types. For SAE only a few fields are allowed. IE's are not allowed
but were being included with CMD_AUTHENTICATE.
---
src/netdev.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/netdev.c b/src/netdev.c
index b3c3bf73..bce6ada3 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -2143,7 +2143,15 @@ static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
- l_genl_msg_append_attr(msg, NL80211_ATTR_IE, hs->supplicant_ie[1] + 2,
+ /*
+ * IEEE 802.11-2016 Table 9-36 Presents of fields in Auth frames
+ *
+ * For the SAE auth type no IEs are listed to be included in the
+ * authenticate frame. Only SAE related fields should be included.
+ */
+ if (auth_type != NL80211_AUTHTYPE_SAE)
+ l_genl_msg_append_attr(msg, NL80211_ATTR_IE,
+ hs->supplicant_ie[1] + 2,
hs->supplicant_ie);
return msg;
--
2.21.1
2 years, 1 month