From nobody Fri Dec 1 01:48:48 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ShGDw4VlSz535Z9; Fri, 1 Dec 2023 01:48:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ShGDw3lmXz4Xd6; Fri, 1 Dec 2023 01:48:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701395328; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=lFJ37nGX0FNYGHwOPJm3+cmIueKjO+UJ0sWs6EwqFbo=; b=mX09J3lzFuxqrVNaSL3344xNJ7lrnr5Pk8tiP26jw+FbcewM5faz54d6vgRAdlwaf8X1g7 lTrLR4Rd6DfRSowPjMgJrWDmkARMnZeEpiuJ5//bJeWc586kGjTEBCK6COiqtHMe5xdqLe F9LSoFAK2vuOWCMkE9eGDMbR81ReniJWfBjotBeMLBoplq9j0pOJ17tPcBZIU3BkjrI3Ic ONtnULBplPyzTohynEKd0sb6dzXAhY1AyvpUaDDKoQmK7GamS69UBSUkJcScfX/WKRhYES bvSITKQ4MXp7OeaHVSyKmNJJjoGhgrTbs+TEUwTkAjzpO3AuED+F+AB1cpau6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701395328; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=lFJ37nGX0FNYGHwOPJm3+cmIueKjO+UJ0sWs6EwqFbo=; b=CSPMRa9YwNXApVLyzGrYGaCsz8K4BJSrnICD/riU4suLHNpIFT8fddLKzcL7Cq+TMI/du7 MpWJMMckMkcEgFJy9RJcTr0abNBYtkOLJoND0e59iT2ekpR53dAaJK4taSC9EcR4tVFpmD 85wD2BBDyNwQWyUimyFgA9Sq4sz0bwZDdzbRMHtQrWjwo5kAyC9M/VScrKBcVPb+feSMVi txtGXPyibIqTGHxcOJdBPEuLouzcxjeoKy3M3exWw9uKg2bvj6W64Su2DNRY67kERMF0j3 vZiO/mZx0HwninDwrQJc7hXupeEmhcIYTfuynWyuddbwWlZndGnVpGctQIKk+Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1701395328; a=rsa-sha256; cv=none; b=bTbl69aUj8OR4YGFYQbqnFDkp/Oy+exh+RXZnE22aR3ygyGWHURNCedf26Io3PabwT42qJ huIf4WbR/VMItGlhJOQD0uUUrk28LOnVsn0tuNvWZH5jH2D9/RnfrOI/mhM150VBJ2ZH1T xllZKjBinYCyX0XkDL8r/HDRHLKy54WBjsZKKli7DxywFM45xU4bnSl8oJuqCsTLnunSr3 j5B8Hi0Hp8UaDX9ug4u0I3ZtOxN7ITs3a4gSuymPD4hbNiDQzOtawuXkfyxRK0N7VdNKS1 DPj6DzelvnPJbVH6py5lJbOJI00juvD+eVm6vkUJ9wanG9/tciJV+FNCOXbkcA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ShGDw2pXpz9Q; Fri, 1 Dec 2023 01:48:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 3B11mmRN074188; Fri, 1 Dec 2023 01:48:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3B11mm99074185; Fri, 1 Dec 2023 01:48:48 GMT (envelope-from git) Date: Fri, 1 Dec 2023 01:48:48 GMT Message-Id: <202312010148.3B11mm99074185@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 643d6dce6c1e - main - tools/net80211: add mlme_assoc List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 643d6dce6c1e39f067f8d0feea8615913b324891 Auto-Submitted: auto-generated The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=643d6dce6c1e39f067f8d0feea8615913b324891 commit 643d6dce6c1e39f067f8d0feea8615913b324891 Author: Bjoern A. Zeeb AuthorDate: 2023-12-01 01:37:25 +0000 Commit: Bjoern A. Zeeb CommitDate: 2023-12-01 01:48:34 +0000 tools/net80211: add mlme_assoc mlme_assoc is a tool to trigger net80211::ieee80211_sta_join1() calls which in certain conditions cause problems to the LinuxKPI 802.11 compat code (but also believed to possibly cause problems in case of race to other firmware based drivers). This has proven to be a good reproducer for the problem even on setups which otherwise could run for days without hitting it. Sponsored by: The FreeBSD Foundation PR: 271979 --- tools/tools/net80211/mlme_assoc/Makefile | 7 + tools/tools/net80211/mlme_assoc/README | 51 +++++++ tools/tools/net80211/mlme_assoc/mlme_assoc.c | 200 +++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) diff --git a/tools/tools/net80211/mlme_assoc/Makefile b/tools/tools/net80211/mlme_assoc/Makefile new file mode 100644 index 000000000000..580fb045ac52 --- /dev/null +++ b/tools/tools/net80211/mlme_assoc/Makefile @@ -0,0 +1,7 @@ +PROG= mlme_assoc +BINDIR= /usr/bin +MAN= + +SRCS= mlme_assoc.c + +.include diff --git a/tools/tools/net80211/mlme_assoc/README b/tools/tools/net80211/mlme_assoc/README new file mode 100644 index 000000000000..fc5e754a58d6 --- /dev/null +++ b/tools/tools/net80211/mlme_assoc/README @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 The FreeBSD Foundation +# +# This documentation was written by Björn Zeeb under sponsorship from +# the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +This is a simple program to drive net80211::ieee80211_sta_join1() calls from +user space. + +The program optionally accepts an interface name (e.g., wlan42), or an +interface name, an SSID and a BSSID. + +In the former case of no SSID/BSSID passed it will query the scan results and +then try to join each entry from the scan with a short delay. + +In the lastter case giving the SSID/BSSID one can trigger the "canreassoc" case +in ieee80211_sta_join1() or not depending on whether one passes the currently +associated SSID/BSSID or not. + +The tool is useful to trigger net80211::newstate() changes while other +newstate() changes are pending or being executed. + +I was specifically developed to show a problem with the LinuxKPI 802.11 compat +code. The reason is that ieee80211_sta_join1() also calls in (*iv_update_bss)() +swapping nodes before initiating the state changes and in LinuxKPI state is on +the sta and not the vif causing all kinds of troubles, especially if we lose +a state transition before the taskq is run or if the iv_bss node gets swapped +before a task is executed. diff --git a/tools/tools/net80211/mlme_assoc/mlme_assoc.c b/tools/tools/net80211/mlme_assoc/mlme_assoc.c new file mode 100644 index 000000000000..c26aaa03fe87 --- /dev/null +++ b/tools/tools/net80211/mlme_assoc/mlme_assoc.c @@ -0,0 +1,200 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * First get scan results in a hurry. + * Pick a random BSSID and try to assoc. + * Hopefully this is enough to trigger the newstate race along with the + * (*iv_update_bss)() logic. + * + * Alternatively pass IF SSID BSSID in and just try that. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +static int +if_up(int sd, const char *ifnam) +{ + struct ifreq ifr; + int error; + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifnam, sizeof(ifr.ifr_name)); + + error = ioctl(sd, SIOCGIFFLAGS, &ifr); + if (error == -1) { + warn("SIOCGIFFLAGS"); + return (error); + } + + if (ifr.ifr_flags & IFF_UP) + return (0); + + ifr.ifr_flags |= IFF_UP; + + error = ioctl(sd, SIOCSIFFLAGS, &ifr); + if (error == -1) { + warn("SIOCSIFFLAGS"); + return (error); + } + + return (0); +} + +static int +try_mlme_assoc(int sd, const char *ifnam, uint8_t *ssid, uint8_t ssid_len, uint8_t *bssid) +{ + struct ieee80211req ireq; + struct ieee80211req_mlme mlme; + int error; + + memset(&mlme, 0, sizeof(mlme)); + mlme.im_op = IEEE80211_MLME_ASSOC; + if (ssid != NULL) + memcpy(mlme.im_ssid, ssid, ssid_len); + mlme.im_ssid_len = ssid_len; + if (bssid != NULL) + memcpy(mlme.im_macaddr, bssid, IEEE80211_ADDR_LEN); + + memset(&ireq, 0, sizeof(ireq)); + strlcpy(ireq.i_name, ifnam, sizeof(ireq.i_name)); + ireq.i_type = IEEE80211_IOC_MLME; + ireq.i_val = 0; + ireq.i_data = (void *)&mlme; + ireq.i_len = sizeof(mlme); + + error = ioctl(sd, SIOCS80211, &ireq); + if (error == -1) { + warn("SIOCS80211, %#x", ireq.i_type); + return (error); + } + + return (0); +} + +static int +mlme_assoc_scan_results(int sd, const char *ifnam) +{ + struct ieee80211req ireq; + struct ieee80211req_scan_result *sr; + uint8_t buf[32 * 1024], *p; + ssize_t len; + int error; + + memset(&ireq, 0, sizeof(ireq)); + strlcpy(ireq.i_name, ifnam, sizeof(ireq.i_name)); + ireq.i_type = IEEE80211_IOC_SCAN_RESULTS; + ireq.i_data = (void *)buf; + ireq.i_len = sizeof(buf); + + error = ioctl(sd, SIOCG80211, &ireq); + if (error == -1 || ireq.i_len < 0) { + warn("SIOCG80211, %#x", ireq.i_type); + return (error); + } + + p = buf; + len = ireq.i_len; + while (len > (ssize_t)sizeof(*sr)) { + sr = (struct ieee80211req_scan_result *)(void *)p; + p += sr->isr_len; + len -= sr->isr_len; + + error = try_mlme_assoc(sd, ifnam, (void *)(sr + 1), sr->isr_ssid_len, + sr->isr_bssid); + if (error != 0) { + warnx("try_mlme_assoc"); + return (error); + } + + usleep(100000); + } + + return (0); +} + +int +main(int argc, char *argv[]) +{ + const char *ifnam; + uint8_t *ssid, *bssid; + struct ether_addr ea; + int error, sd; + + ifnam = "wlan0"; + ssid = NULL; + bssid = NULL; + + if (argc == 4) { + ifnam = argv[1]; + ssid = (uint8_t *)argv[2]; + bssid = (uint8_t *)ether_aton_r(argv[3], &ea); + if (bssid == NULL) + warnx("ether_aton_r, ignoring BSSID"); + } else if (argc == 2) { + ifnam = argv[1]; + } + + sd = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (sd == -1) + errx(EX_UNAVAILABLE, "socket"); + + error = if_up(sd, ifnam); + if (error != 0) + errx(EX_UNAVAILABLE, "if_up"); + + if (argc == 4) { + error = try_mlme_assoc(sd, ifnam, ssid, strlen((const char *)ssid), bssid); + if (error != 0) + errx(EX_UNAVAILABLE, "try_mlme_assoc"); + + } else { + error = mlme_assoc_scan_results(sd, ifnam); + if (error != 0) + errx(EX_UNAVAILABLE, "mlme_assoc_scan_results"); + } + + close(sd); + + return (0); +}