From patchwork Mon Aug 22 18:25:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951030 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 199F04A02 for ; Mon, 22 Aug 2022 18:25:33 +0000 (UTC) Received: by mail-pl1-f182.google.com with SMTP id v23so5399004plo.9 for ; Mon, 22 Aug 2022 11:25:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=8sFP2wUffrdzvdYya0knROp5q2bk9q9P+Z4NTzglWLQ=; b=bX22hujOyc4AdM8DBqX1OJDXdWxDl2fCYxmEGszvaiDc4dQXAft/Cmwl1jOpybQr3L pB3cumFN8UJOEF2r+hsK4tr5WmmFiT7rRLKgJzoJ6DkknDdEEAcrJ0v2bD/1IbEYQvoI RvqCatr0yWOjE3KBodqbTxWSXULk4KsxAZ674nwfokjYruxahcP8njcj4WbLCP4MLHdh W7tkXF+oIri9VhDM7uTA2BlekPCkdttbRXITvcYsPEDgsR4nA+eDn/wWEg+NV21PV8be FYTlw8b5ZXl1MIbMKDr25MmN0YfEJs1HLAC0wgJVHF9rxGafcfbbnt05KmFeetknKYhh DpKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=8sFP2wUffrdzvdYya0knROp5q2bk9q9P+Z4NTzglWLQ=; b=7f70OHXhG2Zb4nI2eNWnCE3QAxdqgwf95W2jm+UxIfEj3WR/rsOvk8WrtNebRJQMmU LRIr5w7OJCtTgrCXv6zBk1mThtF2VwMFw3VI3oKkBrMPpBBMtvesaEYUG8cXqp8CzWud SJzaQiFdBIk28DhR/7ooTY1itJVffCh9E2mH6KoNV1cKY6G4VI9I2pNRWW6qbjIH4AuX k9E9ivorMH+3zg/tTP7BRMpkhPZk2aLOgNjzL91s3mbR3gnYl1w7zLdLKV59ml1pVxII l6FHJiYbD87bjTwYpd8JSnDNeRzGY4Jdy9vTsGrv3Z1AAwyH1jI+u/vQK6hxk+AJc4Y+ H8pg== X-Gm-Message-State: ACgBeo0bCHH6Qi2l4zBcymlrvaGBZ+S5FjXYzCNiROOg29sYZboQkXrU KDTcGZ56hlPb8/gX7nHqUOypNCwr1jg= X-Google-Smtp-Source: AA6agR7cEiLw/iFy+mwzvU9oOl7XHt5rdGyblWGawW/iwAUcnu2QRwaZP+DhCmc/CptERwQymye2Zw== X-Received: by 2002:a17:902:8b87:b0:16f:1bb7:984a with SMTP id ay7-20020a1709028b8700b0016f1bb7984amr20956407plb.113.1661192732355; Mon, 22 Aug 2022 11:25:32 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:32 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 1/9] frame-xchg: add type to frame_xchg_prefix Date: Mon, 22 Aug 2022 11:25:17 -0700 Message-Id: <20220822182525.2078312-1-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 All uses of frame-xchg were for action frames, and the frame type was hard coded. Soon other frame types will be needed so the type must now be specified in the frame_xchg_prefix structure. --- src/anqp.c | 1 + src/frame-xchg.c | 2 +- src/frame-xchg.h | 1 + src/p2p.c | 4 ++++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/anqp.c b/src/anqp.c index 8febdf91..a3c3d7ed 100644 --- a/src/anqp.c +++ b/src/anqp.c @@ -156,6 +156,7 @@ static bool anqp_response_frame_event(const struct mmpdu_header *hdr, } static const struct frame_xchg_prefix anqp_frame_prefix = { + .frame_type = 0x00d0, .data = (uint8_t []) { 0x04, 0x0b, }, diff --git a/src/frame-xchg.c b/src/frame-xchg.c index 5ba36081..158befd0 100644 --- a/src/frame-xchg.c +++ b/src/frame-xchg.c @@ -1193,7 +1193,7 @@ uint32_t frame_xchg_startv(uint64_t wdev_id, struct iovec *frame, uint32_t freq, watch = l_new(struct frame_xchg_watch_data, 1); watch->prefix = prefix; watch->cb = va_arg(resp_args, void *); - frame_watch_add(wdev_id, group_id, 0x00d0, + frame_watch_add(wdev_id, group_id, prefix->frame_type, prefix->data, prefix->len, frame_xchg_resp_cb, fx, NULL); diff --git a/src/frame-xchg.h b/src/frame-xchg.h index e3748538..360bb4d4 100644 --- a/src/frame-xchg.h +++ b/src/frame-xchg.h @@ -32,6 +32,7 @@ typedef void (*frame_xchg_cb_t)(int err, void *user_data); typedef void (*frame_xchg_destroy_func_t)(void *user_data); struct frame_xchg_prefix { + uint16_t frame_type; const uint8_t *data; size_t len; }; diff --git a/src/p2p.c b/src/p2p.c index ff3b8e45..45a1b70b 100644 --- a/src/p2p.c +++ b/src/p2p.c @@ -820,6 +820,7 @@ static void p2p_peer_frame_xchg(struct p2p_peer *peer, struct iovec *tx_body, static const struct frame_xchg_prefix p2p_frame_go_neg_req = { /* Management -> Public Action -> P2P -> GO Negotiation Request */ + .frame_type = 0x00d0, .data = (uint8_t []) { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09, P2P_ACTION_GO_NEGOTIATION_REQ @@ -829,6 +830,7 @@ static const struct frame_xchg_prefix p2p_frame_go_neg_req = { static const struct frame_xchg_prefix p2p_frame_go_neg_resp = { /* Management -> Public Action -> P2P -> GO Negotiation Response */ + .frame_type = 0x00d0, .data = (uint8_t []) { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09, P2P_ACTION_GO_NEGOTIATION_RESP @@ -838,6 +840,7 @@ static const struct frame_xchg_prefix p2p_frame_go_neg_resp = { static const struct frame_xchg_prefix p2p_frame_go_neg_confirm = { /* Management -> Public Action -> P2P -> GO Negotiation Confirm */ + .frame_type = 0x00d0, .data = (uint8_t []) { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09, P2P_ACTION_GO_NEGOTIATION_CONFIRM @@ -847,6 +850,7 @@ static const struct frame_xchg_prefix p2p_frame_go_neg_confirm = { static const struct frame_xchg_prefix p2p_frame_pd_resp = { /* Management -> Public Action -> P2P -> Provision Discovery Response */ + .frame_type = 0x00d0, .data = (uint8_t []) { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x09, P2P_ACTION_PROVISION_DISCOVERY_RESP From patchwork Mon Aug 22 18:25:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951031 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC9BE4A17 for ; Mon, 22 Aug 2022 18:25:33 +0000 (UTC) Received: by mail-pl1-f174.google.com with SMTP id c2so10694963plo.3 for ; Mon, 22 Aug 2022 11:25:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=VjVcuI/u0rJMbr1M/MD6lzT4QAzs5eSFQPyZCGKGx6U=; b=Gm8LAKUBQUskOjOexTmhqPUmQw+YGkR7BXgl+1E1YldetUeCcVg1aD45alrTsM0Jx2 H9SfER+igwTRziudhSoGjDUgsgxbhsCeN95pvFnl90mESxglioGtcXipfenNrDUyBDyJ 3M8caw7rwD7LEVTyJmvre3we/EN64sudbdeVG5kKHpXuschsi+RuUn82B7Iwf2ssOw6d E8JsWNECdq031OKhapXI8Qx0jnXt2Lg1taCq9gYreOaRTU9CAtbWscaMrzPKPmmP6PDL zrrYYOj/Ch9xuASzq6APhQviluWB0N6kSdX00Ejs0JkoLiSdr2CLEsPXIcH5ODmw1Ovu owYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=VjVcuI/u0rJMbr1M/MD6lzT4QAzs5eSFQPyZCGKGx6U=; b=WVUq+g3/pphT2G33arEQBRKif73kL/srKzwTZGItXzX8rZiYreAmwMXH1zjkCfHunF urlrW6BzBYOvdRnRKK6dcuXiBUE3AZuP97bL0+ejB0o7bF1AyI17ZK8EXKmATW8s+npI /lHCzqnpf4xUINQJbhfOULDjCnl+EuOMKfHpD40m+lDgUxasqDaRBFU+Dve5DmsTfSbh KNyX6ZDTjr1S/EAJrRiA9UacOQ+ms/EeNYdnsWA3yBQ3KLDMQvuiSFhtBZLyfslMo7rI Cg20qPkZZb9w7COKI5pnxZViZ/qhhg/dIUWQvvcXFwX26J0MzQ46HSVvuQafa2hup1HE naig== X-Gm-Message-State: ACgBeo03jp5ZID+LcX820RV4BXdfptDsBSX1UplLIahTsJxKRfUHlydU uh7kyIgCqdlxZu+IkxVmsLuJNZ28Sbs= X-Google-Smtp-Source: AA6agR7D8E/cAeqe0xE2jiTYfDCDpqoV/HrCGgJM7V3fdrphhwM3/Q3Cv+eUfVAlYHBgjPYI11k6Ug== X-Received: by 2002:a17:903:1ce:b0:16f:145c:a842 with SMTP id e14-20020a17090301ce00b0016f145ca842mr21105040plh.83.1661192733029; Mon, 22 Aug 2022 11:25:33 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:32 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 2/9] ft: netdev: rename structs/APIs to prepare for refactor Date: Mon, 22 Aug 2022 11:25:18 -0700 Message-Id: <20220822182525.2078312-2-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Much of the over-DS processing can be combined with over-air once the authenticate stage is performed via CMD_FRAME. To prepare for this rename all the 'over_ds' structs/APIs so the name makes sense once used with the over-air code path. --- src/ft.c | 17 +++++------ src/ft.h | 17 ++++------- src/netdev.c | 81 ++++++++++++++++++++++++++-------------------------- 3 files changed, 53 insertions(+), 62 deletions(-) diff --git a/src/ft.c b/src/ft.c index 2285a86f..04ae2775 100644 --- a/src/ft.c +++ b/src/ft.c @@ -348,7 +348,7 @@ static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name, return true; } -static int ft_parse_ies(struct handshake_state *hs, +static int parse_ies(struct handshake_state *hs, const uint8_t *authenticator_ie, const uint8_t *ies, size_t ies_len, const uint8_t **mde_out, @@ -471,16 +471,14 @@ static bool mde_equal(const uint8_t *mde1, const uint8_t *mde2) return memcmp(mde1, mde1, mde1[1] + 2) == 0; } -bool ft_over_ds_parse_action_ies(struct ft_ds_info *info, - struct handshake_state *hs, - const uint8_t *ies, - size_t ies_len) +bool ft_parse_ies(struct ft_info *info, struct handshake_state *hs, + const uint8_t *ies, size_t ies_len) { const uint8_t *mde = NULL; const uint8_t *fte = NULL; bool is_rsn = hs->supplicant_ie != NULL; - if (ft_parse_ies(hs, info->authenticator_ie, ies, ies_len, + if (parse_ies(hs, info->authenticator_ie, ies, ies_len, &mde, &fte) < 0) return false; @@ -512,7 +510,7 @@ static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies, if (!ies) goto ft_error; - if (ft_parse_ies(hs, hs->authenticator_ie, ies, ies_len, + if (parse_ies(hs, hs->authenticator_ie, ies, ies_len, &mde, &fte) < 0) goto ft_error; @@ -585,8 +583,7 @@ int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len, return 0; } -bool ft_over_ds_prepare_handshake(struct ft_ds_info *info, - struct handshake_state *hs) +bool ft_prepare_handshake(struct ft_info *info, struct handshake_state *hs) { if (!hs->supplicant_ie) return true; @@ -606,7 +603,7 @@ bool ft_over_ds_prepare_handshake(struct ft_ds_info *info, return true; } -void ft_ds_info_free(struct ft_ds_info *info) +void ft_info_free(struct ft_info *info) { __typeof__(info->free) destroy = info->free; diff --git a/src/ft.h b/src/ft.h index f90fc1b2..8bb31b28 100644 --- a/src/ft.h +++ b/src/ft.h @@ -28,9 +28,7 @@ typedef int (*ft_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len, void *user_data); typedef int (*ft_get_oci)(void *user_data); -typedef void (*ft_ds_free_func_t)(void *user_data); - -struct ft_ds_info { +struct ft_info { uint8_t spa[6]; uint8_t aa[6]; uint8_t snonce[32]; @@ -40,10 +38,10 @@ struct ft_ds_info { struct ie_ft_info ft_info; - void (*free)(struct ft_ds_info *s); + void (*free)(struct ft_info *s); }; -void ft_ds_info_free(struct ft_ds_info *info); +void ft_info_free(struct ft_info *info); bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc, const uint8_t *new_snonce, uint8_t *buf, @@ -54,10 +52,8 @@ int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len, const uint8_t **aa_out, const uint8_t **ies_out, size_t *ies_len); -bool ft_over_ds_parse_action_ies(struct ft_ds_info *info, - struct handshake_state *hs, - const uint8_t *ies, - size_t ies_len); +bool ft_parse_ies(struct ft_info *info, struct handshake_state *hs, + const uint8_t *ies, size_t ies_len); struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs, ft_tx_authenticate_func_t tx_auth, @@ -69,5 +65,4 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs, ft_tx_associate_func_t tx_assoc, void *user_data); -bool ft_over_ds_prepare_handshake(struct ft_ds_info *info, - struct handshake_state *hs); +bool ft_prepare_handshake(struct ft_info *info, struct handshake_state *hs); diff --git a/src/netdev.c b/src/netdev.c index 0d48631c..165dc157 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -96,8 +96,8 @@ struct netdev_handshake_state { enum connection_type type; }; -struct netdev_ft_over_ds_info { - struct ft_ds_info super; +struct netdev_ft_info { + struct ft_info super; struct netdev *netdev; bool parsed : 1; @@ -176,7 +176,7 @@ struct netdev { struct l_genl_msg *auth_cmd; struct wiphy_radio_work_item work; - struct l_queue *ft_ds_list; + struct l_queue *ft_list; struct netdev_ext_key_info *ext_key_info; @@ -752,11 +752,11 @@ static void netdev_preauth_destroy(void *data) l_free(state); } -static void netdev_ft_ds_entry_free(void *data) +static void netdev_ft_entry_free(void *data) { - struct netdev_ft_over_ds_info *info = data; + struct netdev_ft_info *info = data; - ft_ds_info_free(&info->super); + ft_info_free(&info->super); } static void netdev_connect_free(struct netdev *netdev) @@ -848,9 +848,9 @@ static void netdev_connect_free(struct netdev *netdev) netdev->get_oci_cmd_id = 0; } - if (netdev->ft_ds_list) { - l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free); - netdev->ft_ds_list = NULL; + if (netdev->ft_list) { + l_queue_destroy(netdev->ft_list, netdev_ft_entry_free); + netdev->ft_list = NULL; } } @@ -962,9 +962,9 @@ static void netdev_free(void *data) if (netdev->fw_roam_bss) scan_bss_free(netdev->fw_roam_bss); - if (netdev->ft_ds_list) { - l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free); - netdev->ft_ds_list = NULL; + if (netdev->ft_list) { + l_queue_destroy(netdev->ft_list, netdev_ft_entry_free); + netdev->ft_list = NULL; } scan_wdev_remove(netdev->wdev_id); @@ -1415,9 +1415,9 @@ static void netdev_connect_ok(struct netdev *netdev) netdev->fw_roam_bss = NULL; } - if (netdev->ft_ds_list) { - l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free); - netdev->ft_ds_list = NULL; + if (netdev->ft_list) { + l_queue_destroy(netdev->ft_list, netdev_ft_entry_free); + netdev->ft_list = NULL; } if (netdev->connect_cb) { @@ -4508,22 +4508,22 @@ static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss) } } -static void netdev_ft_over_ds_auth_failed(struct netdev_ft_over_ds_info *info, +static void netdev_ft_over_ds_auth_failed(struct netdev_ft_info *info, uint16_t status) { - l_queue_remove(info->netdev->ft_ds_list, info); - ft_ds_info_free(&info->super); + l_queue_remove(info->netdev->ft_list, info); + ft_info_free(&info->super); } -struct ft_ds_finder { +struct ft_finder { const uint8_t *spa; const uint8_t *aa; }; -static bool match_ft_ds_info(const void *a, const void *b) +static bool match_ft_info(const void *a, const void *b) { - const struct netdev_ft_over_ds_info *info = a; - const struct ft_ds_finder *finder = b; + const struct netdev_ft_info *info = a; + const struct ft_finder *finder = b; if (memcmp(info->super.spa, finder->spa, 6)) return false; @@ -4538,14 +4538,14 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr, int rssi, void *user_data) { struct netdev *netdev = user_data; - struct netdev_ft_over_ds_info *info; + struct netdev_ft_info *info; int ret; uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED; const uint8_t *aa; const uint8_t *spa; const uint8_t *ies; size_t ies_len; - struct ft_ds_finder finder; + struct ft_finder finder; if (!netdev->connected) return; @@ -4558,7 +4558,7 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr, finder.spa = spa; finder.aa = aa; - info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder); + info = l_queue_find(netdev->ft_list, match_ft_info, &finder); if (!info) return; @@ -4568,8 +4568,7 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr, goto ft_error; } - if (!ft_over_ds_parse_action_ies(&info->super, netdev->handshake, - ies, ies_len)) + if (!ft_parse_ies(&info->super, netdev->handshake, ies, ies_len)) goto ft_error; info->parsed = true; @@ -4661,8 +4660,8 @@ int netdev_fast_transition_over_ds(struct netdev *netdev, const struct scan_bss *orig_bss, netdev_connect_cb_t cb) { - struct netdev_ft_over_ds_info *info; - struct ft_ds_finder finder; + struct netdev_ft_info *info; + struct ft_finder finder; if (!netdev->operational) return -ENOTCONN; @@ -4675,14 +4674,14 @@ int netdev_fast_transition_over_ds(struct netdev *netdev, finder.spa = netdev->addr; finder.aa = target_bss->addr; - info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder); + info = l_queue_find(netdev->ft_list, match_ft_info, &finder); if (!info || !info->parsed) return -ENOENT; prepare_ft(netdev, target_bss); - ft_over_ds_prepare_handshake(&info->super, netdev->handshake); + ft_prepare_handshake(&info->super, netdev->handshake); netdev->connect_cb = cb; @@ -4699,7 +4698,7 @@ int netdev_fast_transition_over_ds(struct netdev *netdev, static void netdev_ft_request_cb(struct l_genl_msg *msg, void *user_data) { - struct netdev_ft_over_ds_info *info = user_data; + struct netdev_ft_info *info = user_data; if (l_genl_msg_get_error(msg) < 0) { l_error("Could not send CMD_FRAME for FT-over-DS"); @@ -4708,10 +4707,10 @@ static void netdev_ft_request_cb(struct l_genl_msg *msg, void *user_data) } } -static void netdev_ft_ds_info_free(struct ft_ds_info *ft) +static void netdev_ft_info_free(struct ft_info *ft) { - struct netdev_ft_over_ds_info *info = l_container_of(ft, - struct netdev_ft_over_ds_info, super); + struct netdev_ft_info *info = l_container_of(ft, + struct netdev_ft_info, super); l_free(info); } @@ -4719,7 +4718,7 @@ static void netdev_ft_ds_info_free(struct ft_ds_info *ft) int netdev_fast_transition_over_ds_action(struct netdev *netdev, const struct scan_bss *target_bss) { - struct netdev_ft_over_ds_info *info; + struct netdev_ft_info *info; uint8_t ft_req[14]; struct handshake_state *hs = netdev->handshake; struct iovec iovs[5]; @@ -4736,7 +4735,7 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev, l_debug(""); - info = l_new(struct netdev_ft_over_ds_info, 1); + info = l_new(struct netdev_ft_info, 1); info->netdev = netdev; memcpy(info->super.spa, hs->spa, ETH_ALEN); @@ -4748,7 +4747,7 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev, target_bss->rsne[1] + 2); l_getrandom(info->super.snonce, 32); - info->super.free = netdev_ft_ds_info_free; + info->super.free = netdev_ft_info_free; ft_req[0] = 6; /* FT category */ ft_req[1] = 1; /* FT Request action */ @@ -4767,10 +4766,10 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev, iovs[2].iov_base = NULL; - if (!netdev->ft_ds_list) - netdev->ft_ds_list = l_queue_new(); + if (!netdev->ft_list) + netdev->ft_list = l_queue_new(); - l_queue_push_head(netdev->ft_ds_list, info); + l_queue_push_head(netdev->ft_list, info); netdev_send_action_framev(netdev, netdev->handshake->aa, iovs, 2, netdev->frequency, From patchwork Mon Aug 22 18:25:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951032 Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B3294A18 for ; Mon, 22 Aug 2022 18:25:34 +0000 (UTC) Received: by mail-pg1-f169.google.com with SMTP id r69so10125797pgr.2 for ; Mon, 22 Aug 2022 11:25:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=MK443qbrSJ+NQ7mbUC4R5V85T6XrEWA/99+qPDUxiPE=; b=BmrZOg8rVCa7BHklmAaEL4vb1fp7zrvx6+JTvohBPqDrwRC9OGvw/BrgeIjuoPTjpn Cu5YbHiWHitCERDatGkv5dngX6LTg1w8hCJ22uYxxNZ+pQS2H51lBIlYlMdRZlGEL+Bi Sqzv2TYHYvIYx2cq1zwzjJSjGtTpBlYEguKiqxnK+CGY8ExmiJuR0KQlhAoKhvgE6/ma 23Hqz6Q7j+2N0pEmtIeYnAc6gAvqSgMeFGzCimL5EEJvEFCDbLzS6psLMtYr84ztqKev iVcX4yCZOcxd07ex+iAqCOX6IhrTdnJYUzlYKiZOsKDH3JpXmvL8tr3gAF+1+2QQjqjj CW7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=MK443qbrSJ+NQ7mbUC4R5V85T6XrEWA/99+qPDUxiPE=; b=sMl3XP78nVbxd0oxQdchxCILK+X3otgJ8IXnVdCgSIwg3XGxmJNhO8vVFFFor48Srl ygH/Sv0Ut5sb69l0ynoxmi6j/ESh3Eu+aEbj5lCjLrvEAdm86yUS/Va6vZh/PA6uGJLz XpQJRAxztUfPODxdSn50Q979AT2ZqIr0Ren0VYKkrvZXtpT1geY7TyXkRjfBnz/YetMs C5sqRG3l1S2GYlMsfdmWCcxbjtuOVxAknaObKohQHpeYDTVimjZBhxR6gR5vHcBZlcGB QtNYPxmbY21C+rU5KH3Y8CLOetoYv4rHAMWb92R95hv2pdYaQXf9WXCZcJwtQe5Vczv3 dDvA== X-Gm-Message-State: ACgBeo2/8zrXeA+XjwCKVpbBaS/eIFRkaTHtFFxC+XHrAC5YnSbZfCxh JiAErBS55uLMAiEB4ov8/keDAQVMLiE= X-Google-Smtp-Source: AA6agR6EyULYJvoHB6KA8XF4vz05VtEF2IqH08kXWvTIX/nWdH2hDmVjYU2qnDi0T0fWv2wzNHfxXw== X-Received: by 2002:a05:6a00:1650:b0:52f:20d6:e858 with SMTP id m16-20020a056a00165000b0052f20d6e858mr21915774pfc.36.1661192733705; Mon, 22 Aug 2022 11:25:33 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:33 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 3/9] station: have station_transition_start take a list of BSS's Date: Mon, 22 Aug 2022 11:25:19 -0700 Message-Id: <20220822182525.2078312-3-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This prepares for the FT-over-Air refactor, which will allow a candidate list to be provided to netdev_fast_transition. For now generate this candidate list but use the first (best) entry for the roam. This does slightly change the logic and all roam candidates are added to stations->bss_list (where before only the best candidate was), but this shouldn't effect how IWD behaves externally. --- src/station.c | 99 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 31 deletions(-) diff --git a/src/station.c b/src/station.c index 66b296b8..33cea14a 100644 --- a/src/station.c +++ b/src/station.c @@ -2181,13 +2181,14 @@ static void station_preauthenticate_cb(struct netdev *netdev, } static void station_transition_start(struct station *station, - struct scan_bss *bss) + struct l_queue *candidates) { struct handshake_state *hs = netdev_get_handshake(station->netdev); struct network *connected = station->connected_network; enum security security = network_get_security(connected); struct handshake_state *new_hs; struct ie_rsn_info cur_rsne, target_rsne; + struct scan_bss *bss = l_queue_peek_head(candidates); int ret; l_debug("%u, target %s", netdev_get_ifindex(station->netdev), @@ -2311,14 +2312,15 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list, struct station *station = userdata; struct network *network = station->connected_network; struct handshake_state *hs = netdev_get_handshake(station->netdev); - struct scan_bss *current_bss = station->connected_bss; + struct scan_bss *current_bss; struct scan_bss *bss; - struct scan_bss *best_bss = NULL; - double best_bss_rank = 0.0; + struct scan_bss *old_bss = NULL; + double cur_bss_rank = 0.0; static const double RANK_FT_FACTOR = 1.3; uint16_t mdid; enum security orig_security, security; bool seen = false; + struct l_queue *candidates = NULL; if (err) { station_roam_failed(station); @@ -2337,6 +2339,27 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list, ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2, &mdid, NULL, NULL); + /* Ranks better than the current BSS will go into the candidates list */ + current_bss = l_queue_find(bss_list, bss_match_bssid, + station->connected_bss->addr); + if (!current_bss) { + cur_bss_rank = 0; + current_bss = station->connected_bss; + } else + cur_bss_rank = current_bss->rank; + + if (hs->mde) + cur_bss_rank *= RANK_FT_FACTOR; + + /* + * TODO: Best to base this check off the actual transition request by + * looking at disassociation imminent and bss termination bits. + * For now keep existing behavior by always roaming if there are + * any candidates. + */ + if (station->ap_directed_roaming) + cur_bss_rank = 0; + /* * BSSes in the bss_list come already ranked with their initial * association preference rank value. We only need to add preference @@ -2387,51 +2410,59 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list, if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) rank *= RANK_FT_FACTOR; - if (rank > best_bss_rank) { - if (best_bss) - scan_bss_free(best_bss); + if (rank <= cur_bss_rank) + goto next; + + if (!candidates) + candidates = l_queue_new(); - best_bss = bss; - best_bss_rank = rank; + l_queue_insert(candidates, bss, scan_bss_rank_compare, NULL); - continue; + l_debug("Adding BSS "MAC" as roam candidate", + MAC_STR(bss->addr)); + /* + * Should only get here if the rank is better than our current + * BSS. Any BSS's here need to be added to the bss_list in case + * they are chosen to roam to. This also avoids the need to + * free candidates entries separately. + */ + old_bss = network_bss_find_by_addr(network, bss->addr); + if (old_bss) { + network_bss_update(network, bss); + l_queue_remove(station->bss_list, old_bss); + scan_bss_free(old_bss); + + l_queue_insert(station->bss_list, bss, + scan_bss_rank_compare, NULL); + } else { + network_bss_add(network, bss); + l_queue_push_tail(station->bss_list, bss); } + continue; next: scan_bss_free(bss); } l_queue_destroy(bss_list, NULL); - if (!seen) - goto fail_free_bss; + bss = l_queue_peek_head(candidates); /* See if we have anywhere to roam to */ - if (!best_bss || scan_bss_addr_eq(best_bss, station->connected_bss)) { - station_debug_event(station, "no-roam-candidates"); + if (!seen || !bss || scan_bss_addr_eq(bss, station->connected_bss)) goto fail_free_bss; - } - bss = network_bss_find_by_addr(network, best_bss->addr); - if (bss) { - network_bss_update(network, best_bss); - l_queue_remove(station->bss_list, bss); - scan_bss_free(bss); + station_transition_start(station, candidates); - l_queue_insert(station->bss_list, best_bss, - scan_bss_rank_compare, NULL); - } else { - network_bss_add(network, best_bss); - l_queue_push_tail(station->bss_list, best_bss); - } - - station_transition_start(station, best_bss); + l_queue_destroy(candidates, NULL); return true; fail_free_bss: - if (best_bss) - scan_bss_free(best_bss); + station_debug_event(station, "no-roam-candidates"); + + if (candidates) + l_queue_destroy(candidates, NULL); station_roam_failed(station); @@ -4356,6 +4387,7 @@ static struct l_dbus_message *station_force_roam(struct l_dbus *dbus, struct l_dbus_message_iter iter; uint8_t *mac; uint32_t mac_len; + struct l_queue *candidate; if (!l_dbus_message_get_arguments(message, "ay", &iter)) goto invalid_args; @@ -4385,7 +4417,12 @@ static struct l_dbus_message *station_force_roam(struct l_dbus *dbus, /* The various roam routines expect this to be set from scanning */ station->preparing_roam = true; - station_transition_start(station, target); + candidate = l_queue_new(); + l_queue_push_head(candidate, target); + + station_transition_start(station, candidate); + + l_queue_destroy(candidate, NULL); return l_dbus_message_new_method_return(message); From patchwork Mon Aug 22 18:25:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951033 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03F324A02 for ; Mon, 22 Aug 2022 18:25:34 +0000 (UTC) Received: by mail-pg1-f178.google.com with SMTP id bh13so10120346pgb.4 for ; Mon, 22 Aug 2022 11:25:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=FRTmnoWaMEh6i6tK8CdUMeyxrxZWS7oNbKA9TsDqQIo=; b=cmMYYsGo5u3aztES40+0T3vH6eOxn6Es/Y/eB+AlzKa04thLK4Vw5bw1bz/SeSCgJx r4CpEddwWxWTlgHJHoOeT9du1rwEq3RF+G9eO4T9gs5yvF3QgB2noylr6OMWEgGTh5m9 PMSF4Mjy2YHQE/2FRJOXn94xUIFzrNKEH79f0HWLW8xghY5396HNjBzua/x6hctdKOWn c0J9w6VZOxkSplIR3MkS6PAMs6KvjHc0Sh+m5Vr6Db7An5PHXTEy0xzeHHbicY7pMlx2 eAyFYq3Ceyt2fu2AON0kVuyA2vo94GtKl5sxDkd5j7tNZiVhq9VwAXG/snCiw39rDe/z N89A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=FRTmnoWaMEh6i6tK8CdUMeyxrxZWS7oNbKA9TsDqQIo=; b=6pCDghKUHrNqJeCoE8ElraqqtRPBdPK19GkZsxZKgsDt9FhIcKfbdeykq6Hew9iY8r N7BF3omMql+E2N9zfbK1vRCjg8HonLOY5tJwbz4Oi2jGkYBki8gcaKMF8m6rtb9MEKjz tnnNhAVv7WB6zHd/ShwqYg9Zpvu6vLjzGLbaIH5Kp6+Oy+/HSNyIEEX3Zmx9k3DnHTpZ axpalw5cPKxK+cI+vWHQFUuP5CSunqTVUeVKb6eTSW10EL/JPOQh8gCVtCHkfP799f+b NZrilU+tEL8TIwT+PBFlvCoINgEA+5LbsM/EjpRd9r568Ax7mHs8EqYoyIK+u+Hj4pR/ l9yw== X-Gm-Message-State: ACgBeo2/Gy0osNoMocq99Z0MMqyiDTfr8Qujl1+dWKVEMindLeAvNKZL 6eBIa+Uz/UWUrwaw1pe1KaIu6HCXZq4= X-Google-Smtp-Source: AA6agR4snS54b8QH2TgUiIHsvjqh29Jl7OopvJHWfGIwG/CioSDNOXapQ7RY/7BRnvvdAqDugMH18w== X-Received: by 2002:a63:60b:0:b0:42a:bcc4:e2ed with SMTP id 11-20020a63060b000000b0042abcc4e2edmr5047785pgg.409.1661192734324; Mon, 22 Aug 2022 11:25:34 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:33 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 4/9] station: don't set OCVC for FT AKMs Date: Mon, 22 Aug 2022 11:25:20 -0700 Message-Id: <20220822182525.2078312-4-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Using OCV in FT is now disabled, so if the AKM is FT don't set the capability or AP's may reject FT attempts. --- src/station.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/station.c b/src/station.c index 33cea14a..601c3916 100644 --- a/src/station.c +++ b/src/station.c @@ -1110,9 +1110,15 @@ build_ie: * seen that they do not include the OCI in the 4-way handshake yet * still advertise the capability. Because of this OCV is disabled if * any offload features are detected (since IWD prefers to use offload). + * + * TODO: For now OCV is disabled if the network is FT capable. This is + * being done until support in the kernel is added to + * automatically include the OCI element for the association + * request. */ info.ocvc = !disable_ocv && bss_info.ocvc && info.mfpc && - !wiphy_can_offload(wiphy); + !wiphy_can_offload(wiphy) && + !IE_AKM_IS_FT(info.akm_suites); /* * IEEE 802.11-2020 9.4.2.24.4 states extended key IDs can only be used From patchwork Mon Aug 22 18:25:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951034 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DA664A17 for ; Mon, 22 Aug 2022 18:25:35 +0000 (UTC) Received: by mail-pg1-f174.google.com with SMTP id l64so10144109pge.0 for ; Mon, 22 Aug 2022 11:25:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=pa4GC/P96VOsciYaIlI8AloeE9SNoyviro8BNZobB4k=; b=CXXNSMPaA1UnqqhppfNtlay0ziIvidw818VavtSzWMjCEUv3dishRkBjWohyiGbMLp XCJeuKZXv54bZ7digE10J4PuefiGhNL7EuyqdtrBH61BXnvgFrLSJ6qqDMTHFZr+qpNB t5/VxOgxRWM7Q8DAPH675m/L48Mh6l4Ymk6rDxRUSwzuGip9ZWjEZ4eTN/bqrIKztW0+ FI3cFp45/jF+vec2h1g8zOot/qKtR9PopaX48uNCLhAx+difpaVHQdY2L74qikT8zm3q 5VC2uomgAoJDjLHEVo4imVVHWyOdWhlG4cC9X/3wI4WzAeXar4dR0JFbG8Jj4zQqHo84 tAlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=pa4GC/P96VOsciYaIlI8AloeE9SNoyviro8BNZobB4k=; b=lFWLrazBSyzM5eIQNRkLHzW5dMEQK+ERP/K/ruu5SPXtQZd/uNSS/64uuHS6ygg003 h0RTkCMKqMPHVzyrOstj52aS52pdtT/0UKBWzWfNGbqUO5iZ0osDdTUzUUMroSy1PeNy 4Svjw6/RagQkFfDMK+LuUrqmJBPdmIE/uV/OWW+tmIoCBv0Z2SSjw4uDLINWTvKDrTgO wtwtX7HN/08nzDuw3mF79qtFSRYM9vnyFABIWvVKJjGP8vqU0gZiFH0v7Y36W1wIqpKg Mpcz6oguFQM7wrpJJ1v4UmpfCfWLq2aL/n4LWML/A0CU2Zd/M+QR7imUghurgGigI6zZ +Suw== X-Gm-Message-State: ACgBeo31cv+UTghJwTbBFpQ/BqN40hY5RSg0bI6DCltm+jw4SzZGzw6+ KNjrtdydvsq3JTuJlJuK4lyPaqQQ+L4= X-Google-Smtp-Source: AA6agR5sTe2X0xwnNGCc2YjlkDX6Hvn3GjqAfFZOeSjBt7x9rl5MbmWMciQmTHjnR4SuZsdiUf4V3Q== X-Received: by 2002:aa7:81d1:0:b0:535:c2e5:eccf with SMTP id c17-20020aa781d1000000b00535c2e5eccfmr21797515pfn.16.1661192734914; Mon, 22 Aug 2022 11:25:34 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:34 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 5/9] ft: expose ft_parse_authentication_resp_frame Date: Mon, 22 Aug 2022 11:25:21 -0700 Message-Id: <20220822182525.2078312-5-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This will be needed by netdev when doing authentication off-channel. --- src/ft.c | 2 +- src/ft.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ft.c b/src/ft.c index 04ae2775..84873fbd 100644 --- a/src/ft.c +++ b/src/ft.c @@ -116,7 +116,7 @@ static bool ft_calculate_fte_mic(struct handshake_state *hs, uint8_t seq_num, * the start of the IE array (RSN, MD, FT, TI and RIC). * See 8.3.3.1 for the header and 8.3.3.11 for the body format. */ -static bool ft_parse_authentication_resp_frame(const uint8_t *data, size_t len, +bool ft_parse_authentication_resp_frame(const uint8_t *data, size_t len, const uint8_t *addr1, const uint8_t *addr2, const uint8_t *addr3, uint16_t auth_seq, uint16_t *out_status, const uint8_t **out_ies, diff --git a/src/ft.h b/src/ft.h index 8bb31b28..7ae925a3 100644 --- a/src/ft.h +++ b/src/ft.h @@ -52,6 +52,11 @@ int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len, const uint8_t **aa_out, const uint8_t **ies_out, size_t *ies_len); +bool ft_parse_authentication_resp_frame(const uint8_t *data, size_t len, + const uint8_t *addr1, const uint8_t *addr2, + const uint8_t *addr3, uint16_t auth_seq, + uint16_t *out_status, const uint8_t **out_ies, + size_t *out_ies_len); bool ft_parse_ies(struct ft_info *info, struct handshake_state *hs, const uint8_t *ies, size_t ies_len); From patchwork Mon Aug 22 18:25:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951035 Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 244174A18 for ; Mon, 22 Aug 2022 18:25:36 +0000 (UTC) Received: by mail-pf1-f177.google.com with SMTP id x15so10249126pfp.4 for ; Mon, 22 Aug 2022 11:25:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=R1nf1/KuwAZ9aSbanbGV6usIrn9jkYsoNPDfdYBYLpM=; b=pN6XXfBCkReWb9B4/GrvmEoUaNKu1j9szENargsKfb6gD34ZWhKbaYd+WACeP3sTmr U7RsuhuPWnKjq+FTUlcsFiMOyjObxsAHIv+H46RojJCqrfd/rcNDrQEKT2JZcd12HiYR zjddfFAmBWjgDU4Redzz37x7dlGcV4kY5Ga2xtFINeN3MjqktVsp/F4qD7OKou7OvgBe uZ710BT+CTCJ0JUxyJWGVqJs/KejYK1RfAZo76Z4J0twT+Q85hAgZmORYo4Qf00AhLLz 0B5YOazNOTTQeT7R2ylUTQILl9E7a1d7BGv1yH+01ABb407jY1e+N17iTOdRbQDI3jJC Ocng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=R1nf1/KuwAZ9aSbanbGV6usIrn9jkYsoNPDfdYBYLpM=; b=sCTCmaYqHrcF23HTAsw5pr008gfUy2dPHNPdCmDQnTJ7qFPcNjTxQWWG4+frNaWL8c GIA1aidjnmoxkNK7BDpiJ3gQfOujhsBg0eVLr8t54jyJL8txn+fDGuW3bczkdlIV79fI ye/kKo46KRY6ztHc91DnjFVdmMFkUfQlnD2L0qQpQBRlLez1N4qP0Ti61epx/xIP8y+Y 5hoQtW1HAr+CTwtmjkCwMHSJxus60HQP5s6x/hdimcTpgQDunwLQW9UCL69jEmjaYBJ8 hVx0OxMR2mqtDG5iLJLU0BkSt7yUawpiAEfJt58Jltq5hTFYTyyjxm7dLdIdoyoHBXwH /kKQ== X-Gm-Message-State: ACgBeo3jMjKohGdIWT/LcXU7G7XN2FX8eQAmJ+/coXmJq8hFH5Be761L AVNZziwLYlE2tniy5/pZGSqhXZBKQUo= X-Google-Smtp-Source: AA6agR4c5BVGnEIPWMaNm5LPDBVBBe8hVbClblgTB4lRg1gv4pDTMqSRgqBUlCFx1t4GfsoMqF/m4Q== X-Received: by 2002:a63:2cc6:0:b0:41c:5f9c:e15c with SMTP id s189-20020a632cc6000000b0041c5f9ce15cmr17563035pgs.241.1661192735470; Mon, 22 Aug 2022 11:25:35 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:35 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 6/9] ft: remove OCI element from auth/assoc Date: Mon, 22 Aug 2022 11:25:22 -0700 Message-Id: <20220822182525.2078312-6-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 FT is moving to authentication via CMD_FRAME which breaks the ability to get the OCI from the kernel (since its now an offchannel operation). Using OCI during FT isn't that useful anyways, so its being removed. --- src/ft.c | 26 ++------------------------ src/ft.h | 2 +- src/netdev.c | 3 +-- 3 files changed, 4 insertions(+), 27 deletions(-) diff --git a/src/ft.c b/src/ft.c index 84873fbd..14d6f4f2 100644 --- a/src/ft.c +++ b/src/ft.c @@ -233,10 +233,6 @@ static int ft_tx_reassociate(struct ft_sm *ft) rsn_info.num_pmkids = 1; rsn_info.pmkids = hs->pmk_r1_name; - /* Always set OCVC false for FT-over-DS */ - if (ft->over_ds) - rsn_info.ocvc = false; - rsne = alloca(256); ie_build_rsne(&rsn_info, rsne); @@ -276,22 +272,6 @@ static int ft_tx_reassociate(struct ft_sm *ft) memcpy(ft_info.anonce, hs->anonce, 32); memcpy(ft_info.snonce, hs->snonce, 32); - /* - * IEEE 802.11-2020 Section 13.7.1 FT reassociation in an RSN - * - * "If dot11RSNAOperatingChannelValidationActivated is true and - * the FTO indicates OCVC capability, the target AP shall - * ensure that OCI subelement of the FTE matches by ensuring - * that all of the following are true: - * - OCI subelement is present - * - Channel information in the OCI matches current - * operating channel parameters (see 12.2.9)" - */ - if (hs->supplicant_ocvc && hs->chandef) { - oci_from_chandef(hs->chandef, ft_info.oci); - ft_info.oci_present = true; - } - fte = alloca(256); ie_build_fast_bss_transition(&ft_info, kck_len, fte); @@ -809,7 +789,7 @@ static bool ft_over_ds_start(struct auth_proto *ap) return ft_tx_reassociate(ft) == 0; } -bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc, +bool ft_build_authenticate_ies(struct handshake_state *hs, const uint8_t *new_snonce, uint8_t *buf, size_t *len) { @@ -838,7 +818,6 @@ bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc, rsn_info.num_pmkids = 1; rsn_info.pmkids = hs->pmk_r0_name; - rsn_info.ocvc = ocvc; ie_build_rsne(&rsn_info, ptr); ptr += ptr[1] + 2; @@ -889,8 +868,7 @@ static bool ft_start(struct auth_proto *ap) uint8_t buf[512]; size_t len; - if (!ft_build_authenticate_ies(hs, hs->supplicant_ocvc, hs->snonce, - buf, &len)) + if (!ft_build_authenticate_ies(hs, hs->snonce, buf, &len)) return false; iov.iov_base = buf; diff --git a/src/ft.h b/src/ft.h index 7ae925a3..6922513f 100644 --- a/src/ft.h +++ b/src/ft.h @@ -43,7 +43,7 @@ struct ft_info { void ft_info_free(struct ft_info *info); -bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc, +bool ft_build_authenticate_ies(struct handshake_state *hs, const uint8_t *new_snonce, uint8_t *buf, size_t *len); diff --git a/src/netdev.c b/src/netdev.c index 165dc157..6b0cd537 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -4757,8 +4757,7 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev, iovs[0].iov_base = ft_req; iovs[0].iov_len = sizeof(ft_req); - if (!ft_build_authenticate_ies(hs, false, info->super.snonce, - buf, &len)) + if (!ft_build_authenticate_ies(hs, info->super.snonce, buf, &len)) goto failed; iovs[1].iov_base = buf; From patchwork Mon Aug 22 18:25:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951036 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EEB794A17 for ; Mon, 22 Aug 2022 18:25:36 +0000 (UTC) Received: by mail-pf1-f178.google.com with SMTP id f17so4993041pfk.11 for ; Mon, 22 Aug 2022 11:25:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=YYfdk7XgnOvVRTpwBE+250WpcayOI5IIwbwk9zOwtZg=; b=iOsCl7coLkgbcKNZ1dmUY69cGgLC43J4+ezLaW5gsw2336T8tBOy32q64P59YhIcY5 v7nt7QNngKVEeqR/xAb1FxOO5JXK95clBA0ahmk5KK3TLAUxs4yRKi1FcGzzZFa65+xI 1bRnE5U0SAUz9qyIR4f9shReBYLKgUlg2+jrAh1X1l79y3DQY9MkapFx8d3igtNwuLZz pFz5F+HJMbsshHyxrYv2EJ20fdXcIKO8SyDwjxxGGfwVlsmlaeu0NmxPUjWgh9EgF+Pp 70//HhuHiOqNmR9cv29QOJyx/IRDIK/lQTazeD/QfKb3CiOd4gVkheENV1mFVgs5VVGR M8mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=YYfdk7XgnOvVRTpwBE+250WpcayOI5IIwbwk9zOwtZg=; b=tQH/+MSgQg0mdq7e24LaL6PY5qPXKjL1sjO/oNq/cxEtLdYvNjXrXMr8HVqcgSR3Z7 jTtEqWj6vXVQCDgZHhm5X+QZM0l2XMJ6quhA7DLseOsAoeH79QhxOWVjpLJ3gHvxTZKL 9cY95I/OQOPOEkiwe7khM6mLWPjXM/cVhr3MwnI+kp+N8meCZlPvF810kataW3rYIf5I Eyh6u1zS64ueG11YOLIkiW3g7saQkGY8JyvkkXefqnHaN7MaREzbZdjJwD0JEeLqt0Z1 ox37z9Ew4kjR3M/GnF3L+ohWjMpeqHbjdYg6aWSAGA/+C2qO3Y0n3p+mp8rbHf0mI18w KuZg== X-Gm-Message-State: ACgBeo1kg9BawtyYaDjiedklaNEVwfHZcqWRy/8Jd1k8nsUJ6SOk/lAb zPr/PmmwuCuCkz0219LW4fUnBGvy+IU= X-Google-Smtp-Source: AA6agR4azhf/Q3rGagijwBnYUt9EI4C4C080zdpoXOVsBn94eRhJXUWbYZr+sYdtOJ7qaMUF030JQQ== X-Received: by 2002:a05:6a00:1a0c:b0:528:6baa:a2e3 with SMTP id g12-20020a056a001a0c00b005286baaa2e3mr22183505pfv.27.1661192736163; Mon, 22 Aug 2022 11:25:36 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:35 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 7/9] netdev: ft: do FT authentication offchannel Date: Mon, 22 Aug 2022 11:25:23 -0700 Message-Id: <20220822182525.2078312-7-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This removes the use of CMD_AUTHENTICATE from FT. The reason being that a station should be able to authenticate to multiple BSS's, then proceed to association with a single BSS. The kernel does not allow this since CMD_AUTHENTICATE actually transitions to the new BSS's channel and changes state making any failures fatal. Instead userspace can do authentication using CMD_FRAME which allows any failures to be recoverable (during authentication). This is nearly identical to how FT-over-DS works where any auth failures (during the action state) just means you can avoid that BSS but can still transition to another without being disconnected. --- src/ft.c | 103 +--------------------- src/ft.h | 2 - src/netdev.c | 243 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 161 insertions(+), 187 deletions(-) diff --git a/src/ft.c b/src/ft.c index 14d6f4f2..ff908829 100644 --- a/src/ft.c +++ b/src/ft.c @@ -479,48 +479,6 @@ ft_error: return false; } -static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies, - size_t ies_len) -{ - const uint8_t *mde = NULL; - const uint8_t *fte = NULL; - bool is_rsn = hs->supplicant_ie != NULL; - - /* Check 802.11r IEs */ - if (!ies) - goto ft_error; - - if (parse_ies(hs, hs->authenticator_ie, ies, ies_len, - &mde, &fte) < 0) - goto ft_error; - - if (!mde_equal(hs->mde, mde)) - goto ft_error; - - if (is_rsn) { - struct ie_ft_info ft_info; - - if (!ft_parse_fte(hs, hs->snonce, fte, &ft_info)) - goto ft_error; - - handshake_state_set_fte(hs, fte); - - handshake_state_set_anonce(hs, ft_info.anonce); - - handshake_state_set_kh_ids(hs, ft_info.r0khid, - ft_info.r0khid_len, - ft_info.r1khid); - - handshake_state_derive_ptk(hs); - } else if (fte) - goto ft_error; - - return 0; - -ft_error: - return -EBADMSG; -} - int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len, const uint8_t **spa_out, const uint8_t **aa_out, @@ -597,40 +555,6 @@ void ft_info_free(struct ft_info *info) destroy(info); } -static int ft_rx_authenticate(struct auth_proto *ap, const uint8_t *frame, - size_t frame_len) -{ - struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap); - uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED; - const uint8_t *ies = NULL; - size_t ies_len; - int ret; - - /* - * Parse the Authentication Response and validate the contents - * according to 12.5.2 / 12.5.4: RSN or non-RSN Over-the-air - * FT Protocol. - */ - if (!ft_parse_authentication_resp_frame(frame, frame_len, ft->hs->spa, - ft->hs->aa, ft->hs->aa, - 2, &status_code, - &ies, &ies_len)) - goto auth_error; - - /* AP Rejected the authenticate / associate */ - if (status_code != 0) - goto auth_error; - - ret = ft_process_ies(ft->hs, ies, ies_len); - if (ret < 0) - goto auth_error; - - return ft->get_oci(ft->user_data); - -auth_error: - return (int)status_code; -} - static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame, size_t frame_len) { @@ -768,13 +692,6 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame, return 0; } -static int ft_rx_oci(struct auth_proto *ap) -{ - struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap); - - return ft_tx_reassociate(ft); -} - static void ft_sm_free(struct auth_proto *ap) { struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap); @@ -863,41 +780,23 @@ bool ft_build_authenticate_ies(struct handshake_state *hs, static bool ft_start(struct auth_proto *ap) { struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap); - struct handshake_state *hs = ft->hs; - struct iovec iov; - uint8_t buf[512]; - size_t len; - if (!ft_build_authenticate_ies(hs, hs->snonce, buf, &len)) - return false; - - iov.iov_base = buf; - iov.iov_len = len; - - ft->tx_auth(&iov, 1, ft->user_data); - - return true; + return ft_tx_reassociate(ft) == 0; } struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs, - ft_tx_authenticate_func_t tx_auth, ft_tx_associate_func_t tx_assoc, - ft_get_oci get_oci, void *user_data) { struct ft_sm *ft = l_new(struct ft_sm, 1); - ft->tx_auth = tx_auth; ft->tx_assoc = tx_assoc; - ft->get_oci = get_oci; ft->hs = hs; ft->user_data = user_data; - ft->ap.rx_authenticate = ft_rx_authenticate; ft->ap.rx_associate = ft_rx_associate; ft->ap.start = ft_start; ft->ap.free = ft_sm_free; - ft->ap.rx_oci = ft_rx_oci; return &ft->ap; } diff --git a/src/ft.h b/src/ft.h index 6922513f..29da0dd0 100644 --- a/src/ft.h +++ b/src/ft.h @@ -61,9 +61,7 @@ bool ft_parse_ies(struct ft_info *info, struct handshake_state *hs, const uint8_t *ies, size_t ies_len); struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs, - ft_tx_authenticate_func_t tx_auth, ft_tx_associate_func_t tx_assoc, - ft_get_oci get_oci, void *user_data); struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs, diff --git a/src/netdev.c b/src/netdev.c index 6b0cd537..f38b9c9a 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -99,6 +99,7 @@ struct netdev_handshake_state { struct netdev_ft_info { struct ft_info super; struct netdev *netdev; + uint32_t frequency; bool parsed : 1; }; @@ -138,6 +139,7 @@ struct netdev { uint32_t qos_map_cmd_id; uint32_t mac_change_cmd_id; uint32_t get_oci_cmd_id; + uint32_t ft_auth_cmd_id; enum netdev_result result; uint16_t last_code; /* reason or status, depending on result */ struct l_timeout *neighbor_report_timeout; @@ -848,6 +850,11 @@ static void netdev_connect_free(struct netdev *netdev) netdev->get_oci_cmd_id = 0; } + if (netdev->ft_auth_cmd_id) { + frame_xchg_cancel(netdev->ft_auth_cmd_id); + netdev->ft_auth_cmd_id = 0; + } + if (netdev->ft_list) { l_queue_destroy(netdev->ft_list, netdev_ft_entry_free); netdev->ft_list = NULL; @@ -4359,48 +4366,6 @@ static uint32_t netdev_send_action_frame(struct netdev *netdev, user_data); } -static void netdev_cmd_authenticate_ft_cb(struct l_genl_msg *msg, - void *user_data) -{ - struct netdev *netdev = user_data; - - netdev->connect_cmd_id = 0; - - if (l_genl_msg_get_error(msg) < 0) - netdev_connect_failed(netdev, - NETDEV_RESULT_AUTHENTICATION_FAILED, - MMPDU_STATUS_CODE_UNSPECIFIED); -} - -static void netdev_ft_tx_authenticate(struct iovec *iov, - size_t iov_len, void *user_data) -{ - struct netdev *netdev = user_data; - struct l_genl_msg *cmd_authenticate; - - cmd_authenticate = netdev_build_cmd_authenticate(netdev, - NL80211_AUTHTYPE_FT); - l_genl_msg_append_attrv(cmd_authenticate, NL80211_ATTR_IE, iov, - iov_len); - - netdev->connect_cmd_id = l_genl_family_send(nl80211, - cmd_authenticate, - netdev_cmd_authenticate_ft_cb, - netdev, NULL); - if (!netdev->connect_cmd_id) { - l_genl_msg_unref(cmd_authenticate); - goto restore_snonce; - } - - return; - -restore_snonce: - memcpy(netdev->handshake->snonce, netdev->prev_snonce, 32); - - netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED, - MMPDU_STATUS_CODE_UNSPECIFIED); -} - static int netdev_ft_tx_associate(struct iovec *ft_iov, size_t n_ft_iov, void *user_data) { @@ -4441,7 +4406,7 @@ static int netdev_ft_tx_associate(struct iovec *ft_iov, size_t n_ft_iov, return 0; } -static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss) +static void prepare_ft(struct netdev *netdev, struct netdev_ft_info *info) { struct netdev_handshake_state *nhs; @@ -4452,15 +4417,15 @@ static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss) */ memcpy(netdev->prev_snonce, netdev->handshake->snonce, 32); - netdev->frequency = target_bss->frequency; + netdev->frequency = info->frequency; handshake_state_set_authenticator_address(netdev->handshake, - target_bss->addr); + info->super.aa); - if (target_bss->rsne) + if (info->super.authenticator_ie) handshake_state_set_authenticator_ie(netdev->handshake, - target_bss->rsne); - memcpy(netdev->handshake->mde + 2, target_bss->mde, 3); + info->super.authenticator_ie); + memcpy(netdev->handshake->mde + 2, info->super.mde, 3); netdev->handshake->active_tk_index = 0; netdev->associated = false; @@ -4506,6 +4471,8 @@ static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss) eapol_sm_free(netdev->sm); netdev->sm = NULL; } + + ft_prepare_handshake(&info->super, netdev->handshake); } static void netdev_ft_over_ds_auth_failed(struct netdev_ft_info *info, @@ -4624,11 +4591,149 @@ static const struct wiphy_radio_work_item_ops ft_work_ops = { .do_work = netdev_ft_work_ready, }; +static void netdev_authenticate_response_ft_cb(const struct mmpdu_header *hdr, + const void *body, + size_t body_len, int rssi, + void *user_data) +{ + struct netdev_ft_info *info = user_data; + struct netdev *netdev = info->netdev; + uint16_t status; + const uint8_t *ies; + size_t ies_len; + + if (!ft_parse_authentication_resp_frame((const uint8_t *)hdr, + mmpdu_header_len(hdr) + body_len, + info->super.spa, info->super.aa, + info->super.aa, 2, &status, + &ies, &ies_len)) + goto failed; + + if (status != 0) + goto failed; + + if (!ft_parse_ies(&info->super, netdev->handshake, ies, ies_len)) + goto failed; + + /* If we got here authentication was successful, continue with FT */ + netdev->ap = ft_over_air_sm_new(netdev->handshake, + netdev_ft_tx_associate, + netdev); + + memcpy(netdev->ap->prev_bssid, netdev->handshake->aa, ETH_ALEN); + + prepare_ft(netdev, info); + + wiphy_radio_work_insert(netdev->wiphy, &netdev->work, + WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops); + + return; + +failed: + netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED, + MMPDU_STATUS_CODE_UNSPECIFIED); +} + +static const struct frame_xchg_prefix ft_prefix = { + .frame_type = 0x0000 | (MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION << 4), + .data = (uint8_t []) { 0x02, 0x00 }, + .len = 2, +}; + +static void netdev_cmd_authenticate_ft_cb(int err, void *user_data) +{ + struct netdev_ft_info *info = user_data; + + if (err < 0) + netdev_connect_failed(info->netdev, + NETDEV_RESULT_AUTHENTICATION_FAILED, +} + +static bool netdev_send_ft_authenticate(struct netdev *netdev, + struct netdev_ft_info *info) +{ + uint8_t header[28 + sizeof(struct mmpdu_authentication)]; + uint8_t ies[256]; + size_t len; + struct iovec iov[3]; + struct mmpdu_header *mpdu = (struct mmpdu_header *) header; + struct mmpdu_authentication *auth; + struct handshake_state *hs = netdev->handshake; + + memset(mpdu, 0, sizeof(*mpdu)); + + /* Header */ + mpdu->fc.protocol_version = 0; + mpdu->fc.type = MPDU_TYPE_MANAGEMENT; + mpdu->fc.subtype = MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION; + memcpy(mpdu->address_1, info->super.aa, 6); + memcpy(mpdu->address_2, netdev->addr, 6); + memcpy(mpdu->address_3, info->super.aa, 6); + + /* Authentication body */ + auth = (void *) mmpdu_body(mpdu); + auth->algorithm = L_CPU_TO_LE16(MMPDU_AUTH_ALGO_FT); + auth->transaction_sequence = L_CPU_TO_LE16(1); + auth->status = L_CPU_TO_LE16(0); + + iov[0].iov_base = mpdu; + iov[0].iov_len = mmpdu_header_len(mpdu) + + sizeof(struct mmpdu_authentication); + + if (!ft_build_authenticate_ies(hs, info->super.snonce, ies, &len)) + return false; + + iov[1].iov_base = ies; + iov[1].iov_len = len; + + iov[2].iov_base = NULL; + + netdev->ft_auth_cmd_id = frame_xchg_start(netdev->wdev_id, iov, + info->frequency, 0, 100, 0, 0, + netdev_cmd_authenticate_ft_cb, info, NULL, + &ft_prefix, netdev_authenticate_response_ft_cb, NULL); + + return netdev->ft_auth_cmd_id != 0; +} + +static void netdev_ft_info_free(struct ft_info *ft) +{ + struct netdev_ft_info *info = l_container_of(ft, + struct netdev_ft_info, super); + + l_free(info); +} + +static struct netdev_ft_info *netdev_ft_info_new(struct netdev *netdev, + const struct scan_bss *bss) +{ + struct handshake_state *hs = netdev->handshake; + struct netdev_ft_info *info; + + info = l_new(struct netdev_ft_info, 1); + info->netdev = netdev; + info->frequency = bss->frequency; + + memcpy(info->super.spa, hs->spa, ETH_ALEN); + memcpy(info->super.aa, bss->addr, ETH_ALEN); + memcpy(info->super.mde, bss->mde, sizeof(info->super.mde)); + + if (bss->rsne) + info->super.authenticator_ie = l_memdup(bss->rsne, + bss->rsne[1] + 2); + l_getrandom(info->super.snonce, 32); + info->super.free = netdev_ft_info_free; + + return info; +} + int netdev_fast_transition(struct netdev *netdev, const struct scan_bss *target_bss, const struct scan_bss *orig_bss, netdev_connect_cb_t cb) { + struct netdev_ft_info *info; + if (!netdev->operational) return -ENOTCONN; @@ -4637,20 +4742,14 @@ int netdev_fast_transition(struct netdev *netdev, l_get_le16(target_bss->mde)) return -EINVAL; - prepare_ft(netdev, target_bss); - - handshake_state_new_snonce(netdev->handshake); - netdev->connect_cb = cb; - netdev->ap = ft_over_air_sm_new(netdev->handshake, - netdev_ft_tx_authenticate, - netdev_ft_tx_associate, - netdev_get_oci, netdev); - memcpy(netdev->ap->prev_bssid, orig_bss->addr, ETH_ALEN); + info = netdev_ft_info_new(netdev, target_bss); - wiphy_radio_work_insert(netdev->wiphy, &netdev->work, - WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops); + if (!netdev_send_ft_authenticate(netdev, info)) { + netdev_ft_entry_free(info); + return -EBADMSG; + } return 0; } @@ -4679,9 +4778,7 @@ int netdev_fast_transition_over_ds(struct netdev *netdev, if (!info || !info->parsed) return -ENOENT; - prepare_ft(netdev, target_bss); - - ft_prepare_handshake(&info->super, netdev->handshake); + prepare_ft(netdev, info); netdev->connect_cb = cb; @@ -4707,14 +4804,6 @@ static void netdev_ft_request_cb(struct l_genl_msg *msg, void *user_data) } } -static void netdev_ft_info_free(struct ft_info *ft) -{ - struct netdev_ft_info *info = l_container_of(ft, - struct netdev_ft_info, super); - - l_free(info); -} - int netdev_fast_transition_over_ds_action(struct netdev *netdev, const struct scan_bss *target_bss) { @@ -4735,19 +4824,7 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev, l_debug(""); - info = l_new(struct netdev_ft_info, 1); - info->netdev = netdev; - - memcpy(info->super.spa, hs->spa, ETH_ALEN); - memcpy(info->super.aa, target_bss->addr, ETH_ALEN); - memcpy(info->super.mde, target_bss->mde, sizeof(info->super.mde)); - - if (target_bss->rsne) - info->super.authenticator_ie = l_memdup(target_bss->rsne, - target_bss->rsne[1] + 2); - - l_getrandom(info->super.snonce, 32); - info->super.free = netdev_ft_info_free; + info = netdev_ft_info_new(netdev, target_bss); ft_req[0] = 6; /* FT category */ ft_req[1] = 1; /* FT Request action */ From patchwork Mon Aug 22 18:25:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951037 Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B546F4A18 for ; Mon, 22 Aug 2022 18:25:37 +0000 (UTC) Received: by mail-pj1-f47.google.com with SMTP id s36-20020a17090a69a700b001faad0a7a34so14799234pjj.4 for ; Mon, 22 Aug 2022 11:25:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=6PX1KPJLy9QhdYb+dUhKl10SKVqZTnjeXBMy2BjzQUU=; b=Rec7uOfB+18OA+0ACqd8GUCHw8LTn9KavtgBgeNPizkNW/RjcWQCxKenLLRbletAeN KPITirCxYN7mYjfbpjg9Vod116P1q2bTMuPtL5v/a07LjjA7j4ZH+L+qCoFq3dtDAWdD HWUhCmcdeYtdcAxNQnjolG9BHaAwXSa6pNc8p1goIVenD9KXRU1jnFy3vNoIQk+y484I G+tt/21frAvjpfcz8IAs5wSl5oybg1Jadqd9uLkp8V1SItkizLOKs3inahkWboumuEZx +g0nzsV4IUCRfVE27C1sNEUAL1SrT9GxMaOIyk+TpPvYHhe0UdlcomlmhsJE8ML0tA3m kA2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=6PX1KPJLy9QhdYb+dUhKl10SKVqZTnjeXBMy2BjzQUU=; b=4vPu+9RbXdJhgW/jPEjpRMpjWCmNkD8MvHu4sx2I/tEx/OZGxOfGGP/TyQBIEVxW5Z qcxuwGE5qsjiLv+k3V/oKObZxdMPEnLzb+nrpJsTaRXuvsCfRwdC97hQ/1Ch0qzpqZPQ 11+1+Da8O9ADbQlTC2RhoR1buTV/ezg/9KwHLlDMJmDfHphzL00Tb2redXyiGlpFvqgO NNlzdifjOvRGcp16UqkPcC2+VRvv7tTO0dUFcvPmF95GFF+PBs4AtUyrm8j/GhrkB08H mxBymbMtonxmBBgzxOodD7pVGdEyWb7CYAaMtsqF+fLKhNz403Av+3anV8pM4IDB6PC1 mXZQ== X-Gm-Message-State: ACgBeo0flYEUTzOGGE8pB1TpPQ2M0y9rw39kyKa8d258utb8VT7ISHEX g8kgtzFyOUgsR/0ZwT+CfiN/TktCXhQ= X-Google-Smtp-Source: AA6agR6L83yADPN30GGaP6GLg4kUEQqYj8DfPdhtHK7erZLDsb/AXWFS4IdLEfz51ywVDni6Vm7C2g== X-Received: by 2002:a17:90b:3d92:b0:1fb:3854:69d2 with SMTP id pq18-20020a17090b3d9200b001fb385469d2mr5135364pjb.26.1661192737077; Mon, 22 Aug 2022 11:25:37 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:36 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 8/9] netdev: pass candidate list for netdev_fast_transition Date: Mon, 22 Aug 2022 11:25:24 -0700 Message-Id: <20220822182525.2078312-8-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Since FT-over-air authentication is done offchannel any failures during this stage are non-fatal. This means if a BSS target fails to authenticate for whatever reason IWD can move onto another. netdev_fast_transition now takes a list of scan_bss candidates, puts each into the ft_list (just like FT-over-DS) and tries each in order, proceeding to association on the first successful authentication. This assumes the candidate list is sorted with the head of the queue being the best ranked. --- src/netdev.c | 84 +++++++++++++++++++++++++++++++++++++++++---------- src/netdev.h | 2 +- src/station.c | 2 +- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/netdev.c b/src/netdev.c index f38b9c9a..d5e711ef 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -4591,6 +4591,25 @@ static const struct wiphy_radio_work_item_ops ft_work_ops = { .do_work = netdev_ft_work_ready, }; +static bool netdev_send_ft_authenticate(struct netdev *netdev, + struct netdev_ft_info *info); + +static bool netdev_ft_try_next_bss(struct netdev *netdev) +{ + struct netdev_ft_info *info; + + info = l_queue_pop_head(netdev->ft_list); + netdev_ft_entry_free(info); + + /* No more candidates */ + if (l_queue_isempty(netdev->ft_list)) + return false; + + info = l_queue_peek_head(netdev->ft_list); + + return netdev_send_ft_authenticate(netdev, info); +} + static void netdev_authenticate_response_ft_cb(const struct mmpdu_header *hdr, const void *body, size_t body_len, int rssi, @@ -4607,13 +4626,13 @@ static void netdev_authenticate_response_ft_cb(const struct mmpdu_header *hdr, info->super.spa, info->super.aa, info->super.aa, 2, &status, &ies, &ies_len)) - goto failed; + goto next; if (status != 0) - goto failed; + goto next; if (!ft_parse_ies(&info->super, netdev->handshake, ies, ies_len)) - goto failed; + goto next; /* If we got here authentication was successful, continue with FT */ netdev->ap = ft_over_air_sm_new(netdev->handshake, @@ -4627,11 +4646,17 @@ static void netdev_authenticate_response_ft_cb(const struct mmpdu_header *hdr, wiphy_radio_work_insert(netdev->wiphy, &netdev->work, WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops); + l_queue_destroy(netdev->ft_list, netdev_ft_entry_free); + netdev->ft_list = NULL; + return; -failed: - netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED, - MMPDU_STATUS_CODE_UNSPECIFIED); +next: + if (netdev_ft_try_next_bss(netdev)) + return; + + netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED, + MMPDU_STATUS_CODE_UNSPECIFIED); } static const struct frame_xchg_prefix ft_prefix = { @@ -4644,9 +4669,14 @@ static void netdev_cmd_authenticate_ft_cb(int err, void *user_data) { struct netdev_ft_info *info = user_data; - if (err < 0) - netdev_connect_failed(info->netdev, - NETDEV_RESULT_AUTHENTICATION_FAILED, + if (err == 0) + return; + + if (netdev_ft_try_next_bss(info->netdev)) + return; + + netdev_connect_failed(info->netdev, NETDEV_RESULT_AUTHENTICATION_FAILED, + MMPDU_STATUS_CODE_UNSPECIFIED); } static bool netdev_send_ft_authenticate(struct netdev *netdev, @@ -4728,26 +4758,48 @@ static struct netdev_ft_info *netdev_ft_info_new(struct netdev *netdev, } int netdev_fast_transition(struct netdev *netdev, - const struct scan_bss *target_bss, + struct l_queue *candidates, const struct scan_bss *orig_bss, netdev_connect_cb_t cb) { struct netdev_ft_info *info; + const struct l_queue_entry *entry; if (!netdev->operational) return -ENOTCONN; - if (!netdev->handshake->mde || !target_bss->mde_present || - l_get_le16(netdev->handshake->mde + 2) != - l_get_le16(target_bss->mde)) + if (!netdev->handshake->mde) return -EINVAL; - netdev->connect_cb = cb; + /* Initialize info for all candidates */ + for (entry = l_queue_get_entries(candidates); entry; + entry = entry->next) { + struct scan_bss *bss = entry->data; - info = netdev_ft_info_new(netdev, target_bss); + if (!bss->mde_present || + l_get_le16(netdev->handshake->mde + 2) != + l_get_le16(bss->mde)) + continue; + + info = netdev_ft_info_new(netdev, bss); + + if (!netdev->ft_list) + netdev->ft_list = l_queue_new(); + + l_queue_push_tail(netdev->ft_list, info); + } + + if (l_queue_isempty(netdev->ft_list)) + return -EINVAL; + + /* Begin with first candidate */ + info = l_queue_peek_head(netdev->ft_list); + + netdev->connect_cb = cb; if (!netdev_send_ft_authenticate(netdev, info)) { - netdev_ft_entry_free(info); + l_queue_destroy(netdev->ft_list, netdev_ft_entry_free); + netdev->ft_list = NULL; return -EBADMSG; } diff --git a/src/netdev.h b/src/netdev.h index d13bc5e6..f5818350 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -164,7 +164,7 @@ int netdev_reassociate(struct netdev *netdev, struct scan_bss *target_bss, netdev_event_func_t event_filter, netdev_connect_cb_t cb, void *user_data); int netdev_fast_transition(struct netdev *netdev, - const struct scan_bss *target_bss, + struct l_queue *candidates, const struct scan_bss *orig_bss, netdev_connect_cb_t cb); int netdev_fast_transition_over_ds_action(struct netdev *netdev, diff --git a/src/station.c b/src/station.c index 601c3916..1f0330b1 100644 --- a/src/station.c +++ b/src/station.c @@ -2238,7 +2238,7 @@ static void station_transition_start(struct station *station, } } else { try_over_air: - if (netdev_fast_transition(station->netdev, bss, + if (netdev_fast_transition(station->netdev, candidates, station->connected_bss, station_fast_transition_cb) < 0) { station_roam_failed(station); From patchwork Mon Aug 22 18:25:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Prestwood X-Patchwork-Id: 12951038 Received: from mail-pf1-f182.google.com (mail-pf1-f182.google.com [209.85.210.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD1A34A32 for ; Mon, 22 Aug 2022 18:25:38 +0000 (UTC) Received: by mail-pf1-f182.google.com with SMTP id w29so5586270pfj.3 for ; Mon, 22 Aug 2022 11:25:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=w5mFN58RG6SwurvJCh0zv0PIw4A9/dXWwrlmpaGkFBc=; b=LbaXh/i/9cCCv7S+z14JYu0AsDp7rLcqeMLNOZJJ//tlUcBNMTWngbPd7Q/oyQxyg/ +DTNvAnNcqcmmmSKhU0EJ7pRAAxYXWCprHIBiL4nUVo6t1FJAZN2dkiznXJcqh7xaoLC BJIuB5qSL+6Ww72skgwv5irsgTQiz+FZMkZKsjjbHMkj/U4j2/a42FbhcbLK5Gnm2bdd 7eFfWp1OzlFtbWRGFrPnIn9jh2pSlUn/xVa57rbvTkQlPEArcG3rx/ZH8eHBCucu+frW bXqTXRks5S0wSroJAjMg+39FIrMq2fRSzgA53Rs0o9qzDhz0BeAr/lEjAPb0VkCIsXHF 6HsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=w5mFN58RG6SwurvJCh0zv0PIw4A9/dXWwrlmpaGkFBc=; b=toKFfEm4dMbfguDAb0rMSEKWL9x76bo3XojcHRxywhFchm2jUZxJigsuI+bctQOdfR IXAJdAio632+YAHEJkXgbBYvwMw7xw9dF4ML7AaltHxA25pkYAV0EjBjvlMCdkHj7bwA FkYMxapZgRsH/5O+oESK2NiLSUw3GZCcIwC8XrvfxHpAqzeHvC+4aq0tUYHLJZovpT4R F0BdA1SspZOy2TjwyjJbqAnlnYpWRefX9gcaZXP0T5SSRbWbyTkPKTLQXWUzMY+7Xdxa x3vM+twrxHcFNESpF9zdNQ/+6nU/bCTyeeAzrzaDaqx/u9HPK6dO6+/Agu7bHny32usP 7vbA== X-Gm-Message-State: ACgBeo3VHBqt2m4Dbv0D0/06Eefq7I7IjKWn7/75kLv3vwlpmjRMZjNi goIET5Xb3t6xeuN4s8po1CGAJ5Elb0M= X-Google-Smtp-Source: AA6agR4oAM741yTMxlMDoBfdAcuHQyDicpU85Yndl3rKkanXipry9OSU1u/iD5pOtJcEX1OzyZe9pw== X-Received: by 2002:a63:ff5d:0:b0:42a:e27e:5506 with SMTP id s29-20020a63ff5d000000b0042ae27e5506mr999176pgk.41.1661192737814; Mon, 22 Aug 2022 11:25:37 -0700 (PDT) Received: from jprestwo-xps.none ([50.39.168.145]) by smtp.gmail.com with ESMTPSA id w1-20020a1709026f0100b00172bd4c12b2sm1612024plk.224.2022.08.22.11.25.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Aug 2022 11:25:37 -0700 (PDT) From: James Prestwood To: iwd@lists.linux.dev Cc: James Prestwood Subject: [PATCH 9/9] auto-t: add auth retry test to testPSK-roam Date: Mon, 22 Aug 2022 11:25:25 -0700 Message-Id: <20220822182525.2078312-9-prestwoj@gmail.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220822182525.2078312-1-prestwoj@gmail.com> References: <20220822182525.2078312-1-prestwoj@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This tests the new behavior where IWD will try to FT-authenticate with another BSS if it fails. --- autotests/testPSK-roam/connection_test.py | 2 +- autotests/testPSK-roam/ft-psk-ccmp-1.conf | 2 + autotests/testPSK-roam/ft-psk-ccmp-2.conf | 2 + autotests/testPSK-roam/ft-psk-ccmp-3.conf | 44 ++++++ autotests/testPSK-roam/hw.conf | 3 +- .../testPSK-roam/try_multiple_ft_test.py | 134 ++++++++++++++++++ 6 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 autotests/testPSK-roam/ft-psk-ccmp-3.conf create mode 100644 autotests/testPSK-roam/try_multiple_ft_test.py diff --git a/autotests/testPSK-roam/connection_test.py b/autotests/testPSK-roam/connection_test.py index 2206f120..77a7fd06 100644 --- a/autotests/testPSK-roam/connection_test.py +++ b/autotests/testPSK-roam/connection_test.py @@ -181,7 +181,7 @@ class Test(unittest.TestCase): cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'), HostapdCLI(config='ft-psk-ccmp-2.conf') ] rad0 = hwsim.get_radio('rad0') - rad2 = hwsim.get_radio('rad2') + rad2 = hwsim.get_radio('rad3') cls.rule0 = hwsim.rules.create() cls.rule0.source = rad2.addresses[0] diff --git a/autotests/testPSK-roam/ft-psk-ccmp-1.conf b/autotests/testPSK-roam/ft-psk-ccmp-1.conf index c012b4ef..86fb691a 100644 --- a/autotests/testPSK-roam/ft-psk-ccmp-1.conf +++ b/autotests/testPSK-roam/ft-psk-ccmp-1.conf @@ -26,8 +26,10 @@ mobility_domain=1234 reassociation_deadline=60000 r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:03 dummy3 000102030405060708090a0b0c0d0e0f r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f +r1kh=12:00:00:00:00:03 00:00:00:00:00:03 000102030405060708090a0b0c0d0e0f # Push mode only needed for 8021x, not PSK mode since msk already known pmk_r1_push=0 # Allow locally generated FT response so we don't have to configure push/pull diff --git a/autotests/testPSK-roam/ft-psk-ccmp-2.conf b/autotests/testPSK-roam/ft-psk-ccmp-2.conf index 84875fdc..c93b425b 100644 --- a/autotests/testPSK-roam/ft-psk-ccmp-2.conf +++ b/autotests/testPSK-roam/ft-psk-ccmp-2.conf @@ -26,8 +26,10 @@ mobility_domain=1234 reassociation_deadline=60000 r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:03 dummy3 000102030405060708090a0b0c0d0e0f r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f +r1kh=12:00:00:00:00:03 00:00:00:00:00:03 000102030405060708090a0b0c0d0e0f # Push mode only needed for 8021x, not PSK mode since msk already known pmk_r1_push=0 # Allow locally generated FT response so we don't have to configure push/pull diff --git a/autotests/testPSK-roam/ft-psk-ccmp-3.conf b/autotests/testPSK-roam/ft-psk-ccmp-3.conf new file mode 100644 index 00000000..321e1038 --- /dev/null +++ b/autotests/testPSK-roam/ft-psk-ccmp-3.conf @@ -0,0 +1,44 @@ +hw_mode=g +channel=3 +op_class=81 +ssid=TestFT +utf8_ssid=1 +ctrl_interface=/var/run/hostapd + +r1_key_holder=120000000003 +nas_identifier=dummy3 + +wpa=2 +# Can support WPA-PSK and FT-PSK (space separated list) and/or EAP at the same +# time but we want to force FT +wpa_key_mgmt=FT-PSK +wpa_pairwise=CCMP +wpa_passphrase=EasilyGuessedPassword +wpa_ptk_rekey=30 +wpa_group_rekey=80 +ieee80211w=1 +rsn_preauth=1 +rsn_preauth_interfaces=lo +disable_pmksa_caching=0 +# Allow PMK cache to be shared opportunistically among configured interfaces +# and BSSes (i.e., all configurations within a single hostapd process). +okc=1 +mobility_domain=1234 +reassociation_deadline=60000 +r0kh=12:00:00:00:00:01 dummy1 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:02 dummy2 000102030405060708090a0b0c0d0e0f +r0kh=12:00:00:00:00:03 dummy3 000102030405060708090a0b0c0d0e0f +r1kh=12:00:00:00:00:01 00:00:00:00:00:01 000102030405060708090a0b0c0d0e0f +r1kh=12:00:00:00:00:02 00:00:00:00:00:02 000102030405060708090a0b0c0d0e0f +r1kh=12:00:00:00:00:03 00:00:00:00:00:03 000102030405060708090a0b0c0d0e0f +# Push mode only needed for 8021x, not PSK mode since msk already known +pmk_r1_push=0 +# Allow locally generated FT response so we don't have to configure push/pull +# between BSSes running as separate hostapd processes as in the test-runner +# case. Only works with FT-PSK, otherwise brctl needs to be installed and +# CONFIG_BRIDGE enabled in the kernel. +ft_psk_generate_local=1 +ft_over_ds=0 +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 diff --git a/autotests/testPSK-roam/hw.conf b/autotests/testPSK-roam/hw.conf index c2b35d6e..da9e385c 100644 --- a/autotests/testPSK-roam/hw.conf +++ b/autotests/testPSK-roam/hw.conf @@ -1,8 +1,9 @@ [SETUP] -num_radios=3 +num_radios=4 start_iwd=0 hwsim_medium=yes [HOSTAPD] rad0=ft-psk-ccmp-1.conf rad1=ft-psk-ccmp-2.conf +rad2=ft-psk-ccmp-3.conf diff --git a/autotests/testPSK-roam/try_multiple_ft_test.py b/autotests/testPSK-roam/try_multiple_ft_test.py new file mode 100644 index 00000000..a0e1312e --- /dev/null +++ b/autotests/testPSK-roam/try_multiple_ft_test.py @@ -0,0 +1,134 @@ +#! /usr/bin/python3 + +import unittest +import sys, os + +sys.path.append('../util') +import iwd +from iwd import IWD +from iwd import PSKAgent +from iwd import NetworkType +from hwsim import Hwsim +from hostapd import HostapdCLI +import testutil + +class Test(unittest.TestCase): + def validate_connection(self, wd): + device = wd.list_devices(1)[0] + + ordered_network = device.get_ordered_network('TestFT', full_scan=True) + + self.assertEqual(ordered_network.type, NetworkType.psk) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertFalse(self.bss_hostapd[0].list_sta()) + self.assertFalse(self.bss_hostapd[1].list_sta()) + + device.connect_bssid(self.bss_hostapd[0].bssid) + + condition = 'obj.state == DeviceState.connected' + wd.wait_for_object_condition(device, condition) + + self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[1].ifname, device.name, True, True)) + + condition = 'obj.state == DeviceState.roaming' + wd.wait_for_object_condition(device, condition) + + # Check that iwd is on BSS 1 once out of roaming state and doesn't + # go through 'disconnected', 'autoconnect', 'connecting' in between + from_condition = 'obj.state == DeviceState.roaming' + to_condition = 'obj.state == DeviceState.connected' + wd.wait_for_object_change(device, from_condition, to_condition) + + self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address) + + testutil.test_iface_operstate(device.name) + testutil.test_ifaces_connected(self.bss_hostapd[1].ifname, device.name) + self.assertRaises(Exception, testutil.test_ifaces_connected, + (self.bss_hostapd[0].ifname, device.name, True, True)) + + self.bss_hostapd[1].deauthenticate(device.address) + condition = 'obj.state == DeviceState.disconnected' + wd.wait_for_object_condition(device, condition) + + def test_ft_psk(self): + wd = IWD(True) + + self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-PSK') + self.bss_hostapd[0].set_value('ft_over_ds', '0') + self.bss_hostapd[0].set_value('ocv', '1') + self.bss_hostapd[0].reload() + self.bss_hostapd[0].wait_for_event("AP-ENABLED") + + self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-PSK') + self.bss_hostapd[1].set_value('ft_over_ds', '0') + self.bss_hostapd[1].set_value('ocv', '1') + self.bss_hostapd[1].reload() + self.bss_hostapd[1].wait_for_event("AP-ENABLED") + + self.bss_hostapd[2].set_value('wpa_key_mgmt', 'FT-PSK') + self.bss_hostapd[2].set_value('ft_over_ds', '0') + self.bss_hostapd[2].set_value('ocv', '1') + self.bss_hostapd[2].reload() + self.bss_hostapd[2].wait_for_event("AP-ENABLED") + + self.validate_connection(wd) + + @classmethod + def setUpClass(cls): + hwsim = Hwsim() + + IWD.copy_to_storage('TestFT.psk') + + cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'), + HostapdCLI(config='ft-psk-ccmp-2.conf'), + HostapdCLI(config='ft-psk-ccmp-3.conf') ] + + cls.bss_hostapd[0].set_address('12:00:00:00:00:01') + cls.bss_hostapd[1].set_address('12:00:00:00:00:02') + cls.bss_hostapd[2].set_address('12:00:00:00:00:03') + + # Connect here first, worst candidate + cls.rule0 = hwsim.rules.create() + cls.rule0.source = hwsim.get_radio('rad0').addresses[0] + cls.rule0.bidirectional = True + cls.rule0.signal = -8500 + cls.rule0.enabled = True + + # Second best candidate, IWD should eventually get here after failing + # to connect to bss_hostapd[2] + cls.rule1 = hwsim.rules.create() + cls.rule1.source = hwsim.get_radio('rad1').addresses[0] + cls.rule1.bidirectional = True + cls.rule1.signal = -8000 + cls.rule1.enabled = True + + # Best candidate, IWD should try this first, fail (since auth is + # dropped), and move onto another candidate. + cls.rule2 = hwsim.rules.create() + cls.rule2.source = hwsim.get_radio('rad2').addresses[0] + cls.rule2.bidirectional = True + cls.rule2.signal = -2000 + cls.rule2.prefix = 'b0' + cls.rule2.drop = True + cls.rule2.enabled = True + + HostapdCLI.group_neighbors(*cls.bss_hostapd) + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + cls.bss_hostapd = None + cls.rule0.enabled = False + cls.rule1.enabled = False + cls.rule2.enabled = False + +if __name__ == '__main__': + unittest.main(exit=True)