From d12a5ef640e8fb406f187fcb3962184f91d97902 Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Thu, 7 Jul 2022 12:36:27 +0530 Subject: [PATCH 001/150] Add support for Zephyr RTOS (#1) Modifications for building supplicant on Zephyr RTOS. Signed-off-by: Sridhar Nuvusetty Signed-off-by: Sachin Kulkarni Signed-off-by: Ravi Dondaputi Signed-off-by: Krishna T Co-authored-by: krishna T --- src/common/wpa_ctrl.c | 1 - src/crypto/crypto_mbedtls-bignum.c | 313 ++++++++ src/crypto/crypto_mbedtls-ec.c | 939 ++++++++++++++++++++++ src/crypto/crypto_mbedtls.c | 910 +++++++++++++++++++++ src/crypto/tls_mbedtls.c | 1181 ++++++++++++++++++++++++++++ src/drivers/driver.h | 4 + src/drivers/driver_zephyr.c | 733 +++++++++++++++++ src/drivers/driver_zephyr.h | 105 +++ src/drivers/drivers.c | 3 + src/l2_packet/l2_packet_zephyr.c | 251 ++++++ src/rsn_supp/wpa.h | 13 + src/utils/common.c | 10 + src/utils/common.h | 6 +- src/utils/eloop.c | 6 +- src/utils/includes.h | 17 +- src/utils/os.h | 45 +- src/utils/os_zephyr.c | 279 +++++++ wpa_supplicant/ctrl_iface.c | 1 + wpa_supplicant/ctrl_iface_udp.c | 1 - wpa_supplicant/events.c | 3 + wpa_supplicant/main.c | 2 + wpa_supplicant/scan.c | 2 + wpa_supplicant/wmm_ac.c | 2 + wpa_supplicant/wpa_cli.c | 155 ++-- wpa_supplicant/wpa_supplicant.c | 31 +- zephyr/CMakeLists.txt | 325 ++++++++ zephyr/Kconfig | 49 ++ zephyr/module.yml | 3 + zephyr/src/supp_main.c | 191 +++++ 29 files changed, 5521 insertions(+), 60 deletions(-) create mode 100644 src/crypto/crypto_mbedtls-bignum.c create mode 100644 src/crypto/crypto_mbedtls-ec.c create mode 100644 src/crypto/crypto_mbedtls.c create mode 100644 src/crypto/tls_mbedtls.c create mode 100644 src/drivers/driver_zephyr.c create mode 100644 src/drivers/driver_zephyr.h create mode 100644 src/l2_packet/l2_packet_zephyr.c create mode 100644 src/utils/os_zephyr.c create mode 100644 zephyr/CMakeLists.txt create mode 100644 zephyr/Kconfig create mode 100644 zephyr/module.yml create mode 100644 zephyr/src/supp_main.c diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c index 40a979531b..5f16bca492 100644 --- a/src/common/wpa_ctrl.c +++ b/src/common/wpa_ctrl.c @@ -35,7 +35,6 @@ #include "wpa_ctrl.h" #include "common.h" - #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) #define CTRL_IFACE_SOCKET #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c new file mode 100644 index 0000000000..bf49047a00 --- /dev/null +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -0,0 +1,313 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto.h" +#include "random.h" +#include "sha256.h" +#include "mbedtls/pk.h" +#include "mbedtls/ctr_drbg.h" + +static int f_rng(void *p_rng, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} + +struct crypto_bignum *crypto_bignum_init(void) +{ + + mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi)); + if (bn == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate BN\n", __func__); + return NULL; + } + + mbedtls_mpi_init(bn); + + return (struct crypto_bignum *)bn; +} + +struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len) +{ + int ret = 0; + mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi)); + if (bn == NULL) { + return NULL; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len)); + return (struct crypto_bignum *)bn; + +cleanup: + os_free(bn); + return NULL; +} + +int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) +{ + return mbedtls_mpi_random( + (mbedtls_mpi *)r, 0, (mbedtls_mpi *)m, f_rng, NULL); +} + +struct crypto_bignum *crypto_bignum_init_uint(unsigned int val) +{ + // MbedTLS works with BigEndian format + val = host_to_be32(val); + + return crypto_bignum_init_set((const u8 *)&val, sizeof(val)); +} + +void crypto_bignum_deinit(struct crypto_bignum *n, int clear) +{ + mbedtls_mpi_free((mbedtls_mpi *)n); + os_free((mbedtls_mpi *)n); +} + +int crypto_bignum_to_bin( + const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen) +{ + int num_bytes, offset; + int ret = 0; + + if (padlen > buflen) { + return -1; + } + + num_bytes = mbedtls_mpi_size((mbedtls_mpi *)a); + + if ((size_t)num_bytes > buflen) { + return -1; + } + if (padlen > (size_t)num_bytes) { + offset = padlen - num_bytes; + } else { + offset = 0; + } + + os_memset(buf, 0, offset); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary( + (mbedtls_mpi *)a, buf + offset, + mbedtls_mpi_size((mbedtls_mpi *)a))); + + return num_bytes + offset; +cleanup: + return ret; +} + +int crypto_bignum_add( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_add_mpi( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_mod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_mod_mpi( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_exptmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + const struct crypto_bignum *c, struct crypto_bignum *d) +{ + return mbedtls_mpi_exp_mod( + (mbedtls_mpi *)d, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b, (const mbedtls_mpi *)c, NULL) + ? -1 + : 0; +} + +int crypto_bignum_inverse( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_inv_mod( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_sub( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_sub_mpi( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_div( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_div_mpi( + (mbedtls_mpi *)c, NULL, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_mulmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + const struct crypto_bignum *c, struct crypto_bignum *d) +{ + int res; + + mbedtls_mpi temp; + mbedtls_mpi_init(&temp); + + res = mbedtls_mpi_mul_mpi( + &temp, (const mbedtls_mpi *)a, (const mbedtls_mpi *)b); + if (res) { + return -1; + } + + res = mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, &temp, (mbedtls_mpi *)c); + mbedtls_mpi_free(&temp); +# + return res ? -1 : 0; +} + +int crypto_bignum_cmp( + const struct crypto_bignum *a, const struct crypto_bignum *b) +{ + return mbedtls_mpi_cmp_mpi( + (const mbedtls_mpi *)a, (const mbedtls_mpi *)b); +} + +int crypto_bignum_bits(const struct crypto_bignum *a) +{ + return mbedtls_mpi_bitlen((const mbedtls_mpi *)a); +} + +int crypto_bignum_is_zero(const struct crypto_bignum *a) +{ + return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0); +} + +int crypto_bignum_is_one(const struct crypto_bignum *a) +{ + return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0); +} + +int crypto_bignum_sqrmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_exp_mod( + (mbedtls_mpi *)c, (mbedtls_mpi *)a, (mbedtls_mpi *)a, + (mbedtls_mpi *)b, NULL); +} + +int crypto_bignum_rshift( + const struct crypto_bignum *a, int n, struct crypto_bignum *r) +{ + + if (mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)) { + return -1; + } + return mbedtls_mpi_shift_r((mbedtls_mpi *)r, n); +} + +int crypto_bignum_legendre( + const struct crypto_bignum *a, const struct crypto_bignum *p) +{ + mbedtls_mpi exp, tmp; + int res = -2, ret; + + mbedtls_mpi_init(&exp); + mbedtls_mpi_init(&tmp); + + /* exp = (p-1) / 2 */ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &tmp, (const mbedtls_mpi *)a, &exp, (const mbedtls_mpi *)p, NULL)); + + if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) { + res = 1; + } else if ( + mbedtls_mpi_cmp_int(&tmp, 0) == 0 + /* The below check is workaround for the case where HW + * does not behave properly for X ^ A mod M when X is + * power of M. Instead of returning value 0, value M is + * returned.*/ + || mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) { + res = 0; + } else { + res = -1; + } + +cleanup: + mbedtls_mpi_free(&tmp); + mbedtls_mpi_free(&exp); + return res; +} + +int crypto_bignum_to_string( + const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen) +{ + int num_bytes, offset; + size_t outlen; + + if (padlen > buflen) { + return -1; + } + + num_bytes = mbedtls_mpi_size((mbedtls_mpi *)a); + + if (padlen > (size_t)num_bytes) { + offset = padlen - num_bytes; + } else { + offset = 0; + } + + os_memset(buf, 0, offset); + mbedtls_mpi_write_string( + (mbedtls_mpi *)a, 16, (char *)(buf + offset), + mbedtls_mpi_size((mbedtls_mpi *)a), &outlen); + + return outlen; +} + +int crypto_bignum_addmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + const struct crypto_bignum *c, struct crypto_bignum *d) +{ + struct crypto_bignum *tmp = crypto_bignum_init(); + int ret = -1; + + if (mbedtls_mpi_add_mpi( + (mbedtls_mpi *)tmp, (const mbedtls_mpi *)b, + (const mbedtls_mpi *)c) < 0) + goto fail; + + if (mbedtls_mpi_mod_mpi( + (mbedtls_mpi *)a, (const mbedtls_mpi *)tmp, + (const mbedtls_mpi *)d) < 0) + goto fail; + + ret = 0; +fail: + crypto_bignum_deinit(tmp, 0); + return ret; +} + +void crypto_free_buffer(unsigned char *buf) { os_free(buf); } diff --git a/src/crypto/crypto_mbedtls-ec.c b/src/crypto/crypto_mbedtls-ec.c new file mode 100644 index 0000000000..db2b38b69a --- /dev/null +++ b/src/crypto/crypto_mbedtls-ec.c @@ -0,0 +1,939 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto.h" +#include "sha256.h" +#include "crypto/random.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include "mbedtls/pk.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/sha256.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#define IANA_SECP256R1 19 +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES + +#ifdef CONFIG_ECC +static int f_rng(void *p_rng, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} +struct crypto_ec +{ + mbedtls_ecp_group group; +}; + +int crypto_rng_wrapper(void *ctx, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} + +const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.A; +} + +const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.B; +} + +size_t crypto_ec_order_len(struct crypto_ec *e) +{ + return (mbedtls_mpi_bitlen(&e->group.N) + 7) / 8; +} + +struct crypto_ec *crypto_ec_init(int group) +{ + struct crypto_ec *e; + + mbedtls_ecp_group_id grp_id; + + /* IANA registry to mbedtls internal mapping*/ + switch (group) { + case IANA_SECP256R1: + /* For now just support NIST-P256. + * This is of type "short Weierstrass". + */ + grp_id = MBEDTLS_ECP_DP_SECP256R1; + break; + default: + return NULL; + } + e = os_zalloc(sizeof(*e)); + if (e == NULL) { + return NULL; + } + + mbedtls_ecp_group_init(&e->group); + + if (mbedtls_ecp_group_load(&e->group, grp_id)) { + crypto_ec_deinit(e); + e = NULL; + } + + return e; +} + +void crypto_ec_deinit(struct crypto_ec *e) +{ + if (e == NULL) { + return; + } + + mbedtls_ecp_group_free(&e->group); + os_free(e); +} + +struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e) +{ + mbedtls_ecp_point *pt; + if (e == NULL) { + return NULL; + } + + pt = os_zalloc(sizeof(mbedtls_ecp_point)); + + if (pt == NULL) { + return NULL; + } + + mbedtls_ecp_point_init(pt); + + return (struct crypto_ec_point *)pt; +} + +size_t crypto_ec_prime_len(struct crypto_ec *e) +{ + return mbedtls_mpi_size(&e->group.P); +} + +size_t crypto_ec_prime_len_bits(struct crypto_ec *e) +{ + return mbedtls_mpi_bitlen(&e->group.P); +} +struct crypto_ec_group *crypto_ec_get_group_byname(const char *name) +{ + struct crypto_ec *e; + const mbedtls_ecp_curve_info *curve = + mbedtls_ecp_curve_info_from_name(name); + + e = os_zalloc(sizeof(*e)); + if (e == NULL) { + return NULL; + } + + mbedtls_ecp_group_init(&e->group); + + if (mbedtls_ecp_group_load(&e->group, curve->MBEDTLS_PRIVATE(grp_id))) { + crypto_ec_deinit(e); + e = NULL; + } + + return (struct crypto_ec_group *)&e->group; +} + +const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.P; +} + +const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.N; +} + +void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) +{ + mbedtls_ecp_point_free((mbedtls_ecp_point *)p); + os_free(p); +} + +int crypto_ec_point_to_bin( + struct crypto_ec *e, const struct crypto_ec_point *point, u8 *x, u8 *y) +{ + int len = mbedtls_mpi_size(&e->group.P); + + if (x) { + if (crypto_bignum_to_bin( + (struct crypto_bignum *)&((mbedtls_ecp_point *)point) + ->MBEDTLS_PRIVATE(X), + x, len, len) < 0) { + return -1; + } + } + + if (y) { + if (crypto_bignum_to_bin( + (struct crypto_bignum *)&((mbedtls_ecp_point *)point) + ->MBEDTLS_PRIVATE(Y), + y, len, len) < 0) { + return -1; + } + } + + return 0; +} + +int crypto_ec_get_affine_coordinates( + struct crypto_ec *e, struct crypto_ec_point *pt, struct crypto_bignum *x, + struct crypto_bignum *y) +{ + int ret = -1; + mbedtls_ecp_point *point = (mbedtls_ecp_point *)pt; + + if (!mbedtls_ecp_is_zero(point) && + (mbedtls_mpi_cmp_int(&point->MBEDTLS_PRIVATE(Z), 1) == 0)) { + // Affine coordinates mean that z should be 1, + wpa_printf(MSG_ERROR, "Z coordinate is neither 0 or 1"); + return -1; + } + + if (x) { + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + (mbedtls_mpi *)x, + &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X))); + } + if (y) { + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + (mbedtls_mpi *)y, + &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y))); + } + return 0; +cleanup: + return ret; +} + +int crypto_ec_point_x( + struct crypto_ec *e, const struct crypto_ec_point *p, + struct crypto_bignum *x) +{ + int ret = 0; + + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + (mbedtls_mpi *)x, &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X))); + + return 0; +cleanup: + return ret; +} + +struct crypto_ec_point * +crypto_ec_point_from_bin(struct crypto_ec *e, const u8 *val) +{ + mbedtls_ecp_point *pt; + int len, ret; + + if (e == NULL) { + return NULL; + } + + len = mbedtls_mpi_size(&e->group.P); + + pt = os_zalloc(sizeof(mbedtls_ecp_point)); + if (!pt) { + return NULL; + } + mbedtls_ecp_point_init(pt); + + MBEDTLS_MPI_CHK( + mbedtls_mpi_read_binary(&pt->MBEDTLS_PRIVATE(X), val, len)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_read_binary(&pt->MBEDTLS_PRIVATE(Y), val + len, len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->MBEDTLS_PRIVATE(Z)), 1)); + + return (struct crypto_ec_point *)pt; + +cleanup: + mbedtls_ecp_point_free(pt); + os_free(pt); + return NULL; +} + +int crypto_ec_point_add( + struct crypto_ec *e, const struct crypto_ec_point *a, + const struct crypto_ec_point *b, struct crypto_ec_point *c) +{ + int ret = 0; + mbedtls_mpi one; + + mbedtls_mpi_init(&one); + + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); + MBEDTLS_MPI_CHK(mbedtls_ecp_muladd( + &e->group, (mbedtls_ecp_point *)c, &one, + (const mbedtls_ecp_point *)a, &one, (const mbedtls_ecp_point *)b)); + +cleanup: + mbedtls_mpi_free(&one); + return ret ? -1 : 0; +} + +int crypto_ec_point_mul( + struct crypto_ec *e, const struct crypto_ec_point *p, + const struct crypto_bignum *b, struct crypto_ec_point *res) +{ + int ret = 0; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed( + &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)); + + MBEDTLS_MPI_CHK(mbedtls_ecp_mul( + &e->group, (mbedtls_ecp_point *)res, (const mbedtls_mpi *)b, + (const mbedtls_ecp_point *)p, mbedtls_ctr_drbg_random, &ctr_drbg)); +cleanup: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + if (ret) { + wpa_printf(MSG_ERROR, "%s: Failed with %d\n", __func__, ret); + } + return ret ? -1 : 0; +} + +/* Currently mbedtls does not have any function for inverse + * This function calculates inverse of a point. + * Set R = -P + */ +static int ecp_opp( + const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P) +{ + int ret = 0; + + /* Copy */ + if (R != P) { + MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); + } + + /* In-place opposite */ + if (mbedtls_mpi_cmp_int(&R->MBEDTLS_PRIVATE(Y), 0) != 0) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi( + &R->MBEDTLS_PRIVATE(Y), &grp->P, &R->MBEDTLS_PRIVATE(Y))); + } + +cleanup: + return (ret); +} + +int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) +{ + return ecp_opp( + &e->group, (mbedtls_ecp_point *)p, (mbedtls_ecp_point *)p) + ? -1 + : 0; +} + +int crypto_ec_point_solve_y_coord( + struct crypto_ec *e, struct crypto_ec_point *p, + const struct crypto_bignum *x, int y_bit) +{ + mbedtls_mpi temp; + mbedtls_mpi *y_sqr, *y; + mbedtls_mpi_init(&temp); + int ret = 0; + + y = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); + + /* Faster way to find sqrt + * Works only with curves having prime p + * such that p ≡ 3 (mod 4) + * y_ = (y2 ^ ((p+1)/4)) mod p + * + * if LSB of both x and y are same: y = y_ + * else y = p - y_ + * y_bit is LSB of x + */ + y_bit = (y_bit != 0); + + y_sqr = (mbedtls_mpi *)crypto_ec_point_compute_y_sqr(e, x); + + if (y_sqr) { + + MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&temp, &e->group.P, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp, NULL, &temp, 4)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_exp_mod(y, y_sqr, &temp, &e->group.P, NULL)); + + if (y_bit != mbedtls_mpi_get_bit(y, 0)) + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X), + (const mbedtls_mpi *)x)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset( + &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z), 1)); + } else { + ret = 1; + } +cleanup: + mbedtls_mpi_free(&temp); + mbedtls_mpi_free(y_sqr); + os_free(y_sqr); + return ret ? -1 : 0; +} + +int crypto_get_order(struct crypto_ec_group *group, struct crypto_bignum *x) +{ + return mbedtls_mpi_copy( + (mbedtls_mpi *)x, &((mbedtls_ecp_group *)group)->N); +} + +struct crypto_bignum *crypto_ec_point_compute_y_sqr( + struct crypto_ec *e, const struct crypto_bignum *x) +{ + mbedtls_mpi temp, temp2, num; + int ret = 0; + + mbedtls_mpi *y_sqr = os_zalloc(sizeof(mbedtls_mpi)); + if (y_sqr == NULL) { + return NULL; + } + + mbedtls_mpi_init(&temp); + mbedtls_mpi_init(&temp2); + mbedtls_mpi_init(&num); + mbedtls_mpi_init(y_sqr); + + /* y^2 = x^3 + ax + b mod P*/ + /* mbedtls does not have mod-add or mod-mul apis. + * + */ + + /* Calculate x^3 mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&num, 3)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &temp, (const mbedtls_mpi *)x, &num, &e->group.P, NULL)); + + /* Calculate ax mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&num, -3)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_mul_mpi(&temp2, (const mbedtls_mpi *)x, &num)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P)); + + /* Calculate ax + b mod P. Note that b is already < P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &e->group.B)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P)); + + /* Calculate x^3 + ax + b mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &temp)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y_sqr, &temp2, &e->group.P)); + +cleanup: + mbedtls_mpi_free(&temp); + mbedtls_mpi_free(&temp2); + mbedtls_mpi_free(&num); + if (ret) { + mbedtls_mpi_free(y_sqr); + os_free(y_sqr); + return NULL; + } else { + return (struct crypto_bignum *)y_sqr; + } +} + +int crypto_ec_point_is_at_infinity( + struct crypto_ec *e, const struct crypto_ec_point *p) +{ + return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p); +} + +int crypto_ec_point_is_on_curve( + struct crypto_ec *e, const struct crypto_ec_point *p) +{ + mbedtls_mpi y_sqr_lhs, *y_sqr_rhs = NULL, two; + int ret = 0, on_curve = 0; + + mbedtls_mpi_init(&y_sqr_lhs); + mbedtls_mpi_init(&two); + + /* Calculate y^2 mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&two, 2)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &y_sqr_lhs, &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y), + &two, &e->group.P, NULL)); + + y_sqr_rhs = (mbedtls_mpi *)crypto_ec_point_compute_y_sqr( + e, (const struct crypto_bignum *)&((const mbedtls_ecp_point *)p) + ->MBEDTLS_PRIVATE(X)); + + if (y_sqr_rhs && (mbedtls_mpi_cmp_mpi(y_sqr_rhs, &y_sqr_lhs) == 0)) { + on_curve = 1; + } + +cleanup: + mbedtls_mpi_free(&y_sqr_lhs); + mbedtls_mpi_free(&two); + mbedtls_mpi_free(y_sqr_rhs); + os_free(y_sqr_rhs); + return (ret == 0) && (on_curve == 1); +} + +int crypto_ec_point_cmp( + const struct crypto_ec *e, const struct crypto_ec_point *a, + const struct crypto_ec_point *b) +{ + return mbedtls_ecp_point_cmp( + (const mbedtls_ecp_point *)a, (const mbedtls_ecp_point *)b); +} + +void crypto_debug_print_point( + const char *title, struct crypto_ec *e, const struct crypto_ec_point *point) +{ + u8 x[32], y[32]; + + if (crypto_ec_point_to_bin(e, point, x, y) < 0) { + wpa_printf(MSG_ERROR, "error: failed to get corrdinates\n"); + return; + } + + wpa_hexdump(MSG_ERROR, "x:", x, 32); + wpa_hexdump(MSG_ERROR, "y:", y, 32); +} + +static struct crypto_key *crypto_alloc_key(void) +{ + mbedtls_pk_context *key = os_malloc(sizeof(*key)); + + if (!key) { + wpa_printf( + MSG_ERROR, "%s: memory allocation failed\n", __func__); + return NULL; + } + mbedtls_pk_init(key); + + return (struct crypto_key *)key; +} + +void crypto_ec_free_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + mbedtls_pk_free(pkey); + os_free(key); +} + +struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + + return (struct crypto_ec_point *)&mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE( + Q); +} + +int crypto_ec_get_priv_key_der( + struct crypto_key *key, unsigned char **key_data, int *key_len) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + char der_data[ECP_PRV_DER_MAX_BYTES]; + + *key_len = mbedtls_pk_write_key_der( + pkey, (unsigned char *)der_data, ECP_PRV_DER_MAX_BYTES); + if (*key_len <= 0) + return -1; + + *key_data = os_malloc(*key_len); + + if (!*key_data) { + wpa_printf(MSG_ERROR, "memory allocation failed\n"); + return -1; + } + os_memcpy(*key_data, der_data, *key_len); + + return 0; +} + +struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + + return (struct crypto_ec_group *)&( + mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(grp)); +} + +struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + + return ((struct crypto_bignum *)&( + mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(d))); +} + +int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE + 10]; /* tag, length + MPI */ + unsigned char *c = buf + sizeof(buf); + int pk_len = 0; + + memset(buf, 0, sizeof(buf)); + pk_len = mbedtls_pk_write_pubkey(&c, buf, pkey); + + if (pk_len < 0) + return -1; + + if (len == 0) + return pk_len; + + os_memcpy(key_buf, buf + MBEDTLS_MPI_MAX_SIZE + 10 - pk_len, pk_len); + + return pk_len; +} + +int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf) +{ + unsigned char output_buf[1600] = {0}; + int len = mbedtls_pk_write_pubkey_der( + (mbedtls_pk_context *)key, output_buf, 1600); + if (len <= 0) + return 0; + + *key_buf = os_malloc(len); + if (!*key_buf) { + return 0; + } + os_memcpy(*key_buf, output_buf + 1600 - len, len); + + return len; +} + +struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len) +{ + int ret = 0; + mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); + + if (!kctx) { + wpa_printf(MSG_ERROR, "memory allocation failed\n"); + return NULL; + } + ret = mbedtls_pk_parse_key( + kctx, privkey, privkey_len, NULL, 0, f_rng, NULL); + + if (ret < 0) { + // crypto_print_error_string(ret); + goto fail; + } + + return (struct crypto_key *)kctx; + +fail: + mbedtls_pk_free(kctx); + os_free(kctx); + return NULL; +} + +unsigned int crypto_ec_get_mbedtls_to_nist_group_id(int id) +{ + unsigned int nist_grpid = 0; + switch (id) { + case MBEDTLS_ECP_DP_SECP256R1: + nist_grpid = 19; + break; + case MBEDTLS_ECP_DP_SECP384R1: + nist_grpid = 20; + break; + case MBEDTLS_ECP_DP_SECP521R1: + nist_grpid = 21; + break; + case MBEDTLS_ECP_DP_BP256R1: + nist_grpid = 28; + break; + case MBEDTLS_ECP_DP_BP384R1: + nist_grpid = 29; + break; + case MBEDTLS_ECP_DP_BP512R1: + nist_grpid = 30; + break; + default: + break; + } + + return nist_grpid; +} + +int crypto_ec_get_curve_id(const struct crypto_ec_group *group) +{ + mbedtls_ecp_group *grp = (mbedtls_ecp_group *)group; + return (crypto_ec_get_mbedtls_to_nist_group_id(grp->id)); +} + +int crypto_ecdh( + struct crypto_key *key_own, struct crypto_key *key_peer, u8 *secret, + size_t *secret_len) +{ + mbedtls_ecdh_context *ctx; + mbedtls_pk_context *own = (mbedtls_pk_context *)key_own; + mbedtls_pk_context *peer = (mbedtls_pk_context *)key_peer; + + int ret = -1; + + *secret_len = 0; + ctx = os_malloc(sizeof(*ctx)); + if (!ctx) { + wpa_printf( + MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", __func__); + return -1; + } + + mbedtls_ecdh_init(ctx); + /* No need to setup, done through mbedtls_ecdh_get_params */ + + /* set params from our key */ + if (mbedtls_ecdh_get_params( + ctx, mbedtls_pk_ec(*own), MBEDTLS_ECDH_OURS) < 0) { + wpa_printf(MSG_ERROR, "failed to set our ecdh params\n"); + goto fail; + } + +#ifndef DPP_MAX_SHARED_SECRET_LEN +#define DPP_MAX_SHARED_SECRET_LEN 66 +#endif + /* set params from peers key */ + if (mbedtls_ecdh_get_params( + ctx, mbedtls_pk_ec(*peer), MBEDTLS_ECDH_THEIRS) < 0) { + wpa_printf(MSG_ERROR, "failed to set peer's ecdh params\n"); + goto fail; + } + + if (mbedtls_ecdh_calc_secret( + ctx, secret_len, secret, DPP_MAX_SHARED_SECRET_LEN, NULL, + NULL) < 0) { + wpa_printf(MSG_ERROR, "failed to calculate secret\n"); + goto fail; + } + + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + wpa_printf( + MSG_ERROR, "secret len=%d is too big\n", *secret_len); + goto fail; + } + + ret = 0; + +fail: + mbedtls_ecdh_free(ctx); + os_free(ctx); + return ret; +} + +void crypto_debug_print_ec_key(const char *title, struct crypto_key *key) +{ +#ifdef DEBUG_PRINT + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(*pkey); + u8 x[32], y[32], d[32]; + wpa_printf( + MSG_ERROR, "curve: %s\n", + mbedtls_ecp_curve_info_from_grp_id(ecp->grp.id)->name); + int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime( + (struct crypto_ec *)crypto_ec_get_group_from_key(key))); + + wpa_printf(MSG_ERROR, "prime len is %d\n", len); + crypto_ec_point_to_bin( + (struct crypto_ec *)crypto_ec_get_group_from_key(key), + crypto_ec_get_public_key(key), x, y); + crypto_bignum_to_bin(crypto_ec_get_private_key(key), d, len, len); + wpa_hexdump(MSG_ERROR, "Q_x:", x, 32); + wpa_hexdump(MSG_ERROR, "Q_y:", y, 32); + wpa_hexdump(MSG_ERROR, "d: ", d, 32); +#endif +} + +struct crypto_key * +crypto_ec_parse_subpub_key(const unsigned char *p, size_t len) +{ + int ret = 0; + mbedtls_pk_context *pkey = (mbedtls_pk_context *)crypto_alloc_key(); + ret = mbedtls_pk_parse_subpubkey((unsigned char **)&p, p + len, pkey); + + if (ret < 0) { + os_free(pkey); + return NULL; + } + + return (struct crypto_key *)pkey; +} + +int crypto_is_ec_key(struct crypto_key *key) +{ + int ret = + mbedtls_pk_can_do((mbedtls_pk_context *)key, MBEDTLS_PK_ECKEY); + return ret; +} + +struct crypto_key *crypto_ec_gen_keypair(u16 ike_group) +{ + mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); + + if (!kctx) { + wpa_printf( + MSG_ERROR, "%s: memory allocation failed\n", __func__); + return NULL; + } + + if (mbedtls_pk_setup( + kctx, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) != 0) + goto fail; + + mbedtls_ecp_gen_key( + MBEDTLS_ECP_DP_SECP256R1, + mbedtls_pk_ec(*kctx), // get this from argument + crypto_rng_wrapper, NULL); + + return (struct crypto_key *)kctx; +fail: + mbedtls_pk_free(kctx); + os_free(kctx); + return NULL; +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( + unsigned char **p, unsigned char *start, mbedtls_ecp_keypair *ec) +{ + int ret = 0; + size_t len = 0; + const char *oid; + size_t oid_len; + + if ((ret = mbedtls_oid_get_oid_by_ec_grp( + ec->MBEDTLS_PRIVATE(grp).id, &oid, &oid_len)) != 0) + return (ret); + + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); + + return ((int)len); +} + +static int pk_write_ec_pubkey_formatted( + unsigned char **p, unsigned char *start, mbedtls_ecp_keypair *ec, + int format) +{ + int ret = 0; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if ((ret = mbedtls_ecp_point_write_binary( + &ec->MBEDTLS_PRIVATE(grp), &ec->MBEDTLS_PRIVATE(Q), format, + &len, buf, sizeof(buf))) != 0) { + return (ret); + } + + if (*p < start || (size_t)(*p - start) < len) + return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); + + *p -= len; + memcpy(*p, buf, len); + + return ((int)len); +} + +int mbedtls_pk_write_pubkey_formatted( + unsigned char **p, unsigned char *start, const mbedtls_pk_context *key, + int format) +{ + int ret = 0; + size_t len = 0; + + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) + MBEDTLS_ASN1_CHK_ADD( + len, pk_write_ec_pubkey_formatted( + p, start, mbedtls_pk_ec(*key), format)); + else + return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); + + return ((int)len); +} + +int crypto_pk_write_formatted_pubkey_der( + mbedtls_pk_context *key, unsigned char *buf, size_t size, int format) +{ + int ret = 0; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + if (size == 0) + return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_pk_write_pubkey_formatted(&c, buf, key, format)); + + if (c - buf < 1) + return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); + + if ((ret = mbedtls_oid_get_oid_by_pk_alg( + mbedtls_pk_get_type(key), &oid, &oid_len)) != 0) { + return (ret); + } + + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { + MBEDTLS_ASN1_CHK_ADD( + par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); + } + + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_asn1_write_algorithm_identifier( + &c, buf, oid, oid_len, par_len)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD( + len, + mbedtls_asn1_write_tag( + &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return ((int)len); +} + +int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf) +{ + unsigned char output_buf[1600] = {0}; + int len = crypto_pk_write_formatted_pubkey_der( + (mbedtls_pk_context *)key, output_buf, 1600, 1); + if (len <= 0) + return 0; + + *key_buf = os_malloc(len); + if (!*key_buf) { + wpa_printf( + MSG_ERROR, "%s: memory allocation failed\n", __func__); + return 0; + } + os_memcpy(*key_buf, output_buf + 1600 - len, len); + + return len; +} +#endif /* CONFIG_ECC */ diff --git a/src/crypto/crypto_mbedtls.c b/src/crypto/crypto_mbedtls.c new file mode 100644 index 0000000000..a9ea78f2d3 --- /dev/null +++ b/src/crypto/crypto_mbedtls.c @@ -0,0 +1,910 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto.h" +#include "random.h" +#include "sha256.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/aes.h" +#include "mbedtls/bignum.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/cmac.h" +#include "mbedtls/nist_kw.h" +#include "mbedtls/des.h" +#include "mbedtls/ccm.h" +#ifdef MBEDTLS_ARC4_C +#include "mbedtls/arc4.h" +#endif + +#include "common.h" +#include "utils/wpabuf.h" +#include "dh_group5.h" +#include "sha1.h" +#include "sha256.h" +#include "md5.h" +#include "aes_wrap.h" +#include "crypto.h" + +static int digest_vector( + mbedtls_md_type_t md_type, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + size_t i; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = 0; + + mbedtls_md_init(&md_ctx); + + md_info = mbedtls_md_info_from_type(md_type); + if (!md_info) { + wpa_printf(MSG_ERROR, "mbedtls_md_info_from_type() failed"); + return -1; + } + + ret = mbedtls_md_setup(&md_ctx, md_info, 0); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_md_setup() returned error"); + goto cleanup; + } + + ret = mbedtls_md_starts(&md_ctx); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_md_starts returned error"); + goto cleanup; + } + + for (i = 0; i < num_elem; i++) { + ret = mbedtls_md_update(&md_ctx, addr[i], len[i]); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_md_update ret=%d", ret); + goto cleanup; + } + } + + ret = mbedtls_md_finish(&md_ctx, mac); +cleanup: + mbedtls_md_free(&md_ctx); + + return ret; +} + +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_SHA256, num_elem, addr, len, mac); +} + +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_SHA384, num_elem, addr, len, mac); +} + +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_SHA1, num_elem, addr, len, mac); +} + +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_MD5, num_elem, addr, len, mac); +} + +#ifdef MBEDTLS_MD4_C +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_MD4, num_elem, addr, len, mac); +} +#endif + +struct crypto_hash +{ + mbedtls_md_context_t ctx; +}; + +struct crypto_hash * +crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) +{ + struct crypto_hash *ctx; + mbedtls_md_type_t md_type; + const mbedtls_md_info_t *md_info; + int ret = 0; + + switch (alg) { + case CRYPTO_HASH_ALG_HMAC_MD5: + md_type = MBEDTLS_MD_MD5; + break; + case CRYPTO_HASH_ALG_HMAC_SHA1: + md_type = MBEDTLS_MD_SHA1; + break; + case CRYPTO_HASH_ALG_HMAC_SHA256: + md_type = MBEDTLS_MD_SHA256; + break; + default: + return NULL; + } + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + return NULL; + } + + mbedtls_md_init(&ctx->ctx); + md_info = mbedtls_md_info_from_type(md_type); + if (!md_info) { + os_free(ctx); + return NULL; + } + ret = mbedtls_md_setup(&ctx->ctx, md_info, 1); + if (ret != 0) { + os_free(ctx); + return NULL; + } + mbedtls_md_hmac_starts(&ctx->ctx, key, key_len); + + return ctx; +} + +void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) +{ + if (ctx == NULL) { + return; + } + mbedtls_md_hmac_update(&ctx->ctx, data, len); +} + +int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) +{ + if (ctx == NULL) { + return -2; + } + + if (mac == NULL || len == NULL) { + mbedtls_md_free(&ctx->ctx); + bin_clear_free(ctx, sizeof(*ctx)); + return 0; + } + mbedtls_md_hmac_finish(&ctx->ctx, mac); + mbedtls_md_free(&ctx->ctx); + bin_clear_free(ctx, sizeof(*ctx)); + + return 0; +} + +static int hmac_vector( + mbedtls_md_type_t md_type, const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + size_t i; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = 0; + + mbedtls_md_init(&md_ctx); + + md_info = mbedtls_md_info_from_type(md_type); + if (!md_info) { + return -1; + } + + ret = mbedtls_md_setup(&md_ctx, md_info, 1); + if (ret != 0) { + return (ret); + } + + mbedtls_md_hmac_starts(&md_ctx, key, key_len); + + for (i = 0; i < num_elem; i++) { + mbedtls_md_hmac_update(&md_ctx, addr[i], len[i]); + } + + mbedtls_md_hmac_finish(&md_ctx, mac); + + mbedtls_md_free(&md_ctx); + + return 0; +} + +int hmac_sha384_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_SHA384, key, key_len, num_elem, addr, len, mac); +} + +int hmac_sha384( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_sha256_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_SHA256, key, key_len, num_elem, addr, len, mac); +} + +int hmac_sha256( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_md5_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_MD5, key, key_len, num_elem, addr, len, mac); +} + +int hmac_md5( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_sha1_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_SHA1, key, key_len, num_elem, addr, len, mac); +} + +int hmac_sha1( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); +} + +static void *aes_crypt_init(int mode, const u8 *key, size_t len) +{ + int ret = -1; + mbedtls_aes_context *aes = os_malloc(sizeof(*aes)); + if (!aes) { + return NULL; + } + mbedtls_aes_init(aes); + + if (mode == MBEDTLS_AES_ENCRYPT) { + ret = mbedtls_aes_setkey_enc(aes, key, len * 8); + } else if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_setkey_dec(aes, key, len * 8); + } + if (ret < 0) { + mbedtls_aes_free(aes); + os_free(aes); + wpa_printf( + MSG_ERROR, + "%s: mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec failed", + __func__); + return NULL; + } + + return (void *)aes; +} + +static int aes_crypt(void *ctx, int mode, const u8 *in, u8 *out) +{ + return mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, mode, in, out); +} + +static void aes_crypt_deinit(void *ctx) +{ + mbedtls_aes_free((mbedtls_aes_context *)ctx); + os_free(ctx); +} + +void *aes_encrypt_init(const u8 *key, size_t len) +{ + return aes_crypt_init(MBEDTLS_AES_ENCRYPT, key, len); +} + +int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ + return aes_crypt(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt); +} + +void aes_encrypt_deinit(void *ctx) { return aes_crypt_deinit(ctx); } + +void *aes_decrypt_init(const u8 *key, size_t len) +{ + return aes_crypt_init(MBEDTLS_AES_DECRYPT, key, len); +} + +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +{ + return aes_crypt(ctx, MBEDTLS_AES_DECRYPT, crypt, plain); +} + +void aes_decrypt_deinit(void *ctx) { return aes_crypt_deinit(ctx); } + +int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + u8 cbc[MBEDTLS_AES_BLOCK_SIZE]; + + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_enc(&ctx, key, 128); + if (ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + os_memcpy(cbc, iv, MBEDTLS_AES_BLOCK_SIZE); + ret = mbedtls_aes_crypt_cbc( + &ctx, MBEDTLS_AES_ENCRYPT, data_len, cbc, data, data); + mbedtls_aes_free(&ctx); + + return ret; +} + +int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + u8 cbc[MBEDTLS_AES_BLOCK_SIZE]; + + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_dec(&ctx, key, 128); + if (ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + os_memcpy(cbc, iv, MBEDTLS_AES_BLOCK_SIZE); + ret = mbedtls_aes_crypt_cbc( + &ctx, MBEDTLS_AES_DECRYPT, data_len, cbc, data, data); + mbedtls_aes_free(&ctx); + + return ret; +} + +struct crypto_cipher +{ + mbedtls_cipher_context_t ctx_enc; + mbedtls_cipher_context_t ctx_dec; +}; + +static int crypto_init_cipher_ctx( + mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, + const u8 *iv, const u8 *key, mbedtls_operation_t operation) +{ + mbedtls_cipher_init(ctx); + int ret = 0; + + ret = mbedtls_cipher_setup(ctx, cipher_info); + if (ret != 0) { + return -1; + } + + if (mbedtls_cipher_setkey( + ctx, key, cipher_info->MBEDTLS_PRIVATE(key_bitlen), + operation) != 0) { + wpa_printf(MSG_ERROR, "mbedtls_cipher_setkey returned error"); + return -1; + } + if (mbedtls_cipher_set_iv( + ctx, iv, cipher_info->MBEDTLS_PRIVATE(iv_size)) != 0) { + wpa_printf(MSG_ERROR, "mbedtls_cipher_set_iv returned error"); + return -1; + } + if (mbedtls_cipher_reset(ctx) != 0) { + wpa_printf(MSG_ERROR, "mbedtls_cipher_reset() returned error"); + return -1; + } + + return 0; +} + +static mbedtls_cipher_type_t +alg_to_mbedtls_cipher(enum crypto_cipher_alg alg, size_t key_len) +{ + switch (alg) { +#ifdef MBEDTLS_ARC4_C + case CRYPTO_CIPHER_ALG_RC4: + return MBEDTLS_CIPHER_ARC4_128; +#endif + case CRYPTO_CIPHER_ALG_AES: + if (key_len == 16) { + return MBEDTLS_CIPHER_AES_128_CBC; + } + if (key_len == 24) { + return MBEDTLS_CIPHER_AES_192_CBC; + } + if (key_len == 32) { + return MBEDTLS_CIPHER_AES_256_CBC; + } + break; +#ifdef MBEDTLS_DES_C + case CRYPTO_CIPHER_ALG_3DES: + return MBEDTLS_CIPHER_DES_EDE3_CBC; + case CRYPTO_CIPHER_ALG_DES: + return MBEDTLS_CIPHER_DES_CBC; +#endif + default: + break; + } + + return MBEDTLS_CIPHER_NONE; +} + +struct crypto_cipher *crypto_cipher_init( + enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) +{ + struct crypto_cipher *ctx; + mbedtls_cipher_type_t cipher_type; + const mbedtls_cipher_info_t *cipher_info; + + ctx = (struct crypto_cipher *)os_zalloc(sizeof(*ctx)); + if (!ctx) { + return NULL; + } + + cipher_type = alg_to_mbedtls_cipher(alg, key_len); + if (cipher_type == MBEDTLS_CIPHER_NONE) { + goto cleanup; + } + + cipher_info = mbedtls_cipher_info_from_type(cipher_type); + if (cipher_info == NULL) { + goto cleanup; + } + + /* Init both ctx encryption/decryption */ + if (crypto_init_cipher_ctx( + &ctx->ctx_enc, cipher_info, iv, key, MBEDTLS_ENCRYPT) < 0) { + goto cleanup; + } + + if (crypto_init_cipher_ctx( + &ctx->ctx_dec, cipher_info, iv, key, MBEDTLS_DECRYPT) < 0) { + goto cleanup; + } + + return ctx; + +cleanup: + os_free(ctx); + return NULL; +} + +int crypto_cipher_encrypt( + struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) +{ + int ret = 0; + size_t olen = 1200; + + ret = mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen); + if (ret != 0) { + return -1; + } + + ret = mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen); + if (ret != 0) { + return -1; + } + + return 0; +} + +int crypto_cipher_decrypt( + struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) +{ + int ret = 0; + size_t olen = 1200; + + ret = mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen); + if (ret != 0) { + return -1; + } + + ret = mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen); + if (ret != 0) { + return -1; + } + + return 0; +} + +void crypto_cipher_deinit(struct crypto_cipher *ctx) +{ + mbedtls_cipher_free(&ctx->ctx_enc); + mbedtls_cipher_free(&ctx->ctx_dec); + os_free(ctx); +} + +int aes_ctr_encrypt( + const u8 *key, size_t key_len, const u8 *nonce, u8 *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + uint8_t stream_block[MBEDTLS_AES_BLOCK_SIZE]; + size_t offset = 0; + + mbedtls_aes_init(&ctx); + ret = mbedtls_aes_setkey_enc(&ctx, key, key_len * 8); + if (ret < 0) { + goto cleanup; + } + ret = mbedtls_aes_crypt_ctr( + &ctx, data_len, &offset, (u8 *)nonce, stream_block, data, data); +cleanup: + mbedtls_aes_free(&ctx); + return ret; +} + +int aes_128_ctr_encrypt( + const u8 *key, const u8 *nonce, u8 *data, size_t data_len) +{ + return aes_ctr_encrypt(key, 16, nonce, data, data_len); +} + +#ifdef MBEDTLS_NIST_KW_C +int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) +{ + mbedtls_nist_kw_context ctx; + size_t olen; + int ret = 0; + mbedtls_nist_kw_init(&ctx); + + ret = mbedtls_nist_kw_setkey( + &ctx, MBEDTLS_CIPHER_ID_AES, kek, kek_len * 8, 1); + if (ret != 0) { + return ret; + } + + ret = mbedtls_nist_kw_wrap( + &ctx, MBEDTLS_KW_MODE_KW, plain, n * 8, cipher, &olen, (n + 1) * 8); + + mbedtls_nist_kw_free(&ctx); + return ret; +} + +int aes_unwrap( + const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) +{ + mbedtls_nist_kw_context ctx; + size_t olen; + int ret = 0; + mbedtls_nist_kw_init(&ctx); + + ret = mbedtls_nist_kw_setkey( + &ctx, MBEDTLS_CIPHER_ID_AES, kek, kek_len * 8, 0); + if (ret != 0) { + return ret; + } + + ret = mbedtls_nist_kw_unwrap( + &ctx, MBEDTLS_KW_MODE_KW, cipher, (n + 1) * 8, plain, &olen, + (n * 8)); + + mbedtls_nist_kw_free(&ctx); + return ret; +} +#endif + +int crypto_mod_exp( + const uint8_t *base, size_t base_len, const uint8_t *power, + size_t power_len, const uint8_t *modulus, size_t modulus_len, + uint8_t *result, size_t *result_len) +{ + mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result, bn_rinv; + int ret = 0; + + mbedtls_mpi_init(&bn_base); + mbedtls_mpi_init(&bn_exp); + mbedtls_mpi_init(&bn_modulus); + mbedtls_mpi_init(&bn_result); + mbedtls_mpi_init(&bn_rinv); + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&bn_base, base, base_len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&bn_exp, power, power_len)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &bn_result, &bn_base, &bn_exp, &bn_modulus, &bn_rinv)); + + ret = mbedtls_mpi_write_binary(&bn_result, result, *result_len); + +cleanup: + mbedtls_mpi_free(&bn_base); + mbedtls_mpi_free(&bn_exp); + mbedtls_mpi_free(&bn_modulus); + mbedtls_mpi_free(&bn_result); + mbedtls_mpi_free(&bn_rinv); + + return ret; +} + +int pbkdf2_sha1( + const char *passphrase, const u8 *ssid, size_t ssid_len, int iterations, + u8 *buf, size_t buflen) +{ + + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret = 0; + + mbedtls_md_init(&sha1_ctx); + + info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + if (info_sha1 == NULL) { + ret = -1; + goto cleanup; + } + + if ((ret = mbedtls_md_setup(&sha1_ctx, info_sha1, 1)) != 0) { + ret = -1; + goto cleanup; + } + + ret = mbedtls_pkcs5_pbkdf2_hmac( + &sha1_ctx, (const u8 *)passphrase, os_strlen(passphrase), ssid, + ssid_len, iterations, 32, buf); + if (ret != 0) { + ret = -1; + goto cleanup; + } + +cleanup: + mbedtls_md_free(&sha1_ctx); + return ret; +} + +#ifdef MBEDTLS_DES_C +int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) +{ + int ret = 0; + mbedtls_des_context des; + u8 pkey[8], next, tmp; + int i; + + /* Add parity bits to the key */ + next = 0; + for (i = 0; i < 7; i++) { + tmp = key[i]; + pkey[i] = (tmp >> i) | next | 1; + next = tmp << (7 - i); + } + pkey[i] = next | 1; + + mbedtls_des_init(&des); + ret = mbedtls_des_setkey_enc(&des, pkey); + if (ret < 0) { + return ret; + } + ret = mbedtls_des_crypt_ecb(&des, clear, cypher); + mbedtls_des_free(&des); + + return ret; +} +#endif + +/* Only enable this if all other ciphers are using MbedTLS implementation */ +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CMAC_C) && \ + defined(MBEDTLS_NIST_KW_C) +int aes_ccm_ae( + const u8 *key, size_t key_len, const u8 *nonce, size_t M, const u8 *plain, + size_t plain_len, const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth) +{ + int ret = 0; + mbedtls_ccm_context ccm; + + mbedtls_ccm_init(&ccm); + + ret = mbedtls_ccm_setkey(&ccm, MBEDTLS_CIPHER_ID_AES, key, key_len * 8); + if (ret < 0) { + wpa_printf(MSG_ERROR, "mbedtls_ccm_setkey failed"); + goto cleanup; + } + + ret = mbedtls_ccm_encrypt_and_tag( + &ccm, plain_len, nonce, 13, aad, aad_len, plain, crypt, auth, M); + +cleanup: + mbedtls_ccm_free(&ccm); + + return ret; +} + +int aes_ccm_ad( + const u8 *key, size_t key_len, const u8 *nonce, size_t M, const u8 *crypt, + size_t crypt_len, const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain) +{ + int ret = 0; + mbedtls_ccm_context ccm; + + mbedtls_ccm_init(&ccm); + + ret = mbedtls_ccm_setkey(&ccm, MBEDTLS_CIPHER_ID_AES, key, key_len * 8); + if (ret < 0) { + goto cleanup; + ; + } + + ret = mbedtls_ccm_star_auth_decrypt( + &ccm, crypt_len, nonce, 13, aad, aad_len, crypt, plain, auth, M); + +cleanup: + mbedtls_ccm_free(&ccm); + + return ret; +} +#endif + +#ifdef MBEDTLS_ARC4_C +int rc4_skip( + const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) +{ + int ret = 0; + unsigned char skip_buf_in[16]; + unsigned char skip_buf_out[16]; + mbedtls_arc4_context ctx; + unsigned char *obuf = os_malloc(data_len); + + if (!obuf) { + wpa_printf(MSG_ERROR, "%s:memory allocation failed", __func__); + return -1; + } + mbedtls_arc4_init(&ctx); + mbedtls_arc4_setup(&ctx, key, keylen); + while (skip >= sizeof(skip_buf_in)) { + size_t len = skip; + if (len > sizeof(skip_buf_in)) { + len = sizeof(skip_buf_in); + } + if ((ret = mbedtls_arc4_crypt( + &ctx, len, skip_buf_in, skip_buf_out)) != 0) { + wpa_printf(MSG_ERROR, "rc4 encryption failed"); + return -1; + } + os_memcpy(skip_buf_in, skip_buf_out, 16); + skip -= len; + } + + mbedtls_arc4_crypt(&ctx, data_len, data, obuf); + + memcpy(data, obuf, data_len); + os_free(obuf); + + return 0; +} +#endif + +#ifdef MBEDTLS_CMAC_C +int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); +} + +int omac1_aes_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + mbedtls_cipher_type_t cipher_type; + mbedtls_cipher_context_t ctx; + + switch (key_len) { + case 16: + cipher_type = MBEDTLS_CIPHER_AES_128_ECB; + break; + case 24: + cipher_type = MBEDTLS_CIPHER_AES_192_ECB; + break; + case 32: + cipher_type = MBEDTLS_CIPHER_AES_256_ECB; + break; + default: + cipher_type = MBEDTLS_CIPHER_NONE; + break; + } + cipher_info = mbedtls_cipher_info_from_type(cipher_type); + if (cipher_info == NULL) { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + + if (key == NULL || mac == NULL) { + return -1; + } + + mbedtls_cipher_init(&ctx); + + ret = mbedtls_cipher_setup(&ctx, cipher_info); + if (ret != 0) { + goto cleanup; + } + + ret = mbedtls_cipher_cmac_starts(&ctx, key, key_len * 8); + if (ret != 0) { + goto cleanup; + } + + for (i = 0; i < num_elem; i++) { + ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]); + if (ret != 0) { + goto cleanup; + } + } + + ret = mbedtls_cipher_cmac_finish(&ctx, mac); +cleanup: + mbedtls_cipher_free(&ctx); + return (ret); +} + +int omac1_aes_128_vector( + const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + return omac1_aes_vector(key, 16, num_elem, addr, len, mac); +} + +int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_128_vector(key, 1, &data, &data_len, mac); +} +#endif + +int crypto_bignum_is_odd(const struct crypto_bignum *a) +{ + return mbedtls_mpi_get_bit((mbedtls_mpi *)a, 0); +} + +int crypto_dh_derive_secret( + u8 generator, const u8 *prime, size_t prime_len, const u8 *order, + size_t order_len, const u8 *privkey, size_t privkey_len, const u8 *pubkey, + size_t pubkey_len, u8 *secret, size_t *len) +{ + return crypto_mod_exp( + prime, prime_len, privkey, privkey_len, pubkey, pubkey_len, secret, + len); +} + +int crypto_dh_init( + u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, u8 *pubkey) +{ + size_t pubkey_len, pad; + + if (os_get_random(privkey, prime_len) < 0) { + return -1; + } + if (os_memcmp(privkey, prime, prime_len) > 0) { + /* Make sure private value is smaller than prime */ + privkey[0] = 0; + } + + pubkey_len = prime_len; + if (crypto_mod_exp( + &generator, 1, privkey, prime_len, prime, prime_len, pubkey, + &pubkey_len) < 0) { + return -1; + } + if (pubkey_len < prime_len) { + pad = prime_len - pubkey_len; + os_memmove(pubkey + pad, pubkey, pubkey_len); + os_memset(pubkey, 0, pad); + } + + return 0; +} diff --git a/src/crypto/tls_mbedtls.c b/src/crypto/tls_mbedtls.c new file mode 100644 index 0000000000..e13c10a74e --- /dev/null +++ b/src/crypto/tls_mbedtls.c @@ -0,0 +1,1181 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" + +#include "tls.h" +#include "crypto/sha1.h" +#include "crypto/md5.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "random.h" +#include +#include +#include +#include +#include +#include +#include + +#define TLS_RANDOM_LEN 32 +#define TLS_MASTER_SECRET_LEN 48 +#define MAX_CIPHERSUITE 32 + +/* Throw a compilation error if basic requirements in mbedtls are not enabled */ +#if !defined(MBEDTLS_SSL_TLS_C) +#error "TLS not enabled in mbedtls config" +#endif + +#if !defined(MBEDTLS_SHA256_C) +#error "SHA256 is disabled in mbedtls config" +#endif + +#if !defined(MBEDTLS_AES_C) +#error "AES support is disabled in mbedtls config" +#endif + +uint32_t tls_instance_count; +struct tls_data +{ + /* Data for mbedlts */ + struct wpabuf *in_data; + /* Data from mbedtls */ + struct wpabuf *out_data; +}; + +mbedtls_ssl_export_keys_t tls_connection_export_keys_cb; + +typedef struct tls_context +{ + mbedtls_ssl_context ssl; /*!< TLS/SSL context */ + mbedtls_entropy_context + entropy; /*!< mbedTLS entropy context structure */ + mbedtls_ctr_drbg_context + ctr_drbg; /*!< mbedTLS ctr drbg context structure */ + mbedtls_ssl_config conf; /*!< TLS/SSL config to be shared structures */ + mbedtls_x509_crt cacert; /*!< Container for X.509 CA certificate */ + mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */ + mbedtls_x509_crt + clientcert; /*!< Container for X.509 client certificate */ + mbedtls_pk_context clientkey; /*!< Private key of client certificate */ + int ciphersuite[MAX_CIPHERSUITE]; +} tls_context_t; + +struct tls_connection +{ + tls_context_t *tls; + struct tls_data tls_io_data; + unsigned char master_secret[TLS_MASTER_SECRET_LEN]; + unsigned char randbytes[2 * TLS_RANDOM_LEN]; + mbedtls_tls_prf_types tls_prf_type; +}; + +static int f_rng(void *p_rng, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} + +static void tls_mbedtls_cleanup(tls_context_t *tls) +{ + if (!tls) { + return; + } + tls->cacert_ptr = NULL; + mbedtls_x509_crt_free(&tls->cacert); + mbedtls_x509_crt_free(&tls->clientcert); + mbedtls_pk_free(&tls->clientkey); + mbedtls_entropy_free(&tls->entropy); + mbedtls_ssl_config_free(&tls->conf); + mbedtls_ctr_drbg_free(&tls->ctr_drbg); + mbedtls_ssl_free(&tls->ssl); +} + +static void tls_mbedtls_conn_delete(tls_context_t *tls) +{ + if (tls != NULL) { + tls_mbedtls_cleanup(tls); + } +} + +static int tls_mbedtls_write(void *ctx, const unsigned char *buf, size_t len) +{ + struct tls_connection *conn = (struct tls_connection *)ctx; + struct tls_data *data = &conn->tls_io_data; + + if (wpabuf_resize(&data->out_data, len) < 0) + return 0; + + wpabuf_put_data(data->out_data, buf, len); + + return len; +} + +static int tls_mbedtls_read(void *ctx, unsigned char *buf, size_t len) +{ + struct tls_connection *conn = (struct tls_connection *)ctx; + struct tls_data *data = &conn->tls_io_data; + struct wpabuf *local_buf; + size_t data_len = len; + + if (data->in_data == NULL) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + + if (len > wpabuf_len(data->in_data)) { + wpa_printf(MSG_ERROR, "don't have suffient data\n"); + data_len = wpabuf_len(data->in_data); + } + + os_memcpy(buf, wpabuf_head(data->in_data), data_len); + /* adjust buffer */ + if (len < wpabuf_len(data->in_data)) { + local_buf = wpabuf_alloc_copy( + (char *)wpabuf_head(data->in_data) + data_len, + wpabuf_len(data->in_data) - data_len); + wpabuf_free(data->in_data); + data->in_data = local_buf; + } else { + wpabuf_free(data->in_data); + data->in_data = NULL; + } + + return data_len; +} + +static int +set_pki_context(tls_context_t *tls, const struct tls_connection_params *cfg) +{ + int ret = 0; + + if (cfg->client_cert_blob == NULL || cfg->private_key_blob == NULL) { + wpa_printf(MSG_ERROR, "%s: config not correct", __func__); + return -1; + } + + mbedtls_x509_crt_init(&tls->clientcert); + mbedtls_pk_init(&tls->clientkey); + + ret = mbedtls_x509_crt_parse( + &tls->clientcert, cfg->client_cert_blob, cfg->client_cert_blob_len); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret); + return ret; + } + + ret = mbedtls_pk_parse_key( + &tls->clientkey, cfg->private_key_blob, cfg->private_key_blob_len, + (const unsigned char *)cfg->private_key_passwd, + cfg->private_key_passwd ? os_strlen(cfg->private_key_passwd) : 0, + f_rng, NULL); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); + return ret; + } + + ret = mbedtls_ssl_conf_own_cert( + &tls->conf, &tls->clientcert, &tls->clientkey); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_ssl_conf_own_cert returned -0x%x", + -ret); + return ret; + } + + return 0; +} + +static int +set_ca_cert(tls_context_t *tls, const unsigned char *cacert, size_t cacert_len) +{ + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret); + return ret; + } + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + + return 0; +} + +#ifdef CONFIG_SUITEB192 +static int tls_sig_hashes_for_suiteb[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA384, +#endif + MBEDTLS_MD_NONE}; + +const mbedtls_x509_crt_profile suiteb_mbedtls_x509_crt_profile = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | +#endif + 0, + 0xFFFFFFF, /* Any PK alg */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), + 1024, +}; + +static void tls_set_suiteb_config(tls_context_t *tls) +{ + const mbedtls_x509_crt_profile *crt_profile = + &suiteb_mbedtls_x509_crt_profile; + mbedtls_ssl_conf_cert_profile(&tls->conf, crt_profile); + mbedtls_ssl_conf_sig_hashes(&tls->conf, tls_sig_hashes_for_suiteb); +} +#endif + +static int tls_sig_hashes_for_eap[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE}; + +const mbedtls_x509_crt_profile eap_mbedtls_x509_crt_profile = { +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | +#endif +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | +#endif + 0, + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1024, +}; + +static void tls_enable_sha1_config(tls_context_t *tls) +{ + const mbedtls_x509_crt_profile *crt_profile = + &eap_mbedtls_x509_crt_profile; + mbedtls_ssl_conf_cert_profile(&tls->conf, crt_profile); + mbedtls_ssl_conf_sig_hashes(&tls->conf, tls_sig_hashes_for_eap); +} + +static const int eap_ciphersuite_preference[] = { +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, +#endif +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, +#endif + +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, +#endif +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, +#endif +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, +#endif + +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, +#endif +/* The PSK suites */ +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, +#endif + +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, +#endif +#endif + +#if 0 + /* 3DES suites */ + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, +#endif +#if defined(MBEDTLS_ARC4_C) + /* RC4 suites */ + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, +#endif + 0}; + +#ifdef CONFIG_SUITEB192 +static const int suiteb_rsa_ciphersuite_preference[] = { +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif +#endif + 0}; + +static const int suiteb_ecc_ciphersuite_preference[] = { +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, +#endif +#endif + 0}; +static const int suiteb_ciphersuite_preference[] = { +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif +#endif + 0}; +#endif + +static void +tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_context_t *tls) +{ + /* Only set ciphersuite if cert's key length is high or ciphersuites are + * set by user */ +#ifdef CONFIG_SUITEB192 + if (cfg->flags & TLS_CONN_SUITEB) { + /* cipher suites will be set based on certificate */ + mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&tls->clientkey); + if (pk_alg == MBEDTLS_PK_RSA || + pk_alg == MBEDTLS_PK_RSASSA_PSS) { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, suiteb_rsa_ciphersuite_preference); + } else if ( + pk_alg == MBEDTLS_PK_ECDSA || pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH) { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, suiteb_ecc_ciphersuite_preference); + } else { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, suiteb_ciphersuite_preference); + } + } else +#endif + if (tls->ciphersuite[0]) { + mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite); + } else if ( + mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 || + (tls->cacert_ptr && + mbedtls_pk_get_bitlen(&tls->cacert_ptr->MBEDTLS_PRIVATE(pk)) > + 2048)) { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, eap_ciphersuite_preference); + } +} + +static int +parse_certs(const struct tls_connection_params *cfg, tls_context_t *tls) +{ + int ret = 0; + +#ifdef CONFIG_MBEDTLS_FS_IO + if (cfg->ca_cert) { + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + + ret = mbedtls_x509_crt_parse_file(&tls->cacert, cfg->ca_cert); + if (ret < 0) { + wpa_printf( + MSG_ERROR, + "mbedtls_x509_crt_parse_der failed -0x%x", -ret); + return -1; + } + + mbedtls_ssl_conf_authmode( + &tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + wpa_printf(MSG_ERROR, "Loaded CA cert: %s\n", cfg->ca_cert); + + } else +#endif + if (cfg->ca_cert_blob != NULL) { + ret = + set_ca_cert(tls, cfg->ca_cert_blob, cfg->ca_cert_blob_len); + if (ret != 0) { + return ret; + } + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); + } + +#ifdef CONFIG_MBEDTLS_FS_IO + if (cfg->client_cert && cfg->private_key) { + mbedtls_x509_crt_init(&tls->clientcert); + ret = mbedtls_x509_crt_parse_file( + &tls->clientcert, cfg->client_cert); + if (ret < 0) { + wpa_printf( + MSG_ERROR, + "mbedtls_x509_crt_parse_der failed -0x%x", -ret); + return -1; + } + wpa_printf( + MSG_ERROR, "Loaded Client cert: %s\n", cfg->client_cert); + + mbedtls_pk_init(&tls->clientkey); + ret = mbedtls_pk_parse_keyfile( + &tls->clientkey, cfg->private_key, cfg->private_key_passwd, + f_rng, NULL); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_pk_parse_key failed -0x%x", + -ret); + return -1; + } + wpa_printf( + MSG_ERROR, "Loaded private key: %s\n", cfg->private_key); + + ret = mbedtls_ssl_conf_own_cert( + &tls->conf, &tls->clientcert, &tls->clientkey); + if (ret < 0) { + wpa_printf( + MSG_ERROR, + "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); + return ret; + } + wpa_printf(MSG_ERROR, "Loaded client and key\n"); + + } else +#endif + if (cfg->client_cert_blob != NULL && + cfg->private_key_blob != NULL) { + ret = set_pki_context(tls, cfg); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "Failed to set client pki context"); + return ret; + } + } + + return 0; +} + +static int +set_client_config(const struct tls_connection_params *cfg, tls_context_t *tls) +{ + int ret = 0; + int preset = MBEDTLS_SSL_PRESET_DEFAULT; + assert(cfg != NULL); + assert(tls != NULL); + +#ifdef CONFIG_SUITEB192 + if (cfg->flags & TLS_CONN_SUITEB) + preset = MBEDTLS_SSL_PRESET_SUITEB; +#endif + ret = mbedtls_ssl_config_defaults( + &tls->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, + preset); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "mbedtls_ssl_config_defaults returned -0x%x", + -ret); + return ret; + } + + if (preset != MBEDTLS_SSL_PRESET_SUITEB) { + /* Enable SHA1 support since it's not enabled by default in + * mbedtls */ + tls_enable_sha1_config(tls); +#ifdef CONFIG_SUITEB192 + } else { + tls_set_suiteb_config(tls); +#endif + } + wpa_printf( + MSG_ERROR, ": mbedtls_ssl_config_defaults: ciphersuite: %s\n", + mbedtls_ssl_get_ciphersuite(&tls->ssl)); + + wpa_printf(MSG_ERROR, ": CA cert: %s\n", cfg->ca_cert); + wpa_printf(MSG_ERROR, ": Client cert: %s\n", cfg->client_cert); + wpa_printf(MSG_ERROR, ": Client key: %s\n", cfg->private_key); + + if ((ret = parse_certs(cfg, tls))) { + wpa_printf(MSG_ERROR, "Failed to load certs: %d\n", ret); + return ret; + } + wpa_printf(MSG_INFO, "Loaded certs\n"); + + /* Usages of default ciphersuites can take a lot of time on low end + * device and can cause watchdog. Enabling the ciphers which are secured + * enough but doesn't take that much processing power */ + tls_set_ciphersuite(cfg, tls); + + return 0; +} + +static int tls_create_mbedtls_handle( + const struct tls_connection_params *params, tls_context_t *tls) +{ + int ret = 0; + + assert(params != NULL); + assert(tls != NULL); + + mbedtls_ssl_init(&tls->ssl); + mbedtls_ctr_drbg_init(&tls->ctr_drbg); + mbedtls_ssl_config_init(&tls->conf); + mbedtls_entropy_init(&tls->entropy); + + ret = set_client_config(params, tls); + if (ret != 0) { + wpa_printf(MSG_ERROR, "Failed to set client configurations"); + goto exit; + } + + ret = mbedtls_ctr_drbg_seed( + &tls->ctr_drbg, mbedtls_entropy_func, &tls->entropy, NULL, 0); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); + goto exit; + } + + mbedtls_ssl_conf_rng( + &tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); + + ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret); + goto exit; + } +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + /* Disable BEAST attack countermeasures for Windows 2008 + * interoperability */ + mbedtls_ssl_conf_cbc_record_splitting( + &tls->conf, MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); +#endif + + return 0; + +exit: + tls_mbedtls_cleanup(tls); + return ret; +} + +void *tls_init(const struct tls_config *conf) +{ + tls_instance_count++; + return &tls_instance_count; +} + +void tls_deinit(void *tls_ctx) { tls_instance_count--; } + +struct tls_connection *tls_connection_init(void *tls_ctx) +{ + struct tls_connection *conn = os_zalloc(sizeof(*conn)); + if (!conn) { + wpa_printf( + MSG_ERROR, "TLS: Failed to allocate connection memory"); + return NULL; + } + + return conn; +} + +void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) +{ + /* case: tls init failed */ + if (!conn) { + return; + } + /* Free ssl ctx and data */ + tls_mbedtls_conn_delete((tls_context_t *)conn->tls); + os_free(conn->tls); + conn->tls = NULL; + /* Data in in ssl ctx, free connection */ + os_free(conn); +} + +int tls_get_errors(void *tls_ctx) { return 0; } + +int tls_connection_established(void *tls_ctx, struct tls_connection *conn) +{ + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER) { + return 1; + } + + return 0; +} + +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) +{ + wpa_printf(MSG_INFO, "TLS: global settings are not supported"); + return -1; +} + +int tls_connection_set_verify( + void *tls_ctx, struct tls_connection *conn, int verify_peer, + unsigned int flags, const u8 *session_ctx, size_t session_ctx_len) +{ + wpa_printf(MSG_INFO, "TLS: tls_connection_set_verify not supported"); + return -1; +} + +struct wpabuf *tls_connection_handshake( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + tls_context_t *tls = conn->tls; + int ret = 0; + + /* data freed by sender */ + conn->tls_io_data.out_data = NULL; + if (wpabuf_len(in_data)) { + conn->tls_io_data.in_data = wpabuf_dup(in_data); + } + + /* Multiple reads */ + while (tls->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { + ret = mbedtls_ssl_handshake_step(&tls->ssl); + + if (ret < 0) + break; + } + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ) { + wpa_printf(MSG_INFO, "%s: ret is %d", __func__, ret); + goto end; + } + + if (!conn->tls_io_data.out_data) { + wpa_printf( + MSG_INFO, + "application data is null, adding one byte for ack"); + u8 *dummy = os_zalloc(1); + conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0); + } + +end: + return conn->tls_io_data.out_data; +} + +struct wpabuf *tls_connection_server_handshake( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + wpa_printf(MSG_ERROR, "%s: not supported %d", __func__, __LINE__); + return NULL; +} + +struct wpabuf *tls_connection_encrypt( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) +{ + /* Reset dangling pointer */ + conn->tls_io_data.out_data = NULL; + + ssize_t ret = mbedtls_ssl_write( + &conn->tls->ssl, (unsigned char *)wpabuf_head(in_data), + wpabuf_len(in_data)); + + if (ret < wpabuf_len(in_data)) { + wpa_printf( + MSG_ERROR, "%s:%d, not able to write whole data", __func__, + __LINE__); + } + + return conn->tls_io_data.out_data; +} + +struct wpabuf *tls_connection_decrypt( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) +{ + unsigned char buf[1200]; + int ret = 0; + conn->tls_io_data.in_data = wpabuf_dup(in_data); + ret = mbedtls_ssl_read(&conn->tls->ssl, buf, 1200); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "%s:%d, not able to write whole data", __func__, + __LINE__); + return NULL; + } + + struct wpabuf *out = wpabuf_alloc_copy(buf, ret); + + return out; +} + +int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) +{ + if (conn && conn->tls) { + mbedtls_ssl_session *session = NULL; + + // If we have a session, then its resumed + mbedtls_ssl_get_session(&conn->tls->ssl, session); + + if (session) { + return 1; + } + } + + return 0; +} + +/* cipher array should contain cipher number in mbedtls num as per IANA + * Please see cipherlist is u8, therefore only initial ones are supported */ +int tls_connection_set_cipher_list( + void *tls_ctx, struct tls_connection *conn, u8 *ciphers) +{ + int i = 0; + + while (*ciphers != 0 && i < MAX_CIPHERSUITE) { + conn->tls->ciphersuite[i] = ciphers[i]; + i++; + } + return 0; +} + +int tls_get_version( + void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) +{ + const char *name; + + if (conn == NULL) { + return -1; + } + + name = mbedtls_ssl_get_version(&conn->tls->ssl); + if (name == NULL) { + return -1; + } + + os_strlcpy(buf, name, buflen); + + return 0; +} + +int tls_get_library_version(char *buf, size_t buf_len) +{ + + return os_snprintf(buf, buf_len, "MbedTLS build=test run=test"); +} + +// Lifted from https://stackoverflow.com/a/47117431 +char *strremove(char *str, const char *sub) +{ + char *p, *q, *r; + if (*sub && (q = r = os_strstr(str, sub)) != NULL) { + size_t len = os_strlen(sub); + while ((r = os_strstr(p = r + len, sub)) != NULL) { + os_memmove(q, p, r - p); + q += r - p; + } + os_memmove(q, p, strlen(p) + 1); + } + return str; +} + +// Lifted from: https://stackoverflow.com/a/779960 +// You must free the result if result is non-NULL. +char *str_replace(char *orig, char *rep, char *with) +{ + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = os_zalloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + +int tls_get_cipher( + void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) +{ + const char *name; + if (conn == NULL) { + return -1; + } + + name = mbedtls_ssl_get_ciphersuite(&conn->tls->ssl); + if (name == NULL) { + return -1; + } + + os_strlcpy(buf, name, buflen); + + // Translate to common format for hwsim tests to pass + strremove(buf, "TLS-"); + strremove(buf, "WITH-"); + char *tmp = str_replace(buf, "AES-", "AES"); + os_memcpy(buf, tmp, buflen); + os_free(tmp); + + return 0; +} + +int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) +{ + return -1; +} + +int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + +int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + +int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + +void tls_connection_set_success_data( + struct tls_connection *conn, struct wpabuf *data) +{} + +void tls_connection_set_success_data_resumed(struct tls_connection *conn) {} + +const struct wpabuf * +tls_connection_get_success_data(struct tls_connection *conn) +{ + return NULL; +} + +void tls_connection_remove_session(struct tls_connection *conn) {} + +char *tls_connection_peer_serial_num(void *tls_ctx, struct tls_connection *conn) +{ + return NULL; +} + +int tls_connection_set_params( + void *tls_ctx, struct tls_connection *conn, + const struct tls_connection_params *params) +{ + int ret = 0; + + wpa_printf( + MSG_ERROR, " client_cert 4is %s, %p", params->client_cert, params); + + tls_context_t *tls = (tls_context_t *)os_zalloc(sizeof(tls_context_t)); + + if (!tls) { + wpa_printf(MSG_ERROR, "failed to allocate tls context"); + return -1; + } + if (!params) { + wpa_printf(MSG_ERROR, "configuration is null"); + ret = -1; + goto err; + } + // assert(params->client_cert != NULL); + + ret = tls_create_mbedtls_handle(params, tls); + if (ret < 0) { + wpa_printf(MSG_ERROR, "failed to create ssl handle"); + goto err; + } + mbedtls_ssl_set_bio( + &tls->ssl, conn, tls_mbedtls_write, tls_mbedtls_read, NULL); + conn->tls = (tls_context_t *)tls; + + mbedtls_ssl_set_export_keys_cb( + &conn->tls->ssl, tls_connection_export_keys_cb, conn); + + return ret; +err: + os_free(tls); + return ret; +} + +int tls_global_set_params( + void *tls_ctx, const struct tls_connection_params *params) +{ + wpa_printf(MSG_INFO, "TLS: Global parameters not supported"); + return -1; +} + +int tls_connection_set_session_ticket_cb( + void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, + void *ctx) +{ + wpa_printf(MSG_ERROR, "TLS: %s not supported", __func__); + return -1; +} + +void tls_connection_export_keys_cb( + void *p_expkey, mbedtls_ssl_key_export_type secret_type, + const unsigned char *secret, size_t secret_len, + const unsigned char client_random[32], + const unsigned char server_random[32], mbedtls_tls_prf_types tls_prf_type) + +{ + struct tls_connection *conn = p_expkey; + + os_memcpy(conn->randbytes, client_random, TLS_RANDOM_LEN); + os_memcpy( + conn->randbytes + TLS_RANDOM_LEN, server_random, TLS_RANDOM_LEN); + os_memcpy(conn->master_secret, secret, secret_len); + conn->tls_prf_type = tls_prf_type; +} +static int tls_connection_prf( + void *tls_ctx, struct tls_connection *conn, const char *label, + int server_random_first, u8 *out, size_t out_len) +{ + int ret = 0; + u8 seed[2 * TLS_RANDOM_LEN]; + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + if (!ssl || !conn) { + wpa_printf( + MSG_ERROR, "TLS: %s, connection info is null", __func__); + return -1; + } + if (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { + wpa_printf( + MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, + ssl->MBEDTLS_PRIVATE(state)); + return -1; + } + + if (server_random_first) { + os_memcpy( + seed, conn->randbytes + TLS_RANDOM_LEN, TLS_RANDOM_LEN); + os_memcpy( + seed + TLS_RANDOM_LEN, conn->randbytes, TLS_RANDOM_LEN); + } else { + os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN); + } + + wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN); + wpa_hexdump_key( + MSG_MSGDUMP, "master", conn->master_secret, TLS_MASTER_SECRET_LEN); + + if (conn->tls_prf_type == MBEDTLS_SSL_TLS_PRF_SHA384) { + ret = tls_prf_sha384( + conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, + 2 * TLS_RANDOM_LEN, out, out_len); + } else if (conn->tls_prf_type == MBEDTLS_SSL_TLS_PRF_SHA256) { + ret = tls_prf_sha256( + conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, + 2 * TLS_RANDOM_LEN, out, out_len); + } else { + ret = tls_prf_sha1_md5( + conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, + 2 * TLS_RANDOM_LEN, out, out_len); + } + + if (ret < 0) { + wpa_printf(MSG_ERROR, "prf failed, ret=%d\n", ret); + } + wpa_hexdump_key(MSG_MSGDUMP, "key", out, out_len); + + return ret; +} + +int tls_connection_export_key( + void *tls_ctx, struct tls_connection *conn, const char *label, + const u8 *context, size_t context_len, u8 *out, size_t out_len) +{ + return tls_connection_prf(tls_ctx, conn, label, 0, out, out_len); +} + +int tls_connection_get_eap_fast_key( + void *tls_ctx, struct tls_connection *conn, u8 *out, size_t out_len) +{ + wpa_printf( + MSG_INFO, "TLS: tls_connection_get_eap_fast_key not supported, " + "please unset mbedtls crypto and try again"); + return -1; +} + +int tls_connection_client_hello_ext( + void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, + size_t data_len) +{ + wpa_printf( + MSG_INFO, "TLS: tls_connection_client_hello_ext not supported, " + "please unset mbedtls crypto and try again"); + return -1; +} + +int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) +{ + if (conn->tls_io_data.in_data) { + wpabuf_free(conn->tls_io_data.in_data); + } + conn->tls_io_data.in_data = NULL; + + /* outdata may have dangling pointer */ + conn->tls_io_data.out_data = NULL; + + return mbedtls_ssl_session_reset(&conn->tls->ssl); +} + +int tls_connection_get_random( + void *tls_ctx, struct tls_connection *conn, struct tls_random *data) +{ + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + os_memset(data, 0, sizeof(*data)); + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_CLIENT_HELLO) { + return -1; + } + + data->client_random = conn->randbytes; + data->client_random_len = TLS_RANDOM_LEN; + + if (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_SERVER_HELLO) { + data->server_random = conn->randbytes + TLS_RANDOM_LEN; + data->server_random_len = TLS_RANDOM_LEN; + } + + return 0; +} diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 4b86d8fc67..2a9c1a7bb3 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -6167,5 +6167,9 @@ extern const struct wpa_driver_ops wpa_driver_atheros_ops; #ifdef CONFIG_DRIVER_NONE extern const struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */ #endif /* CONFIG_DRIVER_NONE */ +#ifdef CONFIG_ZEPHYR +extern const struct wpa_driver_ops wpa_driver_zep_ops; /* driver_zephyr.c */ +#endif /* CONFIG_ZEPHYR */ + #endif /* DRIVER_H */ diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c new file mode 100644 index 0000000000..6b43a83176 --- /dev/null +++ b/src/drivers/driver_zephyr.c @@ -0,0 +1,733 @@ +/* + * Driver interaction with Zephyr WLAN device drivers. + * Copyright (c) 2022, Nordic Semiconductor + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "includes.h" +#include "utils/common.h" +#include "eloop.h" +#include "driver_zephyr.h" + +K_MBOX_DEFINE(wpa_supp_mbox); +#define SCAN_TIMEOUT 30 + +static void wpa_supp_drv_mbox_msg_handler(void *eloop_ctx, + void *timeout_ctx) +{ + struct k_mbox_msg msg; + struct zep_wpa_supp_mbox_msg_data mbox_msg_data; + + /* Prepare to receive message */ + msg.size = sizeof(mbox_msg_data); + msg.rx_source_thread = K_ANY; + + k_mbox_get(&wpa_supp_mbox, + &msg, + &mbox_msg_data, + K_FOREVER); + + mbox_msg_data.cb(mbox_msg_data.ctx, + mbox_msg_data.data, + 0); +} + + +void wpa_supp_event_handler(void *ctx, + void *data, + void *cb) +{ + struct k_mbox_msg send_msg; + struct zep_wpa_supp_mbox_msg_data mbox_msg_data; + + mbox_msg_data.ctx = ctx; + mbox_msg_data.data = data; + mbox_msg_data.cb = cb; + + /* Prepare to send message */ + send_msg.size = sizeof(mbox_msg_data); + send_msg.tx_data = &mbox_msg_data; + send_msg.tx_block.data = NULL; + send_msg.tx_target_thread = K_ANY; + + eloop_register_timeout(0, + 500, + wpa_supp_drv_mbox_msg_handler, + NULL, + NULL); + + k_mbox_put(&wpa_supp_mbox, + &send_msg, + K_FOREVER); +} + + +static int wpa_drv_zep_abort_scan(void *priv, + u64 scan_cookie) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->scan_abort) { + wpa_printf(MSG_ERROR, + "%s: No op registered for scan_abort\n", + __func__); + goto out; + } + + ret = dev_ops->scan_abort(if_ctx->dev_priv); +out: + return ret; +} + + +/** + * wpa_drv_zep_scan_timeout - Scan timeout to report scan completion + * @eloop_ctx: Driver private data + * @timeout_ctx: ctx argument given to wpa_drv_zep_init() + * + * This function can be used as registered timeout when starting a scan to + * generate a scan completed event if the driver does not report this. + */ +void wpa_drv_zep_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + + if_ctx = eloop_ctx; + + wpa_printf(MSG_ERROR, + "%s: Scan timeout - try to abort it\n", + __func__); + + if (wpa_drv_zep_abort_scan(if_ctx, 0) == 0) { + return; + } +} + + +void wpa_drv_zep_event_proc_scan_start(struct zep_drv_if_ctx *if_ctx) +{ + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_SCAN_STARTED, + NULL); +} + + +void wpa_drv_zep_event_proc_scan_done(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event) +{ + eloop_cancel_timeout(wpa_drv_zep_scan_timeout, + if_ctx, + if_ctx->supp_if_ctx); + + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_SCAN_RESULTS, + event); +} + + +void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, + struct wpa_scan_res *r, + bool more_res) +{ + struct wpa_scan_res **tmp = NULL; + + tmp = os_realloc_array(if_ctx->scan_res2->res, + if_ctx->scan_res2->num + 1, + sizeof(struct wpa_scan_res *)); + + if (!tmp) { + os_free(r); + return; + } + + tmp[if_ctx->scan_res2->num++] = r; + + if_ctx->scan_res2->res = tmp; + + if_ctx->scan_res2_get_in_prog = more_res; +} + + +void wpa_drv_zep_event_proc_auth_resp(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event) +{ + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_AUTH, + event); +} + + +void wpa_drv_zep_event_proc_assoc_resp(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event, + unsigned int status) +{ + if (status != WLAN_STATUS_SUCCESS) { + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_ASSOC_REJECT, + event); + } else { + if_ctx->associated = true; + + os_memcpy(if_ctx->bssid, + event->assoc_info.addr, + ETH_ALEN); + + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_ASSOC, + event); + } +} + + +void wpa_drv_zep_event_proc_deauth(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event) +{ + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_DEAUTH, + event); +} + + +void wpa_drv_zep_event_proc_disassoc(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event) +{ + wpa_supplicant_event(if_ctx->supp_if_ctx, + EVENT_DISASSOC, + event); +} + + +static void *wpa_drv_zep_global_init(void *ctx) +{ + struct zep_drv_ctx *drv_ctx = NULL; + + drv_ctx = os_zalloc(sizeof(*drv_ctx)); + + if (!drv_ctx) { + return NULL; + } + + drv_ctx->supp_ctx = ctx; + + return drv_ctx; +} + + +static void wpa_drv_zep_global_deinit(void *priv) +{ + struct zep_drv_ctx *drv_ctx = priv; + + if (!drv_ctx) { + return; + } + + os_free(drv_ctx); +} + + +/** + * wpa_driver_zep_init - Initialize Zephyr driver interface + * @ctx: Context to be used when calling wpa_supplicant functions, + * e.g., wpa_supplicant_event() + * @ifname: Interface name, e.g., wlan0 + * @global_priv: private driver global data from global_init() + * + * Returns: Pointer to private data, %NULL on failure + */ +static void *wpa_drv_zep_init(void *ctx, + const char *ifname, + void *global_priv) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + const struct device *device = NULL; + struct zep_wpa_supp_dev_callbk_fns callbk_fns; + + device = device_get_binding(ifname); + + if (!device) { + wpa_printf(MSG_ERROR, "%s: Interface %s not found\n", __func__, ifname); + goto out; + } + + if_ctx = os_zalloc(sizeof(*if_ctx)); + + if (if_ctx == NULL) { + goto out; + } + + if_ctx->supp_if_ctx = ctx; + + if_ctx->dev_ctx = device; + if_ctx->drv_ctx = global_priv; + + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->init) { + wpa_printf(MSG_ERROR, + "%s: No op registered for init\n", + __func__); + os_free(if_ctx); + if_ctx = NULL; + goto out; + } + + os_memset(&callbk_fns, + 0, + sizeof(callbk_fns)); + + callbk_fns.scan_start = wpa_drv_zep_event_proc_scan_start; + callbk_fns.scan_done = wpa_drv_zep_event_proc_scan_done; + callbk_fns.scan_res = wpa_drv_zep_event_proc_scan_res; + callbk_fns.auth_resp = wpa_drv_zep_event_proc_auth_resp; + callbk_fns.assoc_resp = wpa_drv_zep_event_proc_assoc_resp; + callbk_fns.deauth = wpa_drv_zep_event_proc_deauth; + callbk_fns.disassoc = wpa_drv_zep_event_proc_disassoc; + + if_ctx->dev_priv = dev_ops->init(if_ctx, + ifname, + &callbk_fns); + + if (!if_ctx->dev_priv) { + wpa_printf(MSG_ERROR, + "%s: Failed to initialize the interface\n", + __func__); + os_free(if_ctx); + if_ctx = NULL; + goto out; + } + +out: + return if_ctx; +} + + +static void wpa_drv_zep_deinit(void *priv) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->deinit) { + wpa_printf(MSG_ERROR, "%s: No op registered for deinit\n", __func__); + return; + } + + dev_ops->deinit(if_ctx->dev_priv); + + os_free(if_ctx); +} + + +static int wpa_drv_zep_scan2(void *priv, struct wpa_driver_scan_params *params) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int timeout = 0; + int ret = -1; + + if (!priv || !params) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + + if (if_ctx->scan_res2_get_in_prog) { + wpa_printf(MSG_ERROR, "%s: Scan is already in progress\n", __func__); + goto out; + } + + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->scan2) { + wpa_printf(MSG_ERROR, "%s: No op registered for scan2\n", __func__); + goto out; + } + + ret = dev_ops->scan2(if_ctx->dev_priv, params); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: scan2 op failed\n", __func__); + goto out; + } + + /* The driver delivers events to notify when scan is + * complete, so use longer timeout to avoid race conditions + * with scanning and following association request. + */ + timeout = SCAN_TIMEOUT; + + wpa_printf(MSG_DEBUG, + "%s: Scan requested - scan timeout %d seconds\n", + __func__, + timeout); + + eloop_cancel_timeout(wpa_drv_zep_scan_timeout, + if_ctx, + if_ctx->supp_if_ctx); + + eloop_register_timeout(timeout, + 0, + wpa_drv_zep_scan_timeout, + if_ctx, + if_ctx->supp_if_ctx); + + ret = 0; + +out: + return ret; +} + + +/** + * wpa_drv_zep_get_scan_results2 - Fetch the latest scan results + * @priv: Pointer to private data from wpa_drv_zep_init() + * Returns: Scan results on success, -1 on failure + */ +struct wpa_scan_results *wpa_drv_zep_get_scan_results2(void *priv) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + unsigned int i = 0; + int ret = -1; + + if (!priv) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->get_scan_results2) { + wpa_printf(MSG_ERROR, + "%s: No op registered for scan2\n", + __func__); + goto out; + } + + if_ctx->scan_res2 = os_zalloc(sizeof(*if_ctx->scan_res2)); + + if (!if_ctx->scan_res2) { + goto out; + } + + ret = dev_ops->get_scan_results2(if_ctx->dev_priv); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: get_scan_results2 op failed\n", __func__); + goto out; + } + + if_ctx->scan_res2_get_in_prog = true; + + /* Wait for the device to populate the scan results */ + while ((if_ctx->scan_res2_get_in_prog) && (i < SCAN_TIMEOUT)) { + k_yield(); + os_sleep(1, 0); + i++; + } + + if (i == SCAN_TIMEOUT) { + wpa_printf(MSG_ERROR, "%s: Timed out waiting for scan results\n", __func__); + ret = -1; + goto out; + } + + ret = 0; +out: + if (ret == -1) { + if (if_ctx->scan_res2) { + wpa_scan_results_free(if_ctx->scan_res2); + if_ctx->scan_res2 = NULL; + } + } + + return if_ctx->scan_res2; +} + + +static int wpa_drv_zep_deauthenticate(void *priv, const u8 *addr, + u16 reason_code) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if ((!priv) || (!addr)) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + ret = dev_ops->deauthenticate(if_ctx->dev_priv, addr, reason_code); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: deauthenticate op failed\n", __func__); + goto out; + } + + ret = 0; +out: + return ret; +} + + +static int wpa_drv_zep_authenticate(void *priv, + struct wpa_driver_auth_params *params) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if ((!priv) || (!params)) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + os_memcpy(if_ctx->ssid, + params->ssid, + params->ssid_len); + + if_ctx->ssid_len = params->ssid_len; + + ret = dev_ops->authenticate(if_ctx->dev_priv, + params); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: authenticate op failed\n", __func__); + goto out; + } + + ret = 0; +out: + return ret; +} + + +static int wpa_drv_zep_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if ((!priv) || (!params)) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + ret = dev_ops->associate(if_ctx->dev_priv, + params); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: associate op failed\n", __func__); + goto out; + } + + ret = 0; +out: + return ret; +} + + +static int _wpa_drv_zep_set_key(void *priv, + const char *ifname, + enum wpa_alg alg, + const u8 *addr, + int key_idx, + int set_tx, + const u8 *seq, + size_t seq_len, + const u8 *key, + size_t key_len) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if (!priv) { + wpa_printf(MSG_ERROR, "%s: Invalid handle\n", __func__); + goto out; + } + if ((alg != WPA_ALG_NONE) && + ((!seq) || (!key))) { + wpa_printf(MSG_ERROR, + "%s: Missing mandatory params\n", + __func__); + goto out; + } + + if_ctx = priv; + dev_ops = if_ctx->dev_ctx->config; + + wpa_printf(MSG_DEBUG, "%s: priv:%p alg %d addr %p key_idx %d set_tx %d seq %p " + "seq_len %d key %p key_len %d\n", + __func__, + if_ctx->dev_priv, + alg, addr, + key_idx, + set_tx, + seq, + seq_len, + key, + key_len); + + ret = dev_ops->set_key(if_ctx->dev_priv, + ifname, + alg, + addr, + key_idx, + set_tx, + seq, + seq_len, + key, + key_len); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: set_key op failed\n", __func__); + goto out; + } +out: + return ret; +} + + +static int wpa_drv_zep_set_key(void* priv, + struct wpa_driver_set_key_params *params) +{ + return _wpa_drv_zep_set_key(priv, + params->ifname, + params->alg, + params->addr, + params->key_idx, + params->set_tx, + params->seq, + params->seq_len, + params->key, + params->key_len); +} + + +static int wpa_drv_zep_get_capa(void *priv, + struct wpa_driver_capa *capa) +{ + /* Use SME */ + capa->flags = 0; + capa->flags |= WPA_DRIVER_FLAGS_SME; + capa->flags |= WPA_DRIVER_FLAGS_SAE; + + return 0; +} + + +static int wpa_drv_zep_get_bssid(void *priv, + u8 *bssid) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + + if_ctx = priv; + + os_memcpy(bssid, + if_ctx->bssid, + ETH_ALEN); + + return 0; +} + + +static int wpa_drv_zep_get_ssid(void *priv, + u8 *ssid) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + + if_ctx = priv; + + if (!if_ctx->ssid) { + return 0; + } + + wpa_printf(MSG_INFO, + "%s: SSID size: %d\n", + __func__, + if_ctx->ssid_len); + + os_memcpy(ssid, + if_ctx->ssid, + if_ctx->ssid_len); + + return if_ctx->ssid_len; +} + + +static int wpa_drv_zep_set_supp_port(void *priv, + int authorized) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + struct net_if *iface = NULL; + + int ret; + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + iface = net_if_lookup_by_dev(if_ctx->dev_ctx); + + ret = dev_ops->set_supp_port(if_ctx->dev_priv, + authorized, + if_ctx->bssid); + + if (authorized) { + net_dhcpv4_stop(iface); + k_msleep(500); + net_dhcpv4_start(iface); + } + + return ret; +} + + +const struct wpa_driver_ops wpa_driver_zep_ops = { + .name = "zephyr", + .desc = "Zephyr wpa_supplicant driver", + .global_init = wpa_drv_zep_global_init, + .global_deinit = wpa_drv_zep_global_deinit, + .init2 = wpa_drv_zep_init, + .deinit = wpa_drv_zep_deinit, + .scan2 = wpa_drv_zep_scan2, + .abort_scan = wpa_drv_zep_abort_scan, + .get_scan_results2 = wpa_drv_zep_get_scan_results2, + .authenticate = wpa_drv_zep_authenticate, + .associate = wpa_drv_zep_associate, + .get_capa = wpa_drv_zep_get_capa, + .get_bssid = wpa_drv_zep_get_bssid, + .get_ssid = wpa_drv_zep_get_ssid, + .set_supp_port = wpa_drv_zep_set_supp_port, + .deauthenticate = wpa_drv_zep_deauthenticate, + .set_key = wpa_drv_zep_set_key, +}; diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h new file mode 100644 index 0000000000..d61cda1eb6 --- /dev/null +++ b/src/drivers/driver_zephyr.h @@ -0,0 +1,105 @@ +/* + * Driver interaction with Zephyr WLAN device drivers. + * Copyright (c) 2022, Nordic Semiconductor + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DRIVER_ZEPHYR_H +#define DRIVER_ZEPHYR_H + +#include +#include +#include "driver.h" + +struct zep_wpa_supp_mbox_msg_data { + void *ctx; + void *data; + void (*cb)(void *ctx, + void *data, + int flags); +}; + + +struct zep_drv_ctx { + void *supp_ctx; +}; + + +struct zep_drv_if_ctx { + struct zep_drv_ctx *drv_ctx; + void *supp_if_ctx; + const struct device *dev_ctx; + void *dev_priv; + + struct wpa_scan_results *scan_res2; + bool scan_res2_get_in_prog; + + unsigned int assoc_freq; + unsigned char ssid[SSID_MAX_LEN]; + size_t ssid_len; + unsigned char bssid[6]; + bool associated; +}; + + +struct zep_wpa_supp_dev_callbk_fns { + void (*scan_start)(struct zep_drv_if_ctx *if_ctx); + + void (*scan_done)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event); + + void (*scan_res)(struct zep_drv_if_ctx *if_ctx, struct wpa_scan_res *r, + bool more_res); + + void (*auth_resp)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event); + + void (*assoc_resp)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event, unsigned int status); + + void (*deauth)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event); + + void (*disassoc)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event); +}; + + +struct zep_wpa_supp_dev_ops { + void *(*init)(void *supp_drv_if_ctx, + const char *iface_name, + struct zep_wpa_supp_dev_callbk_fns *callbk_fns); + void (*deinit)(void *if_priv); + int (*scan2)(void *if_priv, + struct wpa_driver_scan_params *params); + int (*scan_abort)(void *if_priv); + int (*get_scan_results2)(void *if_priv); + int (*deauthenticate)(void *if_priv, + const char *addr, + unsigned short reason_code); + int (*authenticate)(void *if_priv, + struct wpa_driver_auth_params *params); + int (*associate)(void *if_priv, + struct wpa_driver_associate_params *params); + int (*set_key)(void *if_priv, + const unsigned char *ifname, + enum wpa_alg alg, + const unsigned char *addr, + int key_idx, + int set_tx, + const unsigned char *seq, + size_t seq_len, + const unsigned char *key, + size_t key_len); + int (*set_supp_port)(void *if_priv, + int authorized, + char *bssid); +}; + + +void wpa_supp_event_handler(void *ctx, + void *data, + void *cb); +#endif /* DRIVER_ZEPHYR_H */ diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c index e95df6ddb2..fffc94a35e 100644 --- a/src/drivers/drivers.c +++ b/src/drivers/drivers.c @@ -48,6 +48,9 @@ const struct wpa_driver_ops *const wpa_drivers[] = #endif /* CONFIG_DRIVER_ATHEROS */ #ifdef CONFIG_DRIVER_NONE &wpa_driver_none_ops, +#endif /* CONFIG_DRIVER_NONE */ +#ifdef CONFIG_ZEPHYR + &wpa_driver_zep_ops, #endif /* CONFIG_DRIVER_NONE */ NULL }; diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c new file mode 100644 index 0000000000..364849a7e0 --- /dev/null +++ b/src/l2_packet/l2_packet_zephyr.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "includes.h" + +#include "common.h" +#include "eloop.h" +#include "l2_packet.h" + +#include + +#include +#include + +#include +#include +#include + +struct l2_packet_data { + char ifname[17]; + u8 own_addr[ETH_ALEN]; + int ifindex; + struct net_if *iface; + void (*rx_callback)(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len); + void *rx_callback_ctx; + int l2_hdr; /* whether to include layer 2 (Ethernet) header data + * buffers */ + int fd; + unsigned short protocol; +}; + +int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) +{ + os_memcpy(addr, l2->own_addr, ETH_ALEN); + return 0; +} + +int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len) +{ + int ret; + + if (l2 == NULL) { + return -1; + } + + if (l2->l2_hdr) { + ret = send(l2->fd, buf, len, 0); + if (ret < 0) { + wpa_printf(MSG_ERROR, "l2_packet_send - send: %s", + strerror(errno)); + } + } else { + struct sockaddr_ll ll; + + os_memset(&ll, 0, sizeof(ll)); + ll.sll_family = AF_PACKET; + ll.sll_ifindex = l2->ifindex; + ll.sll_protocol = htons(proto); + ll.sll_halen = ETH_ALEN; + os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN); + // TODO: This takes up too much stack, call wifi driver TX directly? + ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll, + sizeof(ll)); + if (ret < 0) { + wpa_printf(MSG_ERROR, "l2_packet_send - sendto: %s", + strerror(errno)); + } + } + return ret; +} + +static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) +{ + struct l2_packet_data *l2 = eloop_ctx; + u8 buf[2300]; + int res; + struct sockaddr_ll ll; + socklen_t fromlen; + struct l2_ethhdr *ethhdr; + + os_memset(&ll, 0, sizeof(ll)); + fromlen = sizeof(ll); + res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&ll, + &fromlen); + if (res < 0) { + wpa_printf(MSG_ERROR, "RAW : failed to recv error %d", errno); + return; + } + + // FIXME: We should only get registered protcols from networking stack + // but for some reason ETH_P_ALL is being set (bind_default) + ethhdr = (struct l2_ethhdr *) buf; + if (ethhdr->h_proto != htons(l2->protocol)) { + return; + } + + // FIXME: sll_addr is not being filled as L2 header is not removed + wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", + __func__, MAC2STR(ll.sll_addr), (int) res); + + // FIXME: CONFIG_NET_SOCKETS_PACKET_DGRAM should remove L2 header and fill ll + // but, it is not working. For now, remove the L2 header before passing the + // packet to the upper layers + if (!l2->l2_hdr) { + unsigned char l2_hdr_len = sizeof(struct l2_ethhdr); + if (res > l2_hdr_len) { + l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, &buf[l2_hdr_len], res-l2_hdr_len); + } else { + wpa_printf(MSG_WARNING, "RAW : received packet is too short: %d", res); + } + } else { + l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); + } +} + +struct l2_packet_data * +l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len), + void *rx_callback_ctx, int l2_hdr) +{ + struct l2_packet_data *l2; + struct sockaddr_ll ll; + int ret = 0; + struct net_linkaddr *link_addr = NULL; + struct net_if *iface = NULL; + const struct device *device = device_get_binding(ifname); + + if (!device) { + wpa_printf(MSG_ERROR, "Cannot get device for: %s\n", ifname); + return NULL; + } + + iface = net_if_lookup_by_dev(device); + + if (!iface) { + wpa_printf(MSG_ERROR, "Cannot get device for: %s\n", ifname); + return NULL; + } + + l2 = os_zalloc(sizeof(struct l2_packet_data)); + if (l2 == NULL) { + return NULL; + } + os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); + l2->rx_callback = rx_callback; + l2->rx_callback_ctx = rx_callback_ctx; + l2->l2_hdr = l2_hdr; + l2->protocol = protocol; + l2->iface = iface; + + l2->ifindex = net_if_get_by_iface(l2->iface); + + if (!l2->ifindex) { + os_free(l2); + wpa_printf(MSG_ERROR, "Cannot get interface index for: %s\n", + l2->ifname); + return NULL; + } + + link_addr = &iface->if_dev->link_addr; + os_memcpy(l2->own_addr, link_addr->addr, link_addr->len); + + l2->fd = socket(AF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, + htons(protocol)); + if (l2->fd < 0) { + wpa_printf(MSG_ERROR, + "Failed to open socket: %s, proto: %d, af: %d", + strerror(errno), htons(protocol), AF_PACKET); + goto fail; + } + + os_memset(&ll, 0, sizeof(ll)); + ll.sll_family = AF_PACKET; + + ll.sll_ifindex = l2->ifindex; + ll.sll_protocol = htons(protocol); + + // FIXME: This should skip bind_default to ETH_P_ALL, but its not. + if (l2->own_addr) + memcpy(ll.sll_addr, l2->own_addr, ETH_ALEN); + + ret = bind(l2->fd, (const struct sockaddr *) &ll, sizeof(ll)); + if (ret < 0) { + goto fail; + } + + if (rx_callback) { + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + } + + wpa_printf(MSG_INFO, "l2_packet_init: iface %s ifindex %d", l2->ifname, + l2->ifindex); + + return l2; +fail: + os_free(l2); + wpa_printf(MSG_ERROR, "Failed to create l2_packet: %d\n", ret); + return NULL; +} + +struct l2_packet_data * +l2_packet_init_bridge(const char *br_ifname, const char *ifname, + const u8 *own_addr, unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len), + void *rx_callback_ctx, int l2_hdr) +{ + return l2_packet_init(br_ifname, own_addr, protocol, rx_callback, + rx_callback_ctx, l2_hdr); +} + +void l2_packet_deinit(struct l2_packet_data *l2) +{ + if (l2 == NULL) { + return; + } + + if (l2->fd >= 0) { + eloop_unregister_read_sock(l2->fd); + /* TODO: close connection */ + } + + os_free(l2); +} + +int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) +{ + char addr_buf[NET_IPV4_ADDR_LEN]; + os_strlcpy(buf, net_addr_ntop(AF_INET, + &l2->iface->config.ip.ipv4->unicast[0].address.in_addr.s_addr, + addr_buf, sizeof(addr_buf)), len); + return 0; +} + +void l2_packet_notify_auth_start(struct l2_packet_data *l2) +{ + /* This function can be left empty */ +} + +int l2_packet_set_packet_filter(struct l2_packet_data *l2, + enum l2_packet_filter_type type) +{ + /* TODO: Set filter */ + return 0; +} diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 41daaae2cf..a1f02511f7 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -304,6 +304,19 @@ static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, return -1; } +static inline int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe, + size_t *rsnxe_len) +{ + return -1; + +} + +static inline int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *rsnxe, + size_t rsnxe_len) +{ + return -1; +} + static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) { return 0; diff --git a/src/utils/common.c b/src/utils/common.c index 2c12751938..7bed4600c4 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -1302,3 +1302,13 @@ void forced_memzero(void *ptr, size_t len) if (len) forced_memzero_val = ((u8 *) ptr)[0]; } + +#ifdef CONFIG_ZEPHYR +#include +extern char *inet_ntoa(struct in_addr in) +{ + char addr[NET_IPV4_ADDR_LEN]; + + return net_addr_ntop(AF_INET, (const void *)&in, addr, NET_IPV4_ADDR_LEN); +} +#endif diff --git a/src/utils/common.h b/src/utils/common.h index 45f72bb309..6693b2b6f5 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -129,7 +129,7 @@ typedef int8_t s8; /* Define platform specific byte swapping macros */ -#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) +#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) || defined (CONFIG_ZEPHYR) static inline unsigned short wpa_swap_16(unsigned short v) { @@ -553,7 +553,11 @@ void int_array_concat(int **res, const int *a); void int_array_sort_unique(int *a); void int_array_add_unique(int **res, int a); +#ifdef CONFIG_ZEPHYR +char *inet_ntoa(struct in_addr in); +#else #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif void str_clear_free(char *str); void bin_clear_free(void *bin, size_t len); diff --git a/src/utils/eloop.c b/src/utils/eloop.c index 00b0beff0b..a578c320eb 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -963,7 +963,7 @@ int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, } -#ifndef CONFIG_NATIVE_WINDOWS +#if !(defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ZEPHYR)) static void eloop_handle_alarm(int sig) { wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " @@ -980,7 +980,7 @@ static void eloop_handle_signal(int sig) { size_t i; -#ifndef CONFIG_NATIVE_WINDOWS +#if !(defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ZEPHYR)) if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { /* Use SIGALRM to break out from potential busy loops that * would not allow the program to be killed. */ @@ -1009,7 +1009,7 @@ static void eloop_process_pending_signals(void) eloop.signaled = 0; if (eloop.pending_terminate) { -#ifndef CONFIG_NATIVE_WINDOWS +#if !(defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ZEPHYR)) alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ eloop.pending_terminate = 0; diff --git a/src/utils/includes.h b/src/utils/includes.h index 741fc9c143..523bb088c7 100644 --- a/src/utils/includes.h +++ b/src/utils/includes.h @@ -29,11 +29,11 @@ #endif /* _WIN32_WCE */ #include -#ifndef _MSC_VER +#if !(defined(MSC_VER) || defined(CONFIG_ZEPHYR)) #include #endif /* _MSC_VER */ -#ifndef CONFIG_NATIVE_WINDOWS +#if !(defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ZEPHYR)) #include #include #include @@ -43,4 +43,17 @@ #endif /* __vxworks */ #endif /* CONFIG_NATIVE_WINDOWS */ +#if defined(CONFIG_ZEPHYR) +#if defined(CONFIG_POSIX_API) +#include +#include +#include +#include +#else /* defined(CONFIG_POSIX_API) */ +#include +#include +#endif /* defined(CONFIG_POSIX_API) */ +#include +#endif /* defined(CONFIG_ZEPHYR) */ + #endif /* INCLUDES_H */ diff --git a/src/utils/os.h b/src/utils/os.h index 21ba5c3ff8..dd611f0538 100644 --- a/src/utils/os.h +++ b/src/utils/os.h @@ -298,6 +298,42 @@ static inline void * os_calloc(size_t nmemb, size_t size) * these functions need to be implemented in os_*.c file for the target system. */ +#ifdef CONFIG_ZEPHYR +/** + * os_strdup - Duplicate a string + * @s: Source string + * Returns: Allocated buffer with the string copied into it or %NULL on failure + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +char *os_strdup(const char *s); + +/** + * os_strcasecmp - Compare two strings ignoring case + * @s1: First string + * @s2: Second string + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greatred than s2 + */ +int os_strcasecmp(const char *s1, const char *s2); + +/** + * os_strncasecmp - Compare two strings ignoring case + * @s1: First string + * @s2: Second string + * @n: Maximum numbers of characters to compare + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greater than s2. Only first n + * characters will be compared. + */ +int os_strncasecmp(const char *s1, const char *s2, size_t n); + +#ifndef os_memcmp_const +#define os_memcmp_const(s1, s2, n) memcmp((s1), (s2), (n)) +#endif +#endif + + #ifdef OS_NO_C_LIB_DEFINES /** @@ -493,7 +529,7 @@ char * os_strdup(const char *s); #ifndef os_strdup #ifdef _MSC_VER #define os_strdup(s) _strdup(s) -#else +#elif !defined(CONFIG_ZEPHYR) #define os_strdup(s) strdup(s) #endif #endif @@ -518,14 +554,14 @@ char * os_strdup(const char *s); #ifndef os_strcasecmp #ifdef _MSC_VER #define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) -#else +#elif !defined(CONFIG_ZEPHYR) #define os_strcasecmp(s1, s2) strcasecmp((s1), (s2)) #endif #endif #ifndef os_strncasecmp #ifdef _MSC_VER #define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) -#else +#elif !defined(CONFIG_ZEPHYR) #define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n)) #endif #endif @@ -597,6 +633,7 @@ static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size, */ size_t os_strlcpy(char *dest, const char *src, size_t siz); +#ifndef CONFIG_ZEPHYR /** * os_memcmp_const - Constant time memory comparison * @a: First buffer to compare @@ -614,7 +651,7 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz); */ int os_memcmp_const(const void *a, const void *b, size_t len); - +#endif /** * os_memdup - Allocate duplicate of passed memory chunk * @src: Source buffer to duplicate diff --git a/src/utils/os_zephyr.c b/src/utils/os_zephyr.c new file mode 100644 index 0000000000..747a66ced1 --- /dev/null +++ b/src/utils/os_zephyr.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "includes.h" +#include +#include +#include +#include "os.h" + +void os_sleep(os_time_t sec, os_time_t usec) +{ + if (sec) { + k_sleep(K_SECONDS(sec)); + } + if (usec) { + k_usleep(usec); + } +} + +int os_get_time(struct os_time *t) +{ + int res; + struct timeval tv; + + res = gettimeofday(&tv, NULL); + t->sec = tv.tv_sec; + t->usec = tv.tv_usec; + return res; +} + +int os_get_reltime(struct os_reltime *t) +{ +#if defined(CLOCK_BOOTTIME) + static clockid_t clock_id = CLOCK_BOOTTIME; +#elif defined(CLOCK_MONOTONIC) + static clockid_t clock_id = CLOCK_MONOTONIC; +#else + static clockid_t clock_id = CLOCK_REALTIME; +#endif + struct timespec ts; + int res; + + if (TEST_FAIL()) { + return -1; + } + + while (1) { + res = clock_gettime(clock_id, &ts); + if (res == 0) { + t->sec = ts.tv_sec; + t->usec = ts.tv_nsec / 1000; + return 0; + } + switch (clock_id) { +#ifdef CLOCK_BOOTTIME + case CLOCK_BOOTTIME: + clock_id = CLOCK_MONOTONIC; + break; +#endif +#ifdef CLOCK_MONOTONIC + case CLOCK_MONOTONIC: + clock_id = CLOCK_REALTIME; + break; +#endif + case CLOCK_REALTIME: + return -1; + } + } +} + +int os_mktime(int year, int month, int day, int hour, int min, int sec, + os_time_t *t) +{ + struct tm tm, *tm1; + time_t t_local, t1, t2; + os_time_t tz_offset; + + if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || + hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || + sec > 60) { + return -1; + } + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + + t_local = mktime(&tm); + + /* figure out offset to UTC */ + tm1 = localtime(&t_local); + if (tm1) { + t1 = mktime(tm1); + tm1 = gmtime(&t_local); + if (tm1) { + t2 = mktime(tm1); + tz_offset = t2 - t1; + } else { + tz_offset = 0; + } + } else { + tz_offset = 0; + } + + *t = (os_time_t)t_local - tz_offset; + return 0; +} + +int os_gmtime(os_time_t t, struct os_tm *tm) +{ + struct tm *tm2; + time_t t2 = t; + + tm2 = gmtime(&t2); + if (tm2 == NULL) { + return -1; + } + tm->sec = tm2->tm_sec; + tm->min = tm2->tm_min; + tm->hour = tm2->tm_hour; + tm->day = tm2->tm_mday; + tm->month = tm2->tm_mon + 1; + tm->year = tm2->tm_year + 1900; + return 0; +} + +int os_daemonize(const char *pid_file) +{ + return -1; +} + +void os_daemonize_terminate(const char *pid_file) +{ +} + +int os_get_random(unsigned char *buf, size_t len) +{ + sys_rand_get(buf, len); + + return 0; +} + +unsigned long os_random(void) +{ + return sys_rand32_get(); +} + +char *os_rel2abs_path(const char *rel_path) +{ + return NULL; /* strdup(rel_path) can be used here */ +} + +int os_program_init(void) +{ + return 0; +} + +void os_program_deinit(void) +{ +} + +int os_setenv(const char *name, const char *value, int overwrite) +{ + return -1; +} + +int os_unsetenv(const char *name) +{ + return -1; +} + +char *os_readfile(const char *name, size_t *len) +{ + return NULL; +} + +int os_fdatasync(FILE *stream) +{ + return 0; +} + +char *os_strdup(const char *s) +{ + size_t len; + char *d; + + len = os_strlen(s); + d = os_malloc(len + 1); + if (d == NULL) { + return NULL; + } + os_memcpy(d, s, len); + d[len] = '\0'; + return d; +} + +void *os_memdup(const void *src, size_t len) +{ + void *r = os_malloc(len); + + if (r && src) { + os_memcpy(r, src, len); + } + return r; +} + +void *os_zalloc(size_t size) +{ + return calloc(1, size); +} + +size_t os_strlcpy(char *dest, const char *src, size_t siz) +{ + const char *s = src; + size_t left = siz; + + if (left) { + /* Copy string up to the maximum size of the dest buffer */ + while (--left != 0) { + if ((*dest++ = *s++) == '\0') { + break; + } + } + } + + if (left == 0) { + /* Not enough room for the string; force NUL-termination */ + if (siz != 0) { + *dest = '\0'; + } + while (*s++) { + ; /* determine total src string length */ + } + } + + return s - src - 1; +} + +int os_exec(const char *program, const char *arg, int wait_completion) +{ + return -1; +} + +/* Duplicate S, returning an identical malloc'd string. */ +char *__strdup(const char *s) +{ + size_t len = strlen(s) + 1; + void *new = malloc(len); + + if (new == NULL) { + return NULL; + } + return (char *)memcpy(new, s, len); +} + +int os_strcasecmp(const char *s1, const char *s2) +{ + /* + * Ignoring case is not required for main functionality, so just use + * the case sensitive version of the function. + */ + return os_strcmp(s1, s2); +} + +int os_strncasecmp(const char *s1, const char *s2, size_t n) +{ + /* + * Ignoring case is not required for main functionality, so just use + * the case sensitive version of the function. + */ + return os_strncmp(s1, s2, n); +} diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index f7ca929fed..2688eb2ba0 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11482,6 +11482,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, return NULL; } + memset(reply, '\0', reply_size); os_memcpy(reply, "OK\n", 3); reply_len = 3; diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c index 1cbf7fa28d..db2c155da9 100644 --- a/wpa_supplicant/ctrl_iface_udp.c +++ b/wpa_supplicant/ctrl_iface_udp.c @@ -18,7 +18,6 @@ #define COOKIE_LEN 8 - /* Per-interface ctrl_iface */ /** diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 603ac33d1b..3f1ec2117f 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2205,7 +2205,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpa_s->wpa_state < WPA_COMPLETED) goto scan_work_done; +#ifndef CONFIG_ZEPHYR + /* TODO : causing a crash */ wpa_scan_results_free(scan_res); +#endif if (own_request && wpa_s->scan_work) { struct wpa_radio_work *work = wpa_s->scan_work; diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index 51a8a0298a..ad73300125 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -199,6 +199,7 @@ int main(int argc, char *argv[]) wpa_supplicant_fd_workaround(1); +#ifndef CONFIG_ZEPHYR //TODO: use shell_getopt in zephyr for (;;) { c = getopt(argc, argv, "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); @@ -337,6 +338,7 @@ int main(int argc, char *argv[]) goto out; } } +#endif exitcode = 0; global = wpa_supplicant_init(¶ms); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index b0094ca6ca..d3bffa0980 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2051,7 +2051,9 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, * better. */ static int wpa_scan_result_compar(const void *a, const void *b) { +#ifndef CONFIG_ZEPHYR #define MIN(a,b) a < b ? a : b +#endif struct wpa_scan_res **_wa = (void *) a; struct wpa_scan_res **_wb = (void *) b; struct wpa_scan_res *wa = *_wa; diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c index d0fdd55d30..16ef6fe1f7 100644 --- a/wpa_supplicant/wmm_ac.c +++ b/wpa_supplicant/wmm_ac.c @@ -159,12 +159,14 @@ static void wmm_ac_del_req(struct wpa_supplicant *wpa_s, int failed) static void wmm_ac_addts_req_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; +#ifndef CONFIG_ZEPHYR struct wmm_ac_addts_request *addts_req = timeout_ctx; wpa_printf(MSG_DEBUG, "Timeout getting ADDTS response (tsid=%d up=%d)", wmm_ac_get_tsid(&addts_req->tspec), wmm_ac_get_user_priority(&addts_req->tspec)); +#endif /* CONFIG_ZEPHYR */ wmm_ac_del_req(wpa_s, 1); } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 033589f760..e35f0ae607 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -10,6 +10,7 @@ #ifdef CONFIG_CTRL_IFACE +#include #ifdef CONFIG_CTRL_IFACE_UNIX #include #endif /* CONFIG_CTRL_IFACE_UNIX */ @@ -20,12 +21,17 @@ #include "utils/eloop.h" #include "utils/edit.h" #include "utils/list.h" +#include "wpa_supplicant_i.h" +#include "ctrl_iface.h" #include "common/version.h" #include "common/ieee802_11_defs.h" #ifdef ANDROID #include #endif /* ANDROID */ +#define CMD_BUF_LEN 4096 + +extern struct wpa_supplicant *wpa_s_0; static const char *const wpa_cli_version = "wpa_cli v" VERSION_STR "\n" @@ -38,11 +44,15 @@ static const char *const wpa_cli_version = "11: Assoc Req (P2P), 12: Assoc Resp (P2P)" static struct wpa_ctrl *ctrl_conn; +#ifdef notyet static struct wpa_ctrl *mon_conn; static int wpa_cli_quit = 0; +#endif /* notyet */ +#ifdef INTERACTIVE static int wpa_cli_attached = 0; static int wpa_cli_connected = -1; static int wpa_cli_last_id = 0; +#endif /* INTERACTIVE */ #ifndef CONFIG_CTRL_IFACE_DIR #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant" #endif /* CONFIG_CTRL_IFACE_DIR */ @@ -69,14 +79,16 @@ static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */ static void print_help(const char *cmd); +#ifdef notyet static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx); static void wpa_cli_close_connection(void); static char * wpa_cli_get_default_ifname(void); static char ** wpa_list_cmd_list(void); -static void update_creds(struct wpa_ctrl *ctrl); -static void update_networks(struct wpa_ctrl *ctrl); static void update_stations(struct wpa_ctrl *ctrl); static void update_ifnames(struct wpa_ctrl *ctrl); +#endif /* notyet */ +static void update_creds(struct wpa_ctrl *ctrl); +static void update_networks(struct wpa_ctrl *ctrl); static void usage(void) @@ -100,7 +112,7 @@ static void usage(void) print_help(NULL); } - +#ifdef INTERACTIVE static int wpa_cli_show_event(const char *event) { const char *start; @@ -121,7 +133,6 @@ static int wpa_cli_show_event(const char *event) return 1; } - static int wpa_cli_open_connection(const char *ifname, int attach) { #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) @@ -199,7 +210,6 @@ static int wpa_cli_open_connection(const char *ifname, int attach) return 0; } - static void wpa_cli_close_connection(void) { if (ctrl_conn == NULL) @@ -217,39 +227,48 @@ static void wpa_cli_close_connection(void) mon_conn = NULL; } } - +#endif /* INTERACTIVE */ static void wpa_cli_msg_cb(char *msg, size_t len) { printf("%s\n", msg); } - +#ifdef INTERACTIVE static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print) { - char buf[4096]; + char * buf = NULL; + unsigned int buf_size = CMD_BUF_LEN; size_t len; int ret; + buf = os_zalloc(sizeof(u8) * buf_size); + if (!buf){ + printf ("Failed to allocate mem for command buf\n"); + return -1; + } if (ctrl_conn == NULL) { printf("Not connected to wpa_supplicant - command dropped.\n"); - return -1; + ret = -1; + goto err; } if (ifname_prefix) { - os_snprintf(buf, sizeof(buf), "IFNAME=%s %s", + os_snprintf(buf, buf_size, "IFNAME=%s %s", ifname_prefix, cmd); - buf[sizeof(buf) - 1] = '\0'; + buf[buf_size - 1] = '\0'; cmd = buf; } - len = sizeof(buf) - 1; + len = buf_size - 1; ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, wpa_cli_msg_cb); if (ret == -2) { printf("'%s' command timed out.\n", cmd); - return -2; + ret = -2; + goto err; } else if (ret < 0) { printf("'%s' command failed.\n", cmd); - return -1; + ret = -1; + goto err; } if (print) { buf[len] = '\0'; @@ -258,28 +277,59 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print) printf("\n"); } return 0; +err: + os_free(buf); + return ret; } - +#endif /* INTERACTIVE */ static int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) { - return _wpa_ctrl_command(ctrl, cmd, 1); + + char * repl_buf; + int len = 0; /* len of the reply */ + + repl_buf = wpa_supplicant_ctrl_iface_process (wpa_s_0, (char *) cmd, &len); + + if (len > 0 && os_strcmp(repl_buf, "OK") != 0) + printf ("Reply: %s\n", repl_buf); + + if (len > 0 && repl_buf) + os_free(repl_buf); + + return 0; } static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, int argc, char *argv[]) { - char buf[4096]; + char * buf = NULL; + int ret = 0; if (argc < min_args) { printf("Invalid %s command - at least %d argument%s " "required.\n", cmd, min_args, min_args > 1 ? "s are" : " is"); return -1; } - if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0) + buf = os_zalloc(sizeof(char) * CMD_BUF_LEN); + if (!buf){ + printf ("Failed to allocate mem for command buf\n"); return -1; - return wpa_ctrl_command(ctrl, buf); + } + memset(buf, '\0', CMD_BUF_LEN); + if (write_cmd(buf, CMD_BUF_LEN, cmd, argc-1, argv) < 0){ + ret = -1; + goto out; + } + ret = wpa_ctrl_command(ctrl, buf); + + out: + + if (buf) + os_free(buf); + + return ret; } @@ -374,7 +424,7 @@ static int wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, #endif /* CONFIG_MESH */ #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ - +#ifdef notyet static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) { print_help(argc > 0 ? argv[0] : NULL); @@ -411,7 +461,7 @@ static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) eloop_terminate(); return 0; } - +#endif /* notyet */ static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1008,12 +1058,12 @@ static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv); } - +#ifdef notyet static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv); } - +#endif /* notyet */ static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1399,7 +1449,7 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, return 0; } - if (argc != 2) { + if (argc < 2) { printf("Invalid GET_NETWORK command: needs two arguments\n" "(network id and variable name)\n"); return -1; @@ -1799,14 +1849,13 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) return res; } - +#ifdef notyet static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) { printf("Available interfaces:\n"); return wpa_ctrl_command(ctrl, "INTERFACES"); } - static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) { if (argc < 1) { @@ -1830,6 +1879,7 @@ static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) } return 0; } +#endif /* notyet */ static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, @@ -3285,6 +3335,7 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "mib", wpa_cli_cmd_mib, NULL, cli_cmd_flag_none, "= get MIB variables (dot1x, dot11)" }, +#ifdef notyet { "help", wpa_cli_cmd_help, wpa_cli_complete_help, cli_cmd_flag_none, "[command] = show usage help" }, @@ -3300,6 +3351,7 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "quit", wpa_cli_cmd_quit, NULL, cli_cmd_flag_none, "= exit wpa_cli" }, +#endif /* notyet */ { "set", wpa_cli_cmd_set, wpa_cli_complete_set, cli_cmd_flag_none, "= set variables (shows list of variables when run without " @@ -4004,7 +4056,7 @@ static void print_help(const char *cmd) } } - +#ifdef notyet static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd) { const char *c, *delim; @@ -4025,7 +4077,6 @@ static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd) return 0; } - static char ** wpa_list_cmd_list(void) { char **res; @@ -4063,8 +4114,9 @@ static char ** wpa_list_cmd_list(void) return res; } +#endif /* notyet */ - +#ifdef INTERACTIVE static char ** wpa_cli_cmd_completion(const char *cmd, const char *str, int pos) { @@ -4113,7 +4165,7 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos) os_free(cmd); return res; } - +#endif /* INTERACTIVE */ static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -4163,13 +4215,14 @@ static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) printf("Unknown command '%s'\n", argv[0]); ret = 1; } else { - ret = match->handler(ctrl, argc - 1, &argv[1]); + + ret = match->handler(ctrl, argc, &argv[1]); } return ret; } - +#ifdef INTERACTIVE static int wpa_cli_exec(const char *program, const char *arg1, const char *arg2) { @@ -4192,7 +4245,6 @@ static int wpa_cli_exec(const char *program, const char *arg1, return res; } - static void wpa_cli_action_process(const char *msg) { const char *pos; @@ -4378,11 +4430,9 @@ static int wpa_cli_open_global_ctrl(void) } update_stations(ctrl_conn); } - return 0; } - static void wpa_cli_reconnect(void) { wpa_cli_close_connection(); @@ -4557,6 +4607,7 @@ static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx) } + static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx) { wpa_cli_recv_pending(mon_conn, 0); @@ -4616,6 +4667,7 @@ static void start_edit(void) } + static void update_bssid_list(struct wpa_ctrl *ctrl) { char buf[4096]; @@ -4677,7 +4729,7 @@ static void update_ifnames(struct wpa_ctrl *ctrl) pos = end + 1; } } - +#endif /* INTERACTIVE */ static void update_creds(struct wpa_ctrl *ctrl) { @@ -4742,7 +4794,7 @@ static void update_networks(struct wpa_ctrl *ctrl) } } - +#ifdef INTERACTIVE static void update_stations(struct wpa_ctrl *ctrl) { #ifdef CONFIG_AP @@ -4764,6 +4816,8 @@ static void update_stations(struct wpa_ctrl *ctrl) } + + static void try_connection(void *eloop_ctx, void *timeout_ctx) { if (ctrl_conn) @@ -4948,9 +5002,9 @@ static char * wpa_cli_get_default_ifname(void) return ifname; } +#endif /* INTERACTIVE */ - -int main(int argc, char *argv[]) +int cli_main(int argc, char *argv[]) { int c; int daemonize = 0; @@ -5004,6 +5058,7 @@ int main(int argc, char *argv[]) } } +#ifdef INTERACTIVE interactive = (argc == optind) && (action_file == NULL); if (interactive) @@ -5015,8 +5070,6 @@ int main(int argc, char *argv[]) if (global && wpa_cli_open_global_ctrl() < 0) return -1; - eloop_register_signal_terminate(wpa_cli_terminate, NULL); - if (ctrl_ifname == NULL) ctrl_ifname = wpa_cli_get_default_ifname(); @@ -5035,9 +5088,12 @@ int main(int argc, char *argv[]) wpa_cli_attached = 1; } } - } else if (interactive) { + } + + else if (interactive) { wpa_cli_interactive(); - } else { + } + else { if (!global && wpa_cli_open_connection(ctrl_ifname, 0) < 0) { fprintf(stderr, "Failed to connect to non-global " @@ -5063,19 +5119,24 @@ int main(int argc, char *argv[]) if (action_file) wpa_cli_action(ctrl_conn); else - ret = wpa_request(ctrl_conn, argc - optind, - &argv[optind]); +#endif /* INTERACTIVE */ + ret = wpa_request(ctrl_conn, argc, + argv); +#ifdef INTERACTIVE } +#endif /* INTERACTIVE */ os_free(ctrl_ifname); - eloop_destroy(); +#ifdef INTERACTIVE +// eloop_destroy(); wpa_cli_cleanup(); +#endif /* INTERACTIVE */ return ret; } #else /* CONFIG_CTRL_IFACE */ -int main(int argc, char *argv[]) +int cli_main(int argc, char *argv[]) { printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); return -1; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index d89ee17e41..e12320bf20 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -905,6 +905,27 @@ void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s) } } +// TODO: This WAR is needed as we always lose the first frame after association (DHCP), +// and IP assignment gets delayed (esp. with exponential backoff in Zephyr DHCP client), so +// we send out a dummy frame that will be lost, and then DHCP will go through smoothly. +// +// Remove this once the first frame issue is fixed. +static void dhcp_war(struct wpa_supplicant *wpa_s) +{ + int len = 30, res = -1; + char *buf; + + buf = os_malloc(len); + if (buf == NULL) + return; + + memset(buf, 0xAA, len); + + res = l2_packet_send(wpa_s->l2, wpa_s->bssid, ntohs(0x8989), buf, len); + wpa_printf(MSG_INFO, "DHCP WAR: TX frame res=%d", res); + os_free(buf); +} + /** * wpa_supplicant_set_state - Set current connection state @@ -1012,6 +1033,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_s->after_wps = 0; wpa_s->known_wps_freq = 0; wpas_p2p_completed(wpa_s); + dhcp_war(wpa_s); sme_sched_obss_scan(wpa_s, 1); @@ -6806,6 +6828,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); +#ifndef CONFIG_ZEPHYR wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); if (wpa_s->ctrl_iface == NULL) { wpa_printf(MSG_ERROR, @@ -6819,6 +6842,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->conf->ctrl_interface); return -1; } +#endif wpa_s->gas = gas_query_init(wpa_s); if (wpa_s->gas == NULL) { @@ -6968,9 +6992,10 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, if (terminate) wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); - +#ifndef CONFIG_ZEPHYR wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface); wpa_s->ctrl_iface = NULL; +#endif #ifdef CONFIG_MESH if (wpa_s->ifmsh) { @@ -8187,6 +8212,7 @@ void wpas_request_disconnection(struct wpa_supplicant *wpa_s) } +#ifndef CONFIG_ZEPHYR void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title, struct wpa_used_freq_data *freqs_data, unsigned int len) @@ -8201,6 +8227,7 @@ void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title, i, cur->freq, cur->flags); } } +#endif /* CONFIG_ZEPHYR */ /* @@ -8253,7 +8280,9 @@ int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s, } } +#ifndef CONFIG_ZEPHYR dump_freq_data(wpa_s, "completed iteration", freqs_data, idx); +#endif /* CONFIG_ZEPHYR */ return idx; } diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 0000000000..7df96d7653 --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1,325 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if(CONFIG_WPA_SUPP) + +zephyr_library() + +set(HOSTAP_BASE ${CMAKE_CURRENT_SOURCE_DIR}/../) +set(WPA_SUPPLICANT_BASE ${HOSTAP_BASE}/wpa_supplicant) +set(COMMON_SRC_BASE ${HOSTAP_BASE}/src) + +set(CMAKE_EXE_LINKER_FLAGS "--specs=nosys.specs -lnosys") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMISSING_SYSCALL_NAMES") + +zephyr_compile_definitions( + CONFIG_ZEPHYR +) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/ + ${WPA_SUPPLICANT_BASE}/ + ${COMMON_SRC_BASE}/ +) + +zephyr_library_compile_definitions( + TLS_DEFAULT_CIPHERS=\""DEFAULT:!EXP:!LOW"\" + CONFIG_SHA256 + CONFIG_SME + CONFIG_NO_CONFIG_WRITE + CONFIG_NO_CONFIG_BLOBS + CONFIG_WPA_S_ZEPHYR_L2_WIFI_MGMT + #CONFIG_NO_STDOUT_DEBUG + CONFIG_CTRL_IFACE + CONFIG_CTRL_IFACE_UDP + CONFIG_NO_RANDOM_POOL + ) + +zephyr_library_include_directories( + ${HOSTAP_BASE}/ + ${COMMON_SRC_BASE}/utils + ${COMMON_SRC_BASE}/drivers + ${HOSTAP_BASE}/src + ${ZEPHYR_BASE}/include + ${ZEPHYR_BASE}/include/net +) + +zephyr_library_sources( + ${COMMON_SRC_BASE}/common/wpa_common.c + ${COMMON_SRC_BASE}/common/ieee802_11_common.c + ${COMMON_SRC_BASE}/common/hw_features_common.c + ${COMMON_SRC_BASE}/common/wpa_ctrl.c + ${COMMON_SRC_BASE}/common/cli.c + + ${COMMON_SRC_BASE}/drivers/driver_common.c + ${COMMON_SRC_BASE}/drivers/drivers.c + ${COMMON_SRC_BASE}/l2_packet/l2_packet_zephyr.c + ${COMMON_SRC_BASE}/drivers/driver_zephyr.c + ${COMMON_SRC_BASE}/utils/base64.c + ${COMMON_SRC_BASE}/utils/common.c + ${COMMON_SRC_BASE}/utils/wpa_debug.c + ${COMMON_SRC_BASE}/utils/wpabuf.c + ${COMMON_SRC_BASE}/utils/bitfield.c + ${COMMON_SRC_BASE}/utils/eloop.c + ${COMMON_SRC_BASE}/utils/os_zephyr.c + ${COMMON_SRC_BASE}/utils/radiotap.c + #${COMMON_SRC_BASE}/utils/edit_simple.c + ${WPA_SUPPLICANT_BASE}/config.c + ${WPA_SUPPLICANT_BASE}/notify.c + ${WPA_SUPPLICANT_BASE}/bss.c + ${WPA_SUPPLICANT_BASE}/eap_register.c + ${WPA_SUPPLICANT_BASE}/op_classes.c + ${WPA_SUPPLICANT_BASE}/rrm.c + ${WPA_SUPPLICANT_BASE}/wmm_ac.c + ${WPA_SUPPLICANT_BASE}/config_none.c + ${WPA_SUPPLICANT_BASE}/sme.c + ${WPA_SUPPLICANT_BASE}/wpa_supplicant.c + ${WPA_SUPPLICANT_BASE}/events.c + ${WPA_SUPPLICANT_BASE}/bssid_ignore.c + ${WPA_SUPPLICANT_BASE}/wpas_glue.c + ${WPA_SUPPLICANT_BASE}/scan.c + ${WPA_SUPPLICANT_BASE}/robust_av.c + ${WPA_SUPPLICANT_BASE}/ctrl_iface.c + ${WPA_SUPPLICANT_BASE}/ctrl_iface_udp.c + ${WPA_SUPPLICANT_BASE}/wpa_cli.c + # Zephyr main + src/supp_main.c +) +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_AP + ${WPA_SUPPLICANT_BASE}/ap.c + ${COMMON_SRC_BASE}/ap/ap_config.c + ${COMMON_SRC_BASE}/ap/ap_drv_ops.c + ${COMMON_SRC_BASE}/ap/ap_list.c + ${COMMON_SRC_BASE}/ap/ap_mlme.c + ${COMMON_SRC_BASE}/ap/authsrv.c + ${COMMON_SRC_BASE}/ap/beacon.c + ${COMMON_SRC_BASE}/ap/bss_load.c + ${COMMON_SRC_BASE}/ap/dfs.c + ${COMMON_SRC_BASE}/ap/drv_callbacks.c + ${COMMON_SRC_BASE}/ap/eap_user_db.c + ${COMMON_SRC_BASE}/ap/hostapd.c + ${COMMON_SRC_BASE}/ap/hw_features.c + ${COMMON_SRC_BASE}/ap/ieee802_11_auth.c + ${COMMON_SRC_BASE}/ap/ieee802_11.c + ${COMMON_SRC_BASE}/ap/ieee802_11_he.c + ${COMMON_SRC_BASE}/ap/ieee802_11_ht.c + ${COMMON_SRC_BASE}/ap/ieee802_11_shared.c + ${COMMON_SRC_BASE}/ap/ieee802_11_vht.c + ${COMMON_SRC_BASE}/ap/ieee802_1x.c + ${COMMON_SRC_BASE}/ap/neighbor_db.c + ${COMMON_SRC_BASE}/ap/p2p_hostapd.c + ${COMMON_SRC_BASE}/ap/pmksa_cache_auth.c + ${COMMON_SRC_BASE}/ap/preauth_auth.c + ${COMMON_SRC_BASE}/ap/rrm.c + ${COMMON_SRC_BASE}/ap/sta_info.c + ${COMMON_SRC_BASE}/ap/tkip_countermeasures.c + ${COMMON_SRC_BASE}/ap/utils.c + ${COMMON_SRC_BASE}/ap/wmm.c + + ${COMMON_SRC_BASE}/ap/wpa_auth.c + ${COMMON_SRC_BASE}/ap/wpa_auth_ie.c + ${COMMON_SRC_BASE}/ap/wpa_auth_ft.c + ${COMMON_SRC_BASE}/ap/wpa_auth_glue.c + + ${COMMON_SRC_BASE}/eap_common/eap_common.c + ${COMMON_SRC_BASE}/eap_server/eap_server.c + ${COMMON_SRC_BASE}/eap_server/eap_server_identity.c + ${COMMON_SRC_BASE}/eap_server/eap_server_methods.c + ${COMMON_SRC_BASE}/eapol_auth/eapol_auth_sm.c +) + +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_AP + CONFIG_AP + CONFIG_NO_RADIUS + CONFIG_NO_VLAN + CONFIG_NO_ACCOUNTING + CONFIG_NEED_AP_MLME + CONFIG_IEEE80211AX + CONFIG_EAP_SERVER + CONFIG_EAP_SERVER_IDENTITY +) + + +zephyr_library_sources_ifndef(CONFIG_WPA_SUPP_CRYPTO + ${COMMON_SRC_BASE}/crypto/crypto_none.c +) + +zephyr_library_compile_definitions_ifndef(CONFIG_WPA_SUPP_CRYPTO + CONFIG_NO_WPA + CONFIG_CRYPTO_INTERNAL +) + +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_CRYPTO + CONFIG_WEP +) + +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO + ${COMMON_SRC_BASE}/common/wpa_common.c + ${COMMON_SRC_BASE}/rsn_supp/wpa.c + ${COMMON_SRC_BASE}/rsn_supp/preauth.c + ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c + ${COMMON_SRC_BASE}/rsn_supp/wpa_ie.c + + ${COMMON_SRC_BASE}/crypto/crypto_mbedtls-bignum.c + ${COMMON_SRC_BASE}/crypto/crypto_mbedtls-ec.c + ${COMMON_SRC_BASE}/crypto/crypto_mbedtls.c + ${COMMON_SRC_BASE}/crypto/tls_mbedtls.c + ${COMMON_SRC_BASE}/crypto/aes-wrap.c + ${COMMON_SRC_BASE}/crypto/aes-unwrap.c + ${COMMON_SRC_BASE}/crypto/rc4.c + #${COMMON_SRC_BASE}/crypto/random.c + ${COMMON_SRC_BASE}/crypto/sha1-prf.c + ${COMMON_SRC_BASE}/crypto/sha256-prf.c + ${COMMON_SRC_BASE}/crypto/sha256-prf.c + ${COMMON_SRC_BASE}/crypto/sha384-prf.c +) + + +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_WPA3 + ${COMMON_SRC_BASE}/common/sae.c + ${COMMON_SRC_BASE}/common/dragonfly.c + + ${COMMON_SRC_BASE}/crypto/dh_groups.c + ${COMMON_SRC_BASE}/crypto/sha256-kdf.c +) + +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_WPA3 + CONFIG_SAE + CONFIG_ECC +) + +zephyr_library_include_directories_ifdef(CONFIG_WPA_SUPP_CRYPTO + ${CMAKE_SOURCE_DIR} +) + +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_P2P + ${WPA_SUPPLICANT_BASE}/p2p_supplicant.c + ${WPA_SUPPLICANT_BASE}/p2p_supplicant_sd.c + ${COMMON_SRC_BASE}/p2p/p2p.c + ${COMMON_SRC_BASE}/p2p/p2p_utils.c + ${COMMON_SRC_BASE}/p2p/p2p_parse.c + ${COMMON_SRC_BASE}/p2p/p2p_build.c + ${COMMON_SRC_BASE}/p2p/p2p_go_neg.c + ${COMMON_SRC_BASE}/p2p/p2p_sd.c + ${COMMON_SRC_BASE}/p2p/p2p_pd.c + ${COMMON_SRC_BASE}/p2p/p2p_invitation.c + ${COMMON_SRC_BASE}/p2p/p2p_dev_disc.c + ${COMMON_SRC_BASE}/p2p/p2p_group.c + ${COMMON_SRC_BASE}/ap/p2p_hostapd.c + ${COMMON_SRC_BASE}/common/gas.c + ${WPA_SUPPLICANT_BASE}/gas_query.c + ${WPA_SUPPLICANT_BASE}/offchannel.c +) +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_WPS + ${WPA_SUPPLICANT_BASE}/wps_supplicant.c + ${COMMON_SRC_BASE}/utils/uuid.c + ${COMMON_SRC_BASE}/eap_peer/eap_wsc.c + ${COMMON_SRC_BASE}/eap_common/eap_wsc_common.c + ${COMMON_SRC_BASE}/wps/wps.c + ${COMMON_SRC_BASE}/ap/wps_hostapd.c + ${COMMON_SRC_BASE}/wps/wps_common.c + ${COMMON_SRC_BASE}/wps/wps_attr_parse.c + ${COMMON_SRC_BASE}/wps/wps_attr_build.c + ${COMMON_SRC_BASE}/wps/wps_attr_process.c + ${COMMON_SRC_BASE}/wps/wps_dev_attr.c + ${COMMON_SRC_BASE}/wps/wps_enrollee.c + ${COMMON_SRC_BASE}/wps/wps_registrar.c + ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c + ${COMMON_SRC_BASE}/eap_peer/eap.c + ${COMMON_SRC_BASE}/eap_peer/eap_methods.c + ${COMMON_SRC_BASE}/eap_common/eap_common.c + ${COMMON_SRC_BASE}/crypto/dh_groups.c + ${COMMON_SRC_BASE}/crypto/dh_group5.c +) + +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_P2P + CONFIG_P2P + CONFIG_GAS + CONFIG_OFFCHANNEL +) + +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_WPS + CONFIG_WPS + CONFIG_EAP_WSC + CONFIG_IEEE8021X_EAPOL +) + +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE + ${COMMON_SRC_BASE}/eap_peer/eap_tls.c + ${COMMON_SRC_BASE}/eap_peer/eap_tls_common.c + + ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c + ${COMMON_SRC_BASE}/eap_peer/eap.c + ${COMMON_SRC_BASE}/eap_peer/eap_methods.c + ${COMMON_SRC_BASE}/eap_common/eap_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_peap.c + ${COMMON_SRC_BASE}/eap_common/eap_peap_common.c + ${COMMON_SRC_BASE}/eap_peer/eap_ttls.c + ${COMMON_SRC_BASE}/eap_peer/eap_md5.c + ${COMMON_SRC_BASE}/eap_peer/eap_mschapv2.c + ${COMMON_SRC_BASE}/eap_common/chap.c + ${COMMON_SRC_BASE}/eap_peer/mschapv2.c + ${COMMON_SRC_BASE}/eap_peer/eap_leap.c + + ${COMMON_SRC_BASE}/eap_peer/eap_psk.c + ${COMMON_SRC_BASE}/eap_common/eap_psk_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_fast.c + ${COMMON_SRC_BASE}/eap_peer/eap_fast_pac.c + ${COMMON_SRC_BASE}/eap_common/eap_fast_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_pax.c + ${COMMON_SRC_BASE}/eap_common/eap_pax_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_sake.c + ${COMMON_SRC_BASE}/eap_common/eap_sake_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_gpsk.c + ${COMMON_SRC_BASE}/eap_common/eap_gpsk_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_pwd.c + ${COMMON_SRC_BASE}/eap_common/eap_pwd_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_eke.c + ${COMMON_SRC_BASE}/eap_common/eap_eke_common.c + + ${COMMON_SRC_BASE}/eap_peer/eap_ikev2.c + ${COMMON_SRC_BASE}/eap_peer/ikev2.c + ${COMMON_SRC_BASE}/eap_common/eap_ikev2_common.c + ${COMMON_SRC_BASE}/eap_common/ikev2_common.c + + # common + ${COMMON_SRC_BASE}/crypto/sha384-tlsprf.c + ${COMMON_SRC_BASE}/crypto/sha256-tlsprf.c + ${COMMON_SRC_BASE}/crypto/sha1-tlsprf.c + ${COMMON_SRC_BASE}/crypto/sha1-tprf.c + ${COMMON_SRC_BASE}/crypto/ms_funcs.c + ${COMMON_SRC_BASE}/crypto/aes-eax.c + # MD4 removed from MbedTLS + ${COMMON_SRC_BASE}/crypto/md4-internal + ${COMMON_SRC_BASE}/crypto/aes-encblock.c + +) + +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE + CONFIG_EAP_TLS + CONFIG_IEEE8021X_EAPOL + CONFIG_EAP_PEAP + CONFIG_EAP_TTLS + CONFIG_EAP_MD5 + CONFIG_EAP_MSCHAPv2 + CONFIG_EAP_LEAP + CONFIG_EAP_PSK + CONFIG_EAP_FAST + CONFIG_EAP_PAX + CONFIG_EAP_SAKE + CONFIG_EAP_GPSK + CONFIG_EAP_PWD + CONFIG_EAP_EKE + CONFIG_EAP_IKEv2 +) +endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig new file mode 100644 index 0000000000..95ca551a67 --- /dev/null +++ b/zephyr/Kconfig @@ -0,0 +1,49 @@ +# Nordic WiFi driver for nRF52840 and nRF5340 +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config WPA_SUPP + bool "WPA WPA_SUPP" + depends on NET_SOCKETS + depends on NET_SOCKETS_POSIX_NAMES || POSIX_API + select NET_SOCKETS_PACKET + select NET_MGMT + select NET_MGMT_EVENT + select NET_MGMT_EVENT_INFO + help + WPA WPA_SUPP + +config WPA_SUPP_THREAD_STACK_SIZE + int "Stack size for wpa_supplicant thread" + default 8192 + +config WPA_SUPP_CRYPTO + bool "Crypto support for WiFi" + default y + +config WPA_SUPP_CRYPTO_ENTERPRISE + bool "Enterprise Crypto support for WiFi" + +config WPA_SUPP_WPA3 + bool "WPA3 support" + select WPA_SUPP_CRYPTO + default y + +config WPA_SUPP_AP + bool "AP mode support" + select WPA_SUPP_CRYPTO + +config WPA_SUPP_WPS + bool "WPS support" + +config WPA_SUPP_P2P + bool "P2P mode support" + select WPA_SUPP_AP + select WPA_SUPP_WPS + +config WPA_SUPP_DEBUG_LEVEL + string "Debug level for prints" + default "INFO" diff --git a/zephyr/module.yml b/zephyr/module.yml new file mode 100644 index 0000000000..9c43bc6e5f --- /dev/null +++ b/zephyr/module.yml @@ -0,0 +1,3 @@ +build: + cmake: ./zephyr + kconfig: ./zephyr/Kconfig diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c new file mode 100644 index 0000000000..25de39a695 --- /dev/null +++ b/zephyr/src/supp_main.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * WPA Supplicant / main() function for Zephyr OS + * Copyright (c) 2003-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include +LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); + +#include "includes.h" +#include "common.h" +#include "wpa_supplicant/config.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "fst/fst.h" +#include "includes.h" +#include "p2p_supplicant.h" +#include "wpa_supplicant_i.h" +#include "wifi_mgmt.h" + +struct wpa_supplicant *wpa_s_0; + +static void start_wpa_supplicant(void); +static struct k_sem quit_lock; + +K_THREAD_DEFINE(wpa_s_tid, + CONFIG_WPA_SUPP_THREAD_STACK_SIZE, + start_wpa_supplicant, + NULL, + NULL, + NULL, + 0, + 0, + 0); + +#ifdef CONFIG_MATCH_IFACE +static int wpa_supplicant_init_match(struct wpa_global *global) +{ + /* + * The assumption is that the first driver is the primary driver and + * will handle the arrival / departure of interfaces. + */ + if (wpa_drivers[0]->global_init && !global->drv_priv[0]) { + global->drv_priv[0] = wpa_drivers[0]->global_init(global); + if (!global->drv_priv[0]) { + wpa_printf(MSG_ERROR, + "Failed to initialize driver '%s'", + wpa_drivers[0]->name); + return -1; + } + } + + return 0; +} +#endif /* CONFIG_MATCH_IFACE */ + +#include "config.h" +static void iface_cb(struct net_if *iface, void *user_data) +{ + struct wpa_interface *ifaces = user_data; + struct net_linkaddr *link_addr = NULL; + int ifindex; + char own_addr[6]; + char *ifname; + + ifindex = net_if_get_by_iface(iface); + link_addr = &iface->if_dev->link_addr; + os_memcpy(own_addr, link_addr->addr, link_addr->len); + ifname = os_strdup(iface->if_dev->dev->name); + + wpa_printf( + MSG_INFO, + "iface_cb: iface %s ifindex %d %02x:%02x:%02x:%02x:%02x:%02x", + ifname, ifindex, own_addr[0], own_addr[1], own_addr[2], + own_addr[3], own_addr[4], own_addr[5]); + + /* TODO : make this user configurable*/ + ifaces[0].ifname = "wlan0"; +} + +static void start_wpa_supplicant(void) +{ + int i; + struct wpa_interface *ifaces, *iface; + int iface_count, exitcode = -1; + struct wpa_params params; + struct wpa_global *global; + + os_memset(¶ms, 0, sizeof(params)); + params.wpa_debug_level = str_to_debug_level(CONFIG_WPA_SUPP_DEBUG_LEVEL); + + wpa_printf(MSG_INFO, "%s: %d Starting wpa_supplicant thread with debug level: %d\n", + __func__, __LINE__, params.wpa_debug_level); + + iface = ifaces = os_zalloc(sizeof(struct wpa_interface)); + if (ifaces == NULL) { + return; + } + iface_count = 1; + + exitcode = 0; + global = wpa_supplicant_init(¶ms); + if (global == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant"); + exitcode = -1; + goto out; + } else { + wpa_printf(MSG_INFO, "Successfully initialized " + "wpa_supplicant"); + } + + if (fst_global_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize FST"); + exitcode = -1; + goto out; + } + +#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE) + if (!fst_global_add_ctrl(fst_ctrl_cli)) { + wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl"); + } +#endif + + net_if_foreach(iface_cb, ifaces); + + ifaces[0].ctrl_interface = "test_ctrl"; + params.ctrl_interface = "test_ctrl"; + wpa_printf(MSG_INFO, "Using interface %s\n", ifaces[0].ifname); + + for (i = 0; exitcode == 0 && i < iface_count; i++) { + struct wpa_supplicant *wpa_s; + + if ((ifaces[i].confname == NULL && + ifaces[i].ctrl_interface == NULL) || + ifaces[i].ifname == NULL) { + if (iface_count == 1 && (params.ctrl_interface || +#ifdef CONFIG_MATCH_IFACE + params.match_iface_count || +#endif /* CONFIG_MATCH_IFACE */ + params.dbus_ctrl_interface)) + break; + wpa_printf(MSG_INFO, + "Failed to initialize interface %d\n", i); + exitcode = -1; + break; + } + wpa_printf(MSG_INFO, "Initializing interface %d: %s\n", i, + ifaces[i].ifname); + wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL); + if (wpa_s == NULL) { + exitcode = -1; + break; + } + wpa_s_0 = wpa_s; + wpa_s_0->conf->filter_ssids = 1; + wpa_s_0->conf->ap_scan= 1; + } + +#ifdef CONFIG_MATCH_IFACE + if (exitcode == 0) { + exitcode = wpa_supplicant_init_match(global); + } +#endif /* CONFIG_MATCH_IFACE */ + + if (exitcode == 0) { + exitcode = wpa_supplicant_run(global); + } + + wpa_supplicant_deinit(global); + + fst_global_deinit(); + +out: + os_free(ifaces); +#ifdef CONFIG_MATCH_IFACE + os_free(params.match_ifaces); +#endif /* CONFIG_MATCH_IFACE */ + os_free(params.pid_file); + + k_sem_give(&quit_lock); + wpa_printf(MSG_INFO, "wpa_supplicant_main: exitcode %d", exitcode); + return; +} From 3aa5f4deaa64925ce6f33768614452973e860bed Mon Sep 17 00:00:00 2001 From: krish2718 <100136718+krish2718@users.noreply.github.com> Date: Mon, 11 Jul 2022 17:06:09 +0530 Subject: [PATCH 002/150] Fix build error (#4) The file was removed but was still included. --- zephyr/src/supp_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 25de39a695..2b8d29ffc7 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -24,7 +24,6 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "includes.h" #include "p2p_supplicant.h" #include "wpa_supplicant_i.h" -#include "wifi_mgmt.h" struct wpa_supplicant *wpa_s_0; From dbd03bcb225ef07520fcbc1ab7dcfd48b64b8458 Mon Sep 17 00:00:00 2001 From: krish2718 <100136718+krish2718@users.noreply.github.com> Date: Mon, 11 Jul 2022 17:06:26 +0530 Subject: [PATCH 003/150] MbedTLS compat changes for build (#3) sdk-nrf has a different version where these variables are not private, so, remove the private macro for build. --- src/crypto/crypto_mbedtls-ec.c | 2 +- src/crypto/tls_mbedtls.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/crypto_mbedtls-ec.c b/src/crypto/crypto_mbedtls-ec.c index db2b38b69a..281ca38649 100644 --- a/src/crypto/crypto_mbedtls-ec.c +++ b/src/crypto/crypto_mbedtls-ec.c @@ -135,7 +135,7 @@ struct crypto_ec_group *crypto_ec_get_group_byname(const char *name) mbedtls_ecp_group_init(&e->group); - if (mbedtls_ecp_group_load(&e->group, curve->MBEDTLS_PRIVATE(grp_id))) { + if (mbedtls_ecp_group_load(&e->group, curve->grp_id)) { crypto_ec_deinit(e); e = NULL; } diff --git a/src/crypto/tls_mbedtls.c b/src/crypto/tls_mbedtls.c index e13c10a74e..43b0d89b84 100644 --- a/src/crypto/tls_mbedtls.c +++ b/src/crypto/tls_mbedtls.c @@ -471,7 +471,7 @@ tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_context_t *tls) } else if ( mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 || (tls->cacert_ptr && - mbedtls_pk_get_bitlen(&tls->cacert_ptr->MBEDTLS_PRIVATE(pk)) > + mbedtls_pk_get_bitlen(&tls->cacert_ptr->pk) > 2048)) { mbedtls_ssl_conf_ciphersuites( &tls->conf, eap_ciphersuite_preference); From 9fa75490f4f02cd5e4fb2bf3b11ddfb13ad8e229 Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Mon, 11 Jul 2022 19:58:37 +0530 Subject: [PATCH 004/150] Adding CODEOWNERS file .. (#2) * Adding CODEOWNERS file .. Adding @krish2718 @sr1dh48r @rlubos @sachinthegreen Co-authored-by: krish2718 <100136718+krish2718@users.noreply.github.com> --- CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..d81cb55525 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,8 @@ +# CODEOWNERS for autoreview assigning in github + +# https://help.github.com/en/articles/about-code-owners#codeowners-syntax +# Order is important; the last matching pattern takes the most +# precedence. + +# Root folder +* @krish2718 @sr1dh48r @rlubos @sachinthegreen From 2cc498b142c7e0d2ca44f4d22a1b8cb925cfca55 Mon Sep 17 00:00:00 2001 From: krish2718 <100136718+krish2718@users.noreply.github.com> Date: Thu, 14 Jul 2022 14:33:31 +0530 Subject: [PATCH 005/150] Fix crash in case supplicant init fails (#5) Remove uninitialized variable that is no longer needed, this causes crash in case supplicant thread exits. --- zephyr/src/supp_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 2b8d29ffc7..d87099531a 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -28,7 +28,6 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); struct wpa_supplicant *wpa_s_0; static void start_wpa_supplicant(void); -static struct k_sem quit_lock; K_THREAD_DEFINE(wpa_s_tid, CONFIG_WPA_SUPP_THREAD_STACK_SIZE, @@ -184,7 +183,6 @@ static void start_wpa_supplicant(void) #endif /* CONFIG_MATCH_IFACE */ os_free(params.pid_file); - k_sem_give(&quit_lock); wpa_printf(MSG_INFO, "wpa_supplicant_main: exitcode %d", exitcode); return; } From 5d33e59453987bf211a6c41663142ad05cf68a27 Mon Sep 17 00:00:00 2001 From: krish2718 <100136718+krish2718@users.noreply.github.com> Date: Fri, 15 Jul 2022 16:18:09 +0530 Subject: [PATCH 006/150] Cleanups related to Wi-Fi shell (#6) * Include HOSTAP_BASE to fix header file paths * Select WEP automatically through Kconfig --- zephyr/CMakeLists.txt | 1 + zephyr/Kconfig | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 7df96d7653..56212ee0d8 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -21,6 +21,7 @@ zephyr_compile_definitions( zephyr_include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/ + ${HOSTAP_BASE}/ ${WPA_SUPPLICANT_BASE}/ ${COMMON_SRC_BASE}/ ) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 95ca551a67..59b0748795 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -20,8 +20,12 @@ config WPA_SUPP_THREAD_STACK_SIZE int "Stack size for wpa_supplicant thread" default 8192 +config WEP + bool "WEP (Legacy crypto) support" + config WPA_SUPP_CRYPTO bool "Crypto support for WiFi" + select WEP default y config WPA_SUPP_CRYPTO_ENTERPRISE From bf7be5627d2fa528bd61ce1ff10d89828a4d4697 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 15 Jul 2022 22:27:35 +0530 Subject: [PATCH 007/150] Fix upstream warnings nRF CI treats warnings as errors, so, this is must. --- src/rsn_supp/wpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 0a2f877875..9c04692e8d 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2365,7 +2365,7 @@ static void wpa_eapol_key_dump(struct wpa_sm *sm, wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)", + " key_info 0x%x (ver=%d keyidx=%ld rsvd=%ld %s%s%s%s%s%s%s%s)", key_info, key_info & WPA_KEY_INFO_TYPE_MASK, (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> WPA_KEY_INFO_KEY_INDEX_SHIFT, From 5a77ce258cde5053e68c133d763eb32f79a1e9a8 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Tue, 19 Jul 2022 13:36:55 +0200 Subject: [PATCH 008/150] Support build with IPv6 enabled only Add proper pre-processor conditions to the code that uses IPv4 API. Signed-off-by: Damian Krolik --- src/drivers/driver_zephyr.c | 2 ++ src/l2_packet/l2_packet_zephyr.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 6b43a83176..eaa57b2563 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -702,11 +702,13 @@ static int wpa_drv_zep_set_supp_port(void *priv, authorized, if_ctx->bssid); +#ifdef CONFIG_NET_DHCPV4 if (authorized) { net_dhcpv4_stop(iface); k_msleep(500); net_dhcpv4_start(iface); } +#endif return ret; } diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index 364849a7e0..6d3096a266 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -231,11 +231,15 @@ void l2_packet_deinit(struct l2_packet_data *l2) int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) { +#ifdef CONFIG_NET_IPV4 char addr_buf[NET_IPV4_ADDR_LEN]; os_strlcpy(buf, net_addr_ntop(AF_INET, &l2->iface->config.ip.ipv4->unicast[0].address.in_addr.s_addr, addr_buf, sizeof(addr_buf)), len); return 0; +#else + return -1; +#endif } void l2_packet_notify_auth_start(struct l2_packet_data *l2) From 4f47e17d808c77c1f39aec1b7948c519cfdf4b05 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 20 Jul 2022 21:09:52 +0530 Subject: [PATCH 009/150] Remove AF_PACKET workaround PR [1] is now up-merged to NCS, so, remove the workaround. [1] - https://github.com/zephyrproject-rtos/zephyr/pull/45592 Signed-off-by: Krishna T --- src/l2_packet/l2_packet_zephyr.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index 6d3096a266..0d2ff60a18 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -103,19 +103,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", __func__, MAC2STR(ll.sll_addr), (int) res); - // FIXME: CONFIG_NET_SOCKETS_PACKET_DGRAM should remove L2 header and fill ll - // but, it is not working. For now, remove the L2 header before passing the - // packet to the upper layers - if (!l2->l2_hdr) { - unsigned char l2_hdr_len = sizeof(struct l2_ethhdr); - if (res > l2_hdr_len) { - l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, &buf[l2_hdr_len], res-l2_hdr_len); - } else { - wpa_printf(MSG_WARNING, "RAW : received packet is too short: %d", res); - } - } else { - l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); - } + l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); } struct l2_packet_data * From c2400e7d600a4a5dc2f6f587ab337862ea85863a Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 20 Jul 2022 21:43:10 +0530 Subject: [PATCH 010/150] Add workaround for filtering unnecessary frames Previous to [1] we used to get L2 header and that was used to filter unregistered frames (another bug), but now that L2 header is removed, we cannot use L2 header, so, directly parse payload and filter EAPoL frames only. [1] - https://github.com/zephyrproject-rtos/zephyr/pull/45592 Signed-off-by: Krishna T --- src/l2_packet/l2_packet_zephyr.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index 0d2ff60a18..bc6545d88c 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -9,6 +9,7 @@ #include "common.h" #include "eloop.h" #include "l2_packet.h" +#include "common/eapol_common.h" #include @@ -81,7 +82,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) int res; struct sockaddr_ll ll; socklen_t fromlen; - struct l2_ethhdr *ethhdr; + struct ieee802_1x_hdr *hdr; os_memset(&ll, 0, sizeof(ll)); fromlen = sizeof(ll); @@ -92,17 +93,19 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) return; } - // FIXME: We should only get registered protcols from networking stack - // but for some reason ETH_P_ALL is being set (bind_default) - ethhdr = (struct l2_ethhdr *) buf; - if (ethhdr->h_proto != htons(l2->protocol)) { - return; - } - // FIXME: sll_addr is not being filled as L2 header is not removed - wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", - __func__, MAC2STR(ll.sll_addr), (int) res); + wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " proto=0x%x len=%d", + __func__, MAC2STR(ll.sll_addr), ll.sll_protocol, (int) res); + hdr = (const struct ieee802_1x_hdr *) buf; + + // FIXME: L2 header is now removed but sll_protocol is not set. + // So, as a workaround add this check to drop packets. + if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) + return; + + // FIXME: We should only get registered protcols from networking stack + // but for some reason ETH_P_ALL is being set (bind_default) l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); } From 3dabc364cb4e4e7f3513889431737b02ee0111e0 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 21 Jul 2022 18:42:54 +0530 Subject: [PATCH 011/150] Fix a build warning Add const qualifier to the declaration. Signed-off-by: Krishna T --- src/l2_packet/l2_packet_zephyr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index bc6545d88c..7469c6dabe 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -82,7 +82,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) int res; struct sockaddr_ll ll; socklen_t fromlen; - struct ieee802_1x_hdr *hdr; + const struct ieee802_1x_hdr *hdr; os_memset(&ll, 0, sizeof(ll)); fromlen = sizeof(ll); From 386a52e67193f5166090f40a59a5bb0951900ce4 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Wed, 3 Aug 2022 15:19:59 +0200 Subject: [PATCH 012/150] Compile out logs based on configured log level 1. Add WPA_SUPP_LOG_LEVEL_* Kconfig options to control the WPA supplicant log level the same way as other SDK components. 2. Add WPA_SUPP_DEBUG_LEVEL Kconfig option to be used for compile-time filtering of WPA supplicant debug messages. By default, it is aligned with WPA_SUPP_LOG_LEVEL. 3. Implement Zephyr variants of wpa_debug.h and wpa_debug.c files that use Zephyr logging subystem as the default output and apply compile-time filtering for the messages. Signed-off-by: Damian Krolik --- src/utils/common.h | 2 +- zephyr/CMakeLists.txt | 5 +- zephyr/Kconfig | 18 +- zephyr/src/supp_main.c | 2 +- zephyr/src/utils/wpa_debug.c | 414 +++++++++++++++++++++++++++++++++++ zephyr/src/utils/wpa_debug.h | 389 ++++++++++++++++++++++++++++++++ 6 files changed, 824 insertions(+), 6 deletions(-) create mode 100644 zephyr/src/utils/wpa_debug.c create mode 100644 zephyr/src/utils/wpa_debug.h diff --git a/src/utils/common.h b/src/utils/common.h index 6693b2b6f5..4a06a7126b 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -532,7 +532,7 @@ static inline int is_multicast_ether_addr(const u8 *a) #define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff" -#include "wpa_debug.h" +#include struct wpa_freq_range_list { diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 56212ee0d8..908cb85567 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -20,7 +20,7 @@ zephyr_compile_definitions( ) zephyr_include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/src ${HOSTAP_BASE}/ ${WPA_SUPPLICANT_BASE}/ ${COMMON_SRC_BASE}/ @@ -40,6 +40,7 @@ zephyr_library_compile_definitions( ) zephyr_library_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/src ${HOSTAP_BASE}/ ${COMMON_SRC_BASE}/utils ${COMMON_SRC_BASE}/drivers @@ -61,7 +62,6 @@ zephyr_library_sources( ${COMMON_SRC_BASE}/drivers/driver_zephyr.c ${COMMON_SRC_BASE}/utils/base64.c ${COMMON_SRC_BASE}/utils/common.c - ${COMMON_SRC_BASE}/utils/wpa_debug.c ${COMMON_SRC_BASE}/utils/wpabuf.c ${COMMON_SRC_BASE}/utils/bitfield.c ${COMMON_SRC_BASE}/utils/eloop.c @@ -88,6 +88,7 @@ zephyr_library_sources( ${WPA_SUPPLICANT_BASE}/wpa_cli.c # Zephyr main src/supp_main.c + src/utils/wpa_debug.c ) zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_AP ${WPA_SUPPLICANT_BASE}/ap.c diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 59b0748795..6f3ef0c660 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -48,6 +48,20 @@ config WPA_SUPP_P2P select WPA_SUPP_AP select WPA_SUPP_WPS +module = WPA_SUPP +module-str = WPA supplicant +source "subsys/logging/Kconfig.template.log_config" + config WPA_SUPP_DEBUG_LEVEL - string "Debug level for prints" - default "INFO" + int "Min compiled-in debug message level for WPA supplicant" + default 0 if WPA_SUPP_LOG_LEVEL_DBG # MSG_EXCESSIVE + default 3 if WPA_SUPP_LOG_LEVEL_INF # MSG_INFO + default 4 if WPA_SUPP_LOG_LEVEL_WRN # MSG_WARNING + default 5 if WPA_SUPP_LOG_LEVEL_ERR # MSG_ERROR + default 6 + help + Minimum priority level of a debug message emitted by WPA supplicant that + is compiled-in the firmware. See wpa_debug.h file of the supplicant for + available levels and functions for emitting the messages. Note that + runtime filtering can also be configured in addition to the compile-time + filtering. diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index d87099531a..1c55d97004 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -93,7 +93,7 @@ static void start_wpa_supplicant(void) struct wpa_global *global; os_memset(¶ms, 0, sizeof(params)); - params.wpa_debug_level = str_to_debug_level(CONFIG_WPA_SUPP_DEBUG_LEVEL); + params.wpa_debug_level = CONFIG_WPA_SUPP_DEBUG_LEVEL; wpa_printf(MSG_INFO, "%s: %d Starting wpa_supplicant thread with debug level: %d\n", __func__, __LINE__, params.wpa_debug_level); diff --git a/zephyr/src/utils/wpa_debug.c b/zephyr/src/utils/wpa_debug.c new file mode 100644 index 0000000000..542f3e8dee --- /dev/null +++ b/zephyr/src/utils/wpa_debug.c @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * wpa_supplicant/hostapd / Debug prints + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include +#include + +#include "wpa_debug.h" + +#include + +#define WPA_DEBUG_MAX_LINE_LENGTH 256 + +LOG_MODULE_REGISTER(wpa_supp, CONFIG_WPA_SUPP_LOG_LEVEL); + +int wpa_debug_level = MSG_INFO; +int wpa_debug_show_keys = 0; +int wpa_debug_timestamp = 0; + +#ifndef CONFIG_NO_STDOUT_DEBUG + +void wpa_printf_impl(int level, const char *fmt, ...) +{ + va_list ap; + char buffer[WPA_DEBUG_MAX_LINE_LENGTH]; + + if (level < wpa_debug_level) + return; + + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + switch (level) { + case MSG_ERROR: + LOG_ERR("%s", buffer); + break; + case MSG_WARNING: + LOG_WRN("%s", buffer); + break; + case MSG_INFO: + LOG_INF("%s", buffer); + break; + case MSG_DEBUG: + case MSG_MSGDUMP: + case MSG_EXCESSIVE: + LOG_DBG("%s", buffer); + break; + default: + break; + } + + forced_memzero(buffer, sizeof(buffer)); +} + +static void _wpa_hexdump(int level, const char *title, const u8 *buf, size_t len, int show) +{ + size_t i; + const char *content; + char *content_buf = NULL; + + if (level < wpa_debug_level) + return; + + if (buf == NULL) { + content = " [NULL]"; + } else if (show) { + content = content_buf = os_malloc(3 * len + 1); + + if (content == NULL) { + wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to allocate message buffer"); + return; + } + + for (i = 0; i < len; i++) { + os_snprintf(&content_buf[i * 3], 4, " %02x", buf[i]); + } + } else { + content = " [REMOVED]"; + } + + wpa_printf(level, "%s - hexdump(len=%lu):%s", title, (unsigned long)len, content); + bin_clear_free(content_buf, 3 * len + 1); +} + +void wpa_hexdump_impl(int level, const char *title, const void *buf, size_t len) +{ + _wpa_hexdump(level, title, buf, len, 1); +} + +void wpa_hexdump_key_impl(int level, const char *title, const void *buf, size_t len) +{ + _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); +} + +static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, size_t len, int show) +{ + const char *content; + + if (level < wpa_debug_level) { + return; + } + + if (buf == NULL) { + content = " [NULL]"; + } else if (show) { + content = ""; + } else { + content = " [REMOVED]"; + } + + wpa_printf(level, "%s - hexdump_ascii(len=%lu):%s", title, (unsigned long)len, content); + + if (buf == NULL || !show) { + return; + } + + switch (level) { + case MSG_ERROR: + LOG_HEXDUMP_ERR(buf, len, ""); + break; + case MSG_WARNING: + LOG_HEXDUMP_WRN(buf, len, ""); + break; + case MSG_INFO: + LOG_HEXDUMP_INF(buf, len, ""); + break; + case MSG_DEBUG: + case MSG_MSGDUMP: + case MSG_EXCESSIVE: + LOG_HEXDUMP_DBG(buf, len, ""); + break; + default: + break; + } +} + +void wpa_hexdump_ascii_impl(int level, const char *title, const void *buf, size_t len) +{ + _wpa_hexdump_ascii(level, title, buf, len, 1); +} + +void wpa_hexdump_ascii_key_impl(int level, const char *title, const void *buf, size_t len) +{ + _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); +} + +#endif /* CONFIG_NO_STDOUT_DEBUG */ + +#ifndef CONFIG_NO_WPA_MSG + +static wpa_msg_cb_func wpa_msg_cb = NULL; + +void wpa_msg_register_cb(wpa_msg_cb_func func) +{ + wpa_msg_cb = func; +} + +static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; + +void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) +{ + wpa_msg_ifname_cb = func; +} + +void wpa_msg_impl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + char prefix[130]; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + prefix[0] = '\0'; + if (wpa_msg_ifname_cb) { + const char *ifname = wpa_msg_ifname_cb(ctx); + if (ifname) { + int res = os_snprintf(prefix, sizeof(prefix), "%s: ", ifname); + if (os_snprintf_error(sizeof(prefix), res)) + prefix[0] = '\0'; + } + } + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s%s", prefix, buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); + bin_clear_free(buf, buflen); +} + +void wpa_msg_ctrl_impl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + if (!wpa_msg_cb) + return; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len); + bin_clear_free(buf, buflen); +} + +void wpa_msg_global_impl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s", buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); + bin_clear_free(buf, buflen); +} + +void wpa_msg_global_ctrl_impl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + if (!wpa_msg_cb) + return; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg_global_ctrl: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len); + bin_clear_free(buf, buflen); +} + +void wpa_msg_no_global_impl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s", buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len); + bin_clear_free(buf, buflen); +} + +void wpa_msg_global_only_impl(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer", __func__); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + wpa_printf(level, "%s", buf); + if (wpa_msg_cb) + wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len); + os_free(buf); +} + +#endif /* CONFIG_NO_WPA_MSG */ + +#ifndef CONFIG_NO_HOSTAPD_LOGGER + +static hostapd_logger_cb_func hostapd_logger_cb = NULL; + +void hostapd_logger_register_cb(hostapd_logger_cb_func func) +{ + hostapd_logger_cb = func; +} + +void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate message buffer"); + return; + } + va_start(ap, fmt); + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + if (hostapd_logger_cb) + hostapd_logger_cb(ctx, addr, module, level, buf, len); + else if (addr) + wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", MAC2STR(addr), buf); + else + wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); + bin_clear_free(buf, buflen); +} + +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ + +const char *debug_level_str(int level) +{ + switch (level) { + case MSG_EXCESSIVE: + return "EXCESSIVE"; + case MSG_MSGDUMP: + return "MSGDUMP"; + case MSG_DEBUG: + return "DEBUG"; + case MSG_INFO: + return "INFO"; + case MSG_WARNING: + return "WARNING"; + case MSG_ERROR: + return "ERROR"; + default: + return "?"; + } +} + +int str_to_debug_level(const char *s) +{ + if (os_strcasecmp(s, "EXCESSIVE") == 0) + return MSG_EXCESSIVE; + if (os_strcasecmp(s, "MSGDUMP") == 0) + return MSG_MSGDUMP; + if (os_strcasecmp(s, "DEBUG") == 0) + return MSG_DEBUG; + if (os_strcasecmp(s, "INFO") == 0) + return MSG_INFO; + if (os_strcasecmp(s, "WARNING") == 0) + return MSG_WARNING; + if (os_strcasecmp(s, "ERROR") == 0) + return MSG_ERROR; + return -1; +} diff --git a/zephyr/src/utils/wpa_debug.h b/zephyr/src/utils/wpa_debug.h new file mode 100644 index 0000000000..5843cedf17 --- /dev/null +++ b/zephyr/src/utils/wpa_debug.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * wpa_supplicant/hostapd / Debug prints + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_DEBUG_H +#define WPA_DEBUG_H + +#include + +#include + +extern int wpa_debug_level; +extern int wpa_debug_show_keys; +extern int wpa_debug_timestamp; + +enum { MSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; + +/** + * wpa_debug_level_enabled - determine if the given priority level is enabled + * by compile-time configuration. + * + * @level: priority level of a message + */ +#define wpa_debug_level_enabled(level) (CONFIG_WPA_SUPP_DEBUG_LEVEL <= (level)) + +/** + * wpa_debug_cond_run - run the action if the given condition is met + * + * @cond: condition expression + * @action: action to run + */ +#define wpa_debug_cond_run(cond, action) \ + do { \ + if (cond) { \ + action; \ + } \ + } while (0) + + +#ifdef CONFIG_NO_STDOUT_DEBUG + +#define wpa_printf(args...) do { } while (0) +#define wpa_hexdump(l,t,b,le) do { } while (0) +#define wpa_hexdump_buf(l,t,b) do { } while (0) +#define wpa_hexdump_key(l,t,b,le) do { } while (0) +#define wpa_hexdump_buf_key(l,t,b) do { } while (0) +#define wpa_hexdump_ascii(l,t,b,le) do { } while (0) +#define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) +#define wpa_dbg(args...) do { } while (0) + +#else /* CONFIG_NO_STDOUT_DEBUG */ + +/** + * wpa_printf - conditional printf + * + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * The output is directed to Zephyr logging subsystem. + */ +#define wpa_printf(level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_printf_impl(level, fmt, ##__VA_ARGS__)) + +void wpa_printf_impl(int level, const char *fmt, ...) PRINTF_FORMAT(2, 3); + +/** + * wpa_hexdump - conditional hex dump + * + * @level: priority level (MSG_*) of the message + * @title: title of the message + * @buf: data buffer to be dumped + * @len: length of the buffer + * + * This function is used to print conditional debugging and error messages. + * The output is directed to Zephyr logging subsystem. The contents of buf is + * printed out as hex dump. + */ +#define wpa_hexdump(level, title, buf, len) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), wpa_hexdump_impl(level, title, buf, len)) + +void wpa_hexdump_impl(int level, const char *title, const void *buf, size_t len); + +static inline void wpa_hexdump_buf(int level, const char *title, const struct wpabuf *buf) +{ + wpa_hexdump(level, title, buf ? wpabuf_head(buf) : NULL, buf ? wpabuf_len(buf) : 0); +} + +/** + * wpa_hexdump_key - conditional hex dump, hide keys + * + * @level: priority level (MSG_*) of the message + * @title: title of the message + * @buf: data buffer to be dumped + * @len: length of the buffer + * + * This function is used to print conditional debugging and error messages. + * The output is directed to Zephyr logging subsystem. The contents of buf is + * printed out as hex dump. This works like wpa_hexdump(), but by default, does + * not include secret keys (passwords, etc.) in debug output. + */ +#define wpa_hexdump_key(level, title, buf, len) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_hexdump_key_impl(level, title, buf, len)) + +void wpa_hexdump_key_impl(int level, const char *title, const void *buf, size_t len); + +static inline void wpa_hexdump_buf_key(int level, const char *title, const struct wpabuf *buf) +{ + wpa_hexdump_key(level, title, buf ? wpabuf_head(buf) : NULL, buf ? wpabuf_len(buf) : 0); +} + +/** + * wpa_hexdump_ascii - conditional hex dump + * + * @level: priority level (MSG_*) of the message + * @title: title of the message + * @buf: data buffer to be dumped + * @len: length of the buffer + * + * This function is used to print conditional debugging and error messages. + * The output is directed to Zephyr logging subsystem. The contents of buf is + * printed out as hex dump with both the hex numbers and ASCII characters (for + * printable range) shown. 16 bytes per line will be shown. + */ +#define wpa_hexdump_ascii(level, title, buf, len) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_hexdump_ascii_impl(level, title, buf, len)) + +void wpa_hexdump_ascii_impl(int level, const char *title, const void *buf, size_t len); + +/** + * wpa_hexdump_ascii_key - conditional hex dump, hide keys + * @level: priority level (MSG_*) of the message + * @title: title of the message + * @buf: data buffer to be dumped + * @len: length of the buffer + * + * This function is used to print conditional debugging and error messages. + * The output is directed to Zephyr logging subsystem. The contents of buf is + * printed out as hex dump with both the hex numbers and ASCII characters (for + * printable range) shown. 16 bytes per line will be shown. This works like + * wpa_hexdump_ascii(), but by default, does not include secret keys + * (passwords, etc.) in debug output. + */ +#define wpa_hexdump_ascii_key(level, title, buf, len) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_hexdump_ascii_key_impl(level, title, buf, len)); + +void wpa_hexdump_ascii_key_impl(int level, const char *title, const void *buf, size_t len); + +/* + * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce + * binary size. As such, it should be used with debugging messages that are not + * needed in the control interface while wpa_msg() has to be used for anything + * that needs to shown to control interface monitors. + */ +#define wpa_dbg(args...) wpa_msg(args) + +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + +#ifdef CONFIG_NO_WPA_MSG + +#define wpa_msg(args...) do { } while (0) +#define wpa_msg_ctrl(args...) do { } while (0) +#define wpa_msg_global(args...) do { } while (0) +#define wpa_msg_global_ctrl(args...) do { } while (0) +#define wpa_msg_no_global(args...) do { } while (0) +#define wpa_msg_global_only(args...) do { } while (0) +#define wpa_msg_register_cb(f) do { } while (0) +#define wpa_msg_register_ifname_cb(f) do { } while (0) + +#else /* CONFIG_NO_WPA_MSG */ + +/** + * wpa_msg - Conditional printf for default target and ctrl_iface monitors + * + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * The output is directed to Zephyr logging subsystem. This function is like + * wpa_printf(), but it also sends the same message to all attached ctrl_iface + * monitors. + */ +#define wpa_msg(ctx, level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_msg_impl(ctx, level, fmt, ##__VA_ARGS__)) + +void wpa_msg_impl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors + * + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg(), but it sends the output only to the + * attached ctrl_iface monitors. In other words, it can be used for frequent + * events that do not need to be sent to syslog. + */ +#define wpa_msg_ctrl(ctx, level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_msg_ctrl_impl(ctx, level, fmt, ##__VA_ARGS__)) + +void wpa_msg_ctrl_impl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_global - Global printf for ctrl_iface monitors + * + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg(), but it sends the output as a global event, + * i.e., without being specific to an interface. For backwards compatibility, + * an old style event is also delivered on one of the interfaces (the one + * specified by the context data). + */ +#define wpa_msg_global(ctx, level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_msg_global_impl(ctx, level, fmt, ##__VA_ARGS__)) + +void wpa_msg_global_impl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_global_ctrl - Conditional global printf for ctrl_iface monitors + * + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg_global(), but it sends the output only to the + * attached global ctrl_iface monitors. In other words, it can be used for + * frequent events that do not need to be sent to syslog. + */ +#define wpa_msg_global_ctrl(ctx, level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_msg_global_ctrl_impl(ctx, level, fmt, ##__VA_ARGS__)) + +void wpa_msg_global_ctrl_impl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_no_global - Conditional printf for ctrl_iface monitors + * + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg(), but it does not send the output as a global + * event. + */ +#define wpa_msg_no_global(ctx, level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_msg_no_global_impl(ctx, level, fmt, ##__VA_ARGS__)) + +void wpa_msg_no_global_impl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_global_only - Conditional printf for ctrl_iface monitors + * + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg_global(), but it sends the output only as a + * global event. + */ +#define wpa_msg_global_only(ctx, level, fmt, ...) \ + wpa_debug_cond_run(wpa_debug_level_enabled(level), \ + wpa_msg_global_only_impl(ctx, level, fmt, ##__VA_ARGS__)) + +void wpa_msg_global_only_impl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +enum wpa_msg_type { + WPA_MSG_PER_INTERFACE, + WPA_MSG_GLOBAL, + WPA_MSG_NO_GLOBAL, + WPA_MSG_ONLY_GLOBAL, +}; + +typedef void (*wpa_msg_cb_func)(void *ctx, int level, enum wpa_msg_type type, const char *txt, + size_t len); + +/** + * wpa_msg_register_cb - Register callback function for wpa_msg() messages + * @func: Callback function (%NULL to unregister) + */ +void wpa_msg_register_cb(wpa_msg_cb_func func); + +typedef const char * (*wpa_msg_get_ifname_func)(void *ctx); +void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func); + +#endif /* CONFIG_NO_WPA_MSG */ + + +#ifdef CONFIG_NO_HOSTAPD_LOGGER + +#define hostapd_logger(args...) do { } while (0) +#define hostapd_logger_register_cb(f) do { } while (0) + +#else /* CONFIG_NO_HOSTAPD_LOGGER */ + +#define HOSTAPD_MODULE_IEEE80211 0x00000001 +#define HOSTAPD_MODULE_IEEE8021X 0x00000002 +#define HOSTAPD_MODULE_RADIUS 0x00000004 +#define HOSTAPD_MODULE_WPA 0x00000008 +#define HOSTAPD_MODULE_DRIVER 0x00000010 +#define HOSTAPD_MODULE_MLME 0x00000040 + +enum hostapd_logger_level { + HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, + HOSTAPD_LEVEL_DEBUG = 1, + HOSTAPD_LEVEL_INFO = 2, + HOSTAPD_LEVEL_NOTICE = 3, + HOSTAPD_LEVEL_WARNING = 4 +}; + +void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, const char *fmt, ...) + PRINTF_FORMAT(5, 6); + +typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr, unsigned int module, int level, + const char *txt, size_t len); + +/** + * hostapd_logger_register_cb - Register callback function for hostapd_logger() + * @func: Callback function (NULL to unregister) + */ +void hostapd_logger_register_cb(hostapd_logger_cb_func func); + +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ + + +/* CONFIG_DEBUG_FILE is not supported by Zephyr */ + +static inline int wpa_debug_open_file(const char *path) { return 0; } +static inline int wpa_debug_reopen_file(void) { return 0; } +static inline void wpa_debug_close_file(void) {} +static inline void wpa_debug_setup_stdout(void) {} + + +/* CONFIG_DEBUG_SYSLOG is not supported by Zephyr */ + +static inline void wpa_debug_open_syslog(void) {} +static inline void wpa_debug_close_syslog(void) {} + + +/* CONFIG_DEBUG_LINUX_TRACING is not supported by Zephyr */ + +static inline int wpa_debug_open_linux_tracing(void) { return 0; } +static inline void wpa_debug_close_linux_tracing(void) {} + + +#ifdef EAPOL_TEST +#define WPA_ASSERT __ASSERT +#else +#define WPA_ASSERT(a) do {} while (0) +#endif + + +const char * debug_level_str(int level); +int str_to_debug_level(const char *s); + +#endif /* WPA_DEBUG_H */ From db69d6c50b741a0529c66ea429702759a81c3ac2 Mon Sep 17 00:00:00 2001 From: krishna T Date: Sat, 27 Aug 2022 22:45:29 +0530 Subject: [PATCH 013/150] Add Nordic copyright for MbedTLS files As per Apache-2.0 license, we need to indicate that the files have been modified, the recommended way is to add an extra copyright header. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 1 + src/crypto/crypto_mbedtls-ec.c | 1 + src/crypto/crypto_mbedtls.c | 1 + src/crypto/tls_mbedtls.c | 1 + 4 files changed, 4 insertions(+) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index bf49047a00..4a4b939e1d 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/src/crypto/crypto_mbedtls-ec.c b/src/crypto/crypto_mbedtls-ec.c index 281ca38649..4f62e7d862 100644 --- a/src/crypto/crypto_mbedtls-ec.c +++ b/src/crypto/crypto_mbedtls-ec.c @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/src/crypto/crypto_mbedtls.c b/src/crypto/crypto_mbedtls.c index a9ea78f2d3..3b800a0e75 100644 --- a/src/crypto/crypto_mbedtls.c +++ b/src/crypto/crypto_mbedtls.c @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/src/crypto/tls_mbedtls.c b/src/crypto/tls_mbedtls.c index 43b0d89b84..22e737686b 100644 --- a/src/crypto/tls_mbedtls.c +++ b/src/crypto/tls_mbedtls.c @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ From 5d2e29e57ee97402be0c574afbd70e622337a416 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 20 Jul 2022 18:54:52 +0530 Subject: [PATCH 014/150] Redesign the events passing to wpa_supplicant from driver Eloop framework in wpa_supplicant uses select with minimal timeout of all registered users, but by default it is 10secs (periodic cleanup task), so, in case of no other events all registered users will be delayed by 10secs. In Linux, select exits without waiting for full 10secs as for there is a handler registered for NL80211 sockets and whenever there is a event from Kernel select exits and processes expired events immediately. In Zephyr, we don't have such mechanism as we use direction function calls between kernel and wpa_supplicant, so, add an event socket and register it with Eloop and use this to post the event, the socket handler pass the event to wpa_supplicant. For user interface we just post a dummy message only to unblock select. This solves both problems: * Unblocking select for all interesting events immediately * Terminate driver context for events as we use sockets, so, remove mbox + thread. This significantly improves the association time from 30s to 5s. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 110 ++++++++++++-------------------- src/drivers/driver_zephyr.h | 8 +-- zephyr/src/supp_main.c | 124 +++++++++++++++++++++++++++++++++++- zephyr/src/supp_main.h | 17 +++++ 4 files changed, 182 insertions(+), 77 deletions(-) create mode 100644 zephyr/src/supp_main.h diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index eaa57b2563..77c49826b4 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -5,64 +5,35 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ +#include + #include "includes.h" #include "utils/common.h" #include "eloop.h" #include "driver_zephyr.h" +#include "supp_main.h" -K_MBOX_DEFINE(wpa_supp_mbox); #define SCAN_TIMEOUT 30 -static void wpa_supp_drv_mbox_msg_handler(void *eloop_ctx, - void *timeout_ctx) -{ - struct k_mbox_msg msg; - struct zep_wpa_supp_mbox_msg_data mbox_msg_data; - - /* Prepare to receive message */ - msg.size = sizeof(mbox_msg_data); - msg.rx_source_thread = K_ANY; - - k_mbox_get(&wpa_supp_mbox, - &msg, - &mbox_msg_data, - K_FOREVER); - - mbox_msg_data.cb(mbox_msg_data.ctx, - mbox_msg_data.data, - 0); -} - - -void wpa_supp_event_handler(void *ctx, - void *data, - void *cb) +void wpa_supplicant_event_wrapper(void *ctx, + enum wpa_event_type event, + union wpa_event_data *data) { - struct k_mbox_msg send_msg; - struct zep_wpa_supp_mbox_msg_data mbox_msg_data; - - mbox_msg_data.ctx = ctx; - mbox_msg_data.data = data; - mbox_msg_data.cb = cb; - - /* Prepare to send message */ - send_msg.size = sizeof(mbox_msg_data); - send_msg.tx_data = &mbox_msg_data; - send_msg.tx_block.data = NULL; - send_msg.tx_target_thread = K_ANY; - - eloop_register_timeout(0, - 500, - wpa_supp_drv_mbox_msg_handler, - NULL, - NULL); - - k_mbox_put(&wpa_supp_mbox, - &send_msg, - K_FOREVER); + struct wpa_supplicant_event_msg msg = { 0 }; + + msg.ctx = ctx; + msg.event = event; + if (data) { + msg.data = os_zalloc(sizeof(*data)); + if (!msg.data) { + wpa_printf(MSG_ERROR, "Failed to allocated for event: %d", event); + return; + } + os_memcpy(msg.data, data, sizeof(*data)); + } + send_wpa_supplicant_event(&msg); } - static int wpa_drv_zep_abort_scan(void *priv, u64 scan_cookie) { @@ -113,9 +84,9 @@ void wpa_drv_zep_scan_timeout(void *eloop_ctx, void *timeout_ctx) void wpa_drv_zep_event_proc_scan_start(struct zep_drv_if_ctx *if_ctx) { - wpa_supplicant_event(if_ctx->supp_if_ctx, - EVENT_SCAN_STARTED, - NULL); + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_SCAN_STARTED, + NULL); } @@ -126,9 +97,11 @@ void wpa_drv_zep_event_proc_scan_done(struct zep_drv_if_ctx *if_ctx, if_ctx, if_ctx->supp_if_ctx); - wpa_supplicant_event(if_ctx->supp_if_ctx, - EVENT_SCAN_RESULTS, - event); + if_ctx->scan_res2_get_in_prog = false; + + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_SCAN_RESULTS, + event); } @@ -158,7 +131,7 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, void wpa_drv_zep_event_proc_auth_resp(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { - wpa_supplicant_event(if_ctx->supp_if_ctx, + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_AUTH, event); } @@ -169,9 +142,9 @@ void wpa_drv_zep_event_proc_assoc_resp(struct zep_drv_if_ctx *if_ctx, unsigned int status) { if (status != WLAN_STATUS_SUCCESS) { - wpa_supplicant_event(if_ctx->supp_if_ctx, - EVENT_ASSOC_REJECT, - event); + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_ASSOC_REJECT, + event); } else { if_ctx->associated = true; @@ -179,9 +152,9 @@ void wpa_drv_zep_event_proc_assoc_resp(struct zep_drv_if_ctx *if_ctx, event->assoc_info.addr, ETH_ALEN); - wpa_supplicant_event(if_ctx->supp_if_ctx, - EVENT_ASSOC, - event); + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_ASSOC, + event); } } @@ -189,18 +162,18 @@ void wpa_drv_zep_event_proc_assoc_resp(struct zep_drv_if_ctx *if_ctx, void wpa_drv_zep_event_proc_deauth(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { - wpa_supplicant_event(if_ctx->supp_if_ctx, - EVENT_DEAUTH, - event); + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_DEAUTH, + event); } void wpa_drv_zep_event_proc_disassoc(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event) { - wpa_supplicant_event(if_ctx->supp_if_ctx, - EVENT_DISASSOC, - event); + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_DISASSOC, + event); } @@ -235,7 +208,7 @@ static void wpa_drv_zep_global_deinit(void *priv) /** * wpa_driver_zep_init - Initialize Zephyr driver interface * @ctx: Context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() + * e.g., wpa_supplicant_event_wrapper() * @ifname: Interface name, e.g., wlan0 * @global_priv: private driver global data from global_init() * @@ -421,6 +394,7 @@ struct wpa_scan_results *wpa_drv_zep_get_scan_results2(void *priv) if_ctx->scan_res2 = os_zalloc(sizeof(*if_ctx->scan_res2)); if (!if_ctx->scan_res2) { + wpa_printf(MSG_ERROR, "%s: Failed to alloc memory for scan results\n", __func__); goto out; } diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index d61cda1eb6..b39c45369e 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -15,10 +15,8 @@ struct zep_wpa_supp_mbox_msg_data { void *ctx; + enum wpa_event_type event; void *data; - void (*cb)(void *ctx, - void *data, - int flags); }; @@ -98,8 +96,4 @@ struct zep_wpa_supp_dev_ops { char *bssid); }; - -void wpa_supp_event_handler(void *ctx, - void *data, - void *cb); #endif /* DRIVER_ZEPHYR_H */ diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 1c55d97004..224bcf5cb1 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -13,19 +13,29 @@ */ #include +#include LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "includes.h" #include "common.h" +#include "eloop.h" #include "wpa_supplicant/config.h" #include "wpa_supplicant_i.h" -#include "driver_i.h" + #include "fst/fst.h" #include "includes.h" #include "p2p_supplicant.h" #include "wpa_supplicant_i.h" +#include "driver_i.h" + +#include "supp_main.h" + + +#define DUMMY_SOCKET_PORT 9999 + +struct wpa_global *global; -struct wpa_supplicant *wpa_s_0; +static int wpa_event_sock = -1; static void start_wpa_supplicant(void); @@ -84,6 +94,108 @@ static void iface_cb(struct net_if *iface, void *user_data) ifaces[0].ifname = "wlan0"; } +static void wpa_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) +{ + int ret; + ARG_UNUSED(eloop_ctx); + ARG_UNUSED(sock_ctx); + struct wpa_supplicant_event_msg msg; + + ret = recv(sock, &msg, sizeof(msg), 0); + + if (ret < 0) { + wpa_printf(MSG_ERROR, "Failed to recv the message: %s", strerror(errno)); + return; + } + + if (ret != sizeof(msg)) { + wpa_printf(MSG_ERROR, "Recieved incomplete message: got: %d, expected:%d", + ret, sizeof(msg)); + return; + } + + if (msg.ignore_msg) { + return; + } + + wpa_printf(MSG_DEBUG, "Passing message %d to wpa_supplicant", msg.event); + + wpa_supplicant_event(msg.ctx, msg.event, msg.data); + + if (msg.data) { + os_free(msg.data); + } +} + +static int register_wpa_event_sock(void) +{ + struct sockaddr_in addr; + int ret; + + wpa_event_sock = socket(PF_INET, SOCK_DGRAM, 0); + + if (wpa_event_sock < 0) { + wpa_printf(MSG_ERROR, "Failed to initialize socket: %s", strerror(errno)); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = DUMMY_SOCKET_PORT; + + ret = bind(wpa_event_sock, (struct sockaddr *) &addr, sizeof(addr)); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Failed to bind socket: %s", strerror(errno)); + return -1; + } + + eloop_register_read_sock(wpa_event_sock, wpa_event_sock_handler, NULL, NULL); + + return 0; +} + +int send_wpa_supplicant_event(const struct wpa_supplicant_event_msg *msg) +{ + int ret; + unsigned int retry = 0; + struct sockaddr_in dst = { + .sin_addr = { + .s4_addr[0] = 127, + .s4_addr[1] = 0, + .s4_addr[2] = 0, + .s4_addr[3] = 2 + }, + .sin_family = AF_INET, + .sin_port = DUMMY_SOCKET_PORT + }; + + if (wpa_event_sock < 0) { + return -1; + } + +retry_send: + ret = sendto(wpa_event_sock, msg, sizeof(*msg), 0, (struct sockaddr *)&dst, sizeof(dst)); + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK) { + k_msleep(2); + if (retry++ < 3) { + goto retry_send; + } else { + wpa_printf(MSG_WARNING, "Dummy socket send fail (max retries): %s", + strerror(errno)); + return -1; + } + } else { + wpa_printf(MSG_WARNING, "Dummy socket send fail: %s", + strerror(errno)); + return -1; + } + } + + return 0; +} + static void start_wpa_supplicant(void) { int i; @@ -162,6 +274,8 @@ static void start_wpa_supplicant(void) wpa_s_0->conf->ap_scan= 1; } + register_wpa_event_sock(); + #ifdef CONFIG_MATCH_IFACE if (exitcode == 0) { exitcode = wpa_supplicant_init_match(global); @@ -172,10 +286,16 @@ static void start_wpa_supplicant(void) exitcode = wpa_supplicant_run(global); } + eloop_unregister_read_sock(wpa_event_sock); + wpa_supplicant_deinit(global); fst_global_deinit(); + if (wpa_event_sock) { + close(wpa_event_sock); + } + out: os_free(ifaces); #ifdef CONFIG_MATCH_IFACE diff --git a/zephyr/src/supp_main.h b/zephyr/src/supp_main.h new file mode 100644 index 0000000000..d87ee253dc --- /dev/null +++ b/zephyr/src/supp_main.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#ifndef __SUPP_MAIN_H_ +#define __SUPP_MAIN_H_ + +struct wpa_supplicant_event_msg { + /* Dummy messages to unblock select */ + bool ignore_msg; + void *ctx; + unsigned int event; + void *data; +}; +int send_wpa_supplicant_event(const struct wpa_supplicant_event_msg *msg); +#endif /* __SUPP_MAIN_H_ */ From 36fa7a5eb2fe8d08975edcf25dd37b49ffb3d5d8 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 20 Jul 2022 19:35:49 +0530 Subject: [PATCH 015/150] Clear scan results flag for failure cases This fixes unnecessary wait for scan results in case of failure scenarios. Signed-off-by: krishna T --- src/drivers/driver_zephyr.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 77c49826b4..0390b48c17 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -116,8 +116,9 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, sizeof(struct wpa_scan_res *)); if (!tmp) { + wpa_printf(MSG_ERROR, "%s: Failed to realloc scan result array\n", __func__); os_free(r); - return; + goto err; } tmp[if_ctx->scan_res2->num++] = r; @@ -125,6 +126,13 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, if_ctx->scan_res2->res = tmp; if_ctx->scan_res2_get_in_prog = more_res; + + return; +err: + /* Ignore failures except the last */ + if (!more_res) { + if_ctx->scan_res2_get_in_prog = false; + } } From 261b6083150a0f7044fca02b4f24fa66cb8e3585 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 20 Jul 2022 19:40:04 +0530 Subject: [PATCH 016/150] Fix scan results free crash Scan results are allocated by driver using k_malloc Zephyr allocator but are freed by wpa_supplicant using libc free, due to changes in metadata differences between them, we free the pointer which is 8 bytes below the actual one and cause a bus and mem fault. Copy the scan results from driver before passing to the wpa_supplicant and then let driver free them using the same k_free allocator API. We can now enable the scan results free code. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 11 ++++++++++- wpa_supplicant/events.c | 3 --- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 0390b48c17..941f4cc4d0 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -110,6 +110,7 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, bool more_res) { struct wpa_scan_res **tmp = NULL; + size_t scan_res_len = sizeof(struct wpa_scan_res) + r->ie_len + r->beacon_ie_len; tmp = os_realloc_array(if_ctx->scan_res2->res, if_ctx->scan_res2->num + 1, @@ -121,7 +122,15 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, goto err; } - tmp[if_ctx->scan_res2->num++] = r; + struct wpa_scan_res *sr = os_zalloc(scan_res_len); + if (!sr) { + wpa_printf(MSG_ERROR, "%s: Failed to alloc scan results(%d bytes)\n", __func__, scan_res_len); + goto err; + } + + os_memcpy(sr, r, scan_res_len); + + tmp[if_ctx->scan_res2->num++] = sr; if_ctx->scan_res2->res = tmp; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 3f1ec2117f..603ac33d1b 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2205,10 +2205,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpa_s->wpa_state < WPA_COMPLETED) goto scan_work_done; -#ifndef CONFIG_ZEPHYR - /* TODO : causing a crash */ wpa_scan_results_free(scan_res); -#endif if (own_request && wpa_s->scan_work) { struct wpa_radio_work *work = wpa_s->scan_work; From 32f465573ef94a52d9966e27f56540a880702606 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 26 Jul 2022 20:51:22 +0530 Subject: [PATCH 017/150] Fix uninitialized capabilities This can cause allocation failures and an unnecessary prints. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 941f4cc4d0..b13a00d1d5 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -626,6 +626,7 @@ static int wpa_drv_zep_set_key(void* priv, static int wpa_drv_zep_get_capa(void *priv, struct wpa_driver_capa *capa) { + os_memset(capa, 0, sizeof(*capa)); /* Use SME */ capa->flags = 0; capa->flags |= WPA_DRIVER_FLAGS_SME; From 96be2d5fd1f094c0718febba7222029ce0bca0a1 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 15 Aug 2022 01:49:38 +0530 Subject: [PATCH 018/150] Restructure wpa_supplicant interface handle Using first interface handle everywhere is not ideal, esp. when we add support for multi-VIF, so, query wpa_supplicant with the interface name to get the handle. The interface name itself is hard coded to "wlan0" everywhere for now. --- src/drivers/driver_zephyr.c | 12 +++++++++++- src/drivers/driver_zephyr.h | 6 +++++- wpa_supplicant/wpa_cli.c | 25 ++++++++++++++++++++++--- zephyr/src/supp_main.c | 6 ++---- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index b13a00d1d5..1c528e9241 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -484,6 +484,7 @@ static int wpa_drv_zep_authenticate(void *priv, { struct zep_drv_if_ctx *if_ctx = NULL; const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + struct wpa_bss *curr_bss; int ret = -1; if ((!priv) || (!params)) { @@ -501,8 +502,17 @@ static int wpa_drv_zep_authenticate(void *priv, if_ctx->ssid_len = params->ssid_len; + curr_bss = wpa_bss_get(if_ctx->supp_if_ctx, params->bssid, params->ssid, params->ssid_len); + + if (!curr_bss) { + wpa_printf(MSG_ERROR, "%s: Failed to get BSS", __func__); + ret = -1; + goto out; + } + ret = dev_ops->authenticate(if_ctx->dev_priv, - params); + params, + curr_bss); if (ret) { wpa_printf(MSG_ERROR, "%s: authenticate op failed\n", __func__); diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index b39c45369e..0ab1a01087 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -12,6 +12,9 @@ #include #include #include "driver.h" +#include "wpa_supplicant_i.h" +#include "bss.h" +struct wpa_bss; struct zep_wpa_supp_mbox_msg_data { void *ctx; @@ -78,7 +81,8 @@ struct zep_wpa_supp_dev_ops { const char *addr, unsigned short reason_code); int (*authenticate)(void *if_priv, - struct wpa_driver_auth_params *params); + struct wpa_driver_auth_params *params, + struct wpa_bss *curr_bss); int (*associate)(void *if_priv, struct wpa_driver_associate_params *params); int (*set_key)(void *if_priv, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index e35f0ae607..211a8eab3a 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -31,8 +31,6 @@ #define CMD_BUF_LEN 4096 -extern struct wpa_supplicant *wpa_s_0; - static const char *const wpa_cli_version = "wpa_cli v" VERSION_STR "\n" "Copyright (c) 2004-2022, Jouni Malinen and contributors"; @@ -59,7 +57,11 @@ static int wpa_cli_last_id = 0; static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR; static const char *client_socket_dir = NULL; static char *ctrl_ifname = NULL; +#ifndef CONFIG_ZEPHYR static const char *global = NULL; +#else +extern struct wpa_global *global; +#endif static const char *pid_file = NULL; static const char *action_file = NULL; static int reconnect = 0; @@ -288,8 +290,23 @@ static int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) char * repl_buf; int len = 0; /* len of the reply */ + char *ifname; + struct wpa_supplicant *wpa_s; + + if (ifname_prefix) { + ifname = ifname_prefix; + } else { + /* Default */ + ifname = "wlan0"; + } + + wpa_s = wpa_supplicant_get_iface(global, ifname); + if (!wpa_s) { + printf("Unable to find the interface: %s, quitting", ifname); + return -1; + } - repl_buf = wpa_supplicant_ctrl_iface_process (wpa_s_0, (char *) cmd, &len); + repl_buf = wpa_supplicant_ctrl_iface_process (wpa_s, (char *) cmd, &len); if (len > 0 && os_strcmp(repl_buf, "OK") != 0) printf ("Reply: %s\n", repl_buf); @@ -5024,9 +5041,11 @@ int cli_main(int argc, char *argv[]) case 'B': daemonize = 1; break; +#ifndef CONFIG_ZEPHYR case 'g': global = optarg; break; +#endif case 'G': ping_interval = atoi(optarg); break; diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 224bcf5cb1..9e38d2c8ef 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -202,7 +202,6 @@ static void start_wpa_supplicant(void) struct wpa_interface *ifaces, *iface; int iface_count, exitcode = -1; struct wpa_params params; - struct wpa_global *global; os_memset(¶ms, 0, sizeof(params)); params.wpa_debug_level = CONFIG_WPA_SUPP_DEBUG_LEVEL; @@ -269,9 +268,8 @@ static void start_wpa_supplicant(void) exitcode = -1; break; } - wpa_s_0 = wpa_s; - wpa_s_0->conf->filter_ssids = 1; - wpa_s_0->conf->ap_scan= 1; + wpa_s->conf->filter_ssids = 1; + wpa_s->conf->ap_scan= 1; } register_wpa_event_sock(); From 460d1ebf7b5880a978fcc87dc955a3e4e736e653 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 15 Aug 2022 01:49:38 +0530 Subject: [PATCH 019/150] Fix scan results crash Sometimes we are getting a unsolicited or spurious scan result from UMAC but we have already freed the scan results buffer, so, add a null check before processing scan result. --- src/drivers/driver_zephyr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 1c528e9241..953124016a 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -112,6 +112,9 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, struct wpa_scan_res **tmp = NULL; size_t scan_res_len = sizeof(struct wpa_scan_res) + r->ie_len + r->beacon_ie_len; + if (!if_ctx->scan_res2) + return; + tmp = os_realloc_array(if_ctx->scan_res2->res, if_ctx->scan_res2->num + 1, sizeof(struct wpa_scan_res *)); From 40e297d14ed7a1b8292819f6e60caf4e4fc9eda3 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 17 Aug 2022 15:20:46 +0530 Subject: [PATCH 020/150] Fix logging level This print is only for debugging, so, should use DEBUG level. Signed-off-by: Krishna T --- wpa_supplicant/wpa_supplicant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e12320bf20..1c7df4b46e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -922,7 +922,7 @@ static void dhcp_war(struct wpa_supplicant *wpa_s) memset(buf, 0xAA, len); res = l2_packet_send(wpa_s->l2, wpa_s->bssid, ntohs(0x8989), buf, len); - wpa_printf(MSG_INFO, "DHCP WAR: TX frame res=%d", res); + wpa_printf(MSG_DEBUG, "DHCP WAR: TX frame res=%d", res); os_free(buf); } From c6a11ef8a4952d589a94d48a69ea49c8717df917 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Thu, 21 Jul 2022 12:40:37 +0530 Subject: [PATCH 021/150] Implement nRF Wi-Fi management APIs These APIs will be used by nRF Wi-Fi management to interact with wpa_supplicant. Signed-off-by: Krishna T Signed-off-by: Ravi Dondaputi --- zephyr/CMakeLists.txt | 2 + zephyr/Kconfig | 4 +- zephyr/src/supp_api.c | 294 ++++++++++++++++++++++++++++++++++++++++++ zephyr/src/supp_api.h | 57 ++++++++ 4 files changed, 354 insertions(+), 3 deletions(-) create mode 100644 zephyr/src/supp_api.c create mode 100644 zephyr/src/supp_api.h diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 908cb85567..31620e90af 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -89,7 +89,9 @@ zephyr_library_sources( # Zephyr main src/supp_main.c src/utils/wpa_debug.c + src/supp_api.c ) + zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_AP ${WPA_SUPPLICANT_BASE}/ap.c ${COMMON_SRC_BASE}/ap/ap_config.c diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 6f3ef0c660..a6432e1b26 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -10,9 +10,7 @@ config WPA_SUPP depends on NET_SOCKETS depends on NET_SOCKETS_POSIX_NAMES || POSIX_API select NET_SOCKETS_PACKET - select NET_MGMT - select NET_MGMT_EVENT - select NET_MGMT_EVENT_INFO + select NET_L2_NRF_WIFI_MGMT help WPA WPA_SUPP diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c new file mode 100644 index 0000000000..fde1cf74bf --- /dev/null +++ b/zephyr/src/supp_api.c @@ -0,0 +1,294 @@ +/** + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +#include "includes.h" +#include "common.h" +#include "common/defs.h" +#include "wpa_supplicant/config.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" + +#include "zephyr_fmac_main.h" +#include "supp_main.h" +#include "supp_api.h" + +int cli_main(int, const char **); +extern struct wpa_global *global; + +enum requested_ops { + CONNECT = 0, + DISCONNECT +}; + +#define OP_STATUS_POLLING_INTERVAL 1 + +struct wpa_supp_api_ctrl { + const struct device *dev; + enum requested_ops requested_op; + int connection_timeout; + struct k_work_sync sync; +}; + +static struct wpa_supp_api_ctrl wpa_supp_api_ctrl; + +static void supp_shell_connect_status(struct k_work *work); + +static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work, + supp_shell_connect_status); + +static int send_wpa_supplicant_dummy_event(void) +{ + struct wpa_supplicant_event_msg msg = { 0 }; + + msg.ignore_msg = true; + + return send_wpa_supplicant_event(&msg); +} + + +static inline struct wpa_supplicant * get_wpa_s_handle(const struct device *dev) +{ + struct wpa_supplicant *wpa_s = wpa_supplicant_get_iface(global, dev->name); + if (!wpa_s) { + wpa_printf(MSG_ERROR, + "%s: Unable to get wpa_s handle for %s\n", __func__, dev->name); + return NULL; + } + + return wpa_s; +} + +static void supp_shell_connect_status(struct k_work *work) +{ + int i = 0, status = 0; + struct wpa_supplicant *wpa_s; + struct wpa_supp_api_ctrl *ctrl = &wpa_supp_api_ctrl; + + wpa_s = get_wpa_s_handle(ctrl->dev); + if (!wpa_s) { + status = 1; + goto out; + } + + if (ctrl->requested_op == CONNECT) { + if (wpa_s->wpa_state != WPA_COMPLETED && + (ctrl->connection_timeout == SYS_FOREVER_MS || + i++ <= ctrl->connection_timeout)) + { + k_work_reschedule(&wpa_supp_status_work, + K_SECONDS(OP_STATUS_POLLING_INTERVAL)); + return; + } + + if (i > ctrl->connection_timeout){ + if (wpa_s->wpa_state != WPA_COMPLETED){ + wpas_request_disconnection(wpa_s); + status = 1; + goto out; + } + } + } +out: + if (ctrl->requested_op == CONNECT) { + wifi_mgmt_raise_connect_result_event(net_if_lookup_by_dev(ctrl->dev), status); + } else if (ctrl->requested_op == DISCONNECT) { + /* Disconnect is a synchronous operation i.e., we are already disconnected + * we are just using this to post net_mgmt event asynchrnously. + */ + wifi_mgmt_raise_disconnect_result_event(net_if_lookup_by_dev(ctrl->dev), 0); + } +} + +int zephyr_supp_scan(const struct device *dev, scan_result_cb_t cb) +{ + const struct wifi_nrf_dev_ops *dev_ops = dev->api; + + return dev_ops->off_api.disp_scan(dev, cb); +} + + +static inline void wpa_supp_restart_status_work(void) +{ + k_work_cancel_delayable_sync(&wpa_supp_status_work, + &wpa_supp_api_ctrl.sync); + k_work_reschedule(&wpa_supp_status_work, + K_MSEC(10)); +} + +int zephyr_supp_connect(const struct device *dev, + struct wifi_connect_req_params *params) +{ + struct wpa_ssid *ssid = NULL; + bool pmf = true; + struct wpa_supplicant *wpa_s; + + wpa_s = get_wpa_s_handle(dev); + if (!wpa_s) { + return -1; + } + + wpa_supplicant_remove_all_networks(wpa_s); + + ssid = wpa_supplicant_add_network(wpa_s); + ssid->ssid = os_zalloc(sizeof(u8) * MAX_SSID_LEN); + + memcpy(ssid->ssid, params->ssid, params->ssid_length); + ssid->ssid_len = params->ssid_length; + ssid->disabled = 1; + ssid->key_mgmt = WPA_KEY_MGMT_NONE; + + wpa_s->conf->filter_ssids = 1; + wpa_s->conf->ap_scan = 1; + + if (params->psk) { + // TODO: Extend enum wifi_security_type + if (params->security == 3) { + ssid->key_mgmt = WPA_KEY_MGMT_SAE; + str_clear_free(ssid->sae_password); + ssid->sae_password = dup_binstr(params->psk, params->psk_length); + + if (ssid->sae_password == NULL) { + wpa_printf(MSG_ERROR, "%s:Failed t copy sae_password\n", + __func__); + return -1; + } + } else { + if (params->security == 2) + ssid->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; + else + ssid->key_mgmt = WPA_KEY_MGMT_PSK; + + str_clear_free(ssid->passphrase); + ssid->passphrase = dup_binstr(params->psk, params->psk_length); + + if (ssid->passphrase == NULL) { + wpa_printf(MSG_ERROR, "%s:Failed t copy passphrase\n", + __func__); + return -1; + } + } + + wpa_config_update_psk(ssid); + + if (pmf) + ssid->ieee80211w = 1; + + } + + wpa_supplicant_enable_network(wpa_s, + ssid); + + wpa_supplicant_select_network(wpa_s, + ssid); + + send_wpa_supplicant_dummy_event(); + + wpa_supp_api_ctrl.dev = dev; + wpa_supp_api_ctrl.requested_op = CONNECT; + wpa_supp_api_ctrl.connection_timeout = params->timeout; + + wpa_supp_restart_status_work(); + + return 0; +} + +int zephyr_supp_disconnect(const struct device *dev) +{ + struct wpa_supplicant *wpa_s; + + wpa_s = get_wpa_s_handle(dev); + if (!wpa_s) { + return -1; + } + wpa_supp_api_ctrl.dev = dev; + wpa_supp_api_ctrl.requested_op = DISCONNECT; + wpas_request_disconnection(wpa_s); + + wpa_supp_restart_status_work(); + + return 0; +} + + +static inline enum wifi_frequency_bands wpas_band_to_zephyr(enum wpa_radio_work_band band) +{ + switch(band) { + case BAND_2_4_GHZ: + return WIFI_FREQ_BAND_2_4_GHZ; + case BAND_5_GHZ: + return WIFI_FREQ_BAND_5_GHZ; + default: + return WIFI_FREQ_BAND_UNKNOWN; + } +} + +static inline enum wifi_security_type wpas_key_mgmt_to_zephyr(int key_mgmt) +{ + switch(key_mgmt) { + case WPA_KEY_MGMT_NONE: + return WIFI_SECURITY_TYPE_NONE; + case WPA_KEY_MGMT_PSK: + return WIFI_SECURITY_TYPE_PSK; + case WPA_KEY_MGMT_PSK_SHA256: + return WIFI_SECURITY_TYPE_PSK_SHA256; + case WPA_KEY_MGMT_SAE: + return WIFI_SECURITY_TYPE_SAE; + default: + return WIFI_SECURITY_TYPE_UNKNOWN; + } +} + + +int zephyr_supp_status(const struct device *dev, + struct wifi_iface_status *status) +{ + struct wpa_supplicant *wpa_s; + + wpa_s = get_wpa_s_handle(dev); + if (!wpa_s) { + return -1; + } + + status->state = wpa_s->wpa_state; /* 1-1 Mapping */ + + if (wpa_s->wpa_state >= WPA_ASSOCIATED) { + struct wpa_ssid *ssid = wpa_s->current_ssid; + u8 channel; + + os_memcpy(status->bssid, wpa_s->bssid, WIFI_MAC_ADDR_LEN); + status->band = wpas_band_to_zephyr(wpas_freq_to_band(wpa_s->assoc_freq)); + status->security = wpas_key_mgmt_to_zephyr(ssid->key_mgmt); + status->mfp = ssid->ieee80211w; /* Same mapping */ + ieee80211_freq_to_chan(wpa_s->assoc_freq, &channel); + status->channel = channel; + + if (ssid) { + u8 *_ssid = ssid->ssid; + size_t ssid_len = ssid->ssid_len; + u8 ssid_buf[SSID_MAX_LEN] = {0}; + + if (ssid_len == 0) { + int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); + + if (_res < 0) + ssid_len = 0; + else + ssid_len = _res; + _ssid = ssid_buf; + } + os_memcpy(status->ssid, _ssid, ssid_len); + status->ssid_len = ssid_len; + status->iface_mode = ssid->mode; + /* TODO: Derive this based on association IEs */ + status->link_mode = WIFI_6; + } + } + + return 0; +} diff --git a/zephyr/src/supp_api.h b/zephyr/src/supp_api.h new file mode 100644 index 0000000000..fe5dc31987 --- /dev/null +++ b/zephyr/src/supp_api.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + * + */ + +#ifndef ZEPHYR_SUPP_MGMT_H +#define ZEPHYR_SUPP_MGMT_H + +#include + +#define MAX_SSID_LEN 32 +#define MAC_ADDR_LEN 6 + +/** + * @brief Request a scan + * + * @param iface_name: Wi-Fi interface name to use + * @param scan_result_cb_t: Application specific callback when the scan + * attempt is completed. + * + * @return: 0 for OK; -1 for ERROR + */ +int zephyr_supp_scan(const struct device *dev, scan_result_cb_t cb); + +/** + * @brief Request a connection + * + * @param iface_name: Wi-Fi interface name to use + * @param params: Connection details + * + * @return: 0 for OK; -1 for ERROR + */ +int zephyr_supp_connect(const struct device *dev, + struct wifi_connect_req_params *params); +/** + * @brief Forces station to disconnect and stops any subsequent scan + * or connection attempts + * + * @param iface_name: Wi-Fi interface name to use + * + * @return: 0 for OK; -1 for ERROR + */ +int zephyr_supp_disconnect(const struct device *dev); + +/** + * @brief + * + * @param iface_name: Wi-Fi interface name to use + * @param wifi_iface_status: Status structure to fill + * + * @return: 0 for OK; -1 for ERROR + */ +int zephyr_supp_status(const struct device *dev, + struct wifi_iface_status *status); +#endif /* ZEPHYR_SUPP_MGMT_H */ From b50bcfa02c29c3483c8802bc4b9967c9ba086789 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 17 Aug 2022 02:21:53 +0530 Subject: [PATCH 022/150] Migrate wpa_cli from NCS/sdk-nrf This is now purely an internal utility, so, moved from sdk-nrf to here as it works with wpa_supplicant. Signed-off-by: Krishna T --- zephyr/CMakeLists.txt | 4 + zephyr/Kconfig | 4 + zephyr/src/wpa_cli.c | 229 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 zephyr/src/wpa_cli.c diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 31620e90af..b8bfe6d15a 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -92,6 +92,10 @@ zephyr_library_sources( src/supp_api.c ) +zephyr_library_sources_ifdef(CONFIG_WPA_CLI + src/wpa_cli.c +) + zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_AP ${WPA_SUPPLICANT_BASE}/ap.c ${COMMON_SRC_BASE}/ap/ap_config.c diff --git a/zephyr/Kconfig b/zephyr/Kconfig index a6432e1b26..458b98e097 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -46,6 +46,10 @@ config WPA_SUPP_P2P select WPA_SUPP_AP select WPA_SUPP_WPS +config WPA_CLI + bool "CLI support for wpa_supplicant" + default n + module = WPA_SUPP module-str = WPA supplicant source "subsys/logging/Kconfig.template.log_config" diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c new file mode 100644 index 0000000000..6e67176d46 --- /dev/null +++ b/zephyr/src/wpa_cli.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* @file + * @brief Wi-Fi shell sample + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_WPA_SUPP +#include +#include +#include +#endif /* CONFIG_WPA_SUPP */ + +static struct { + const struct shell *shell; + + union { + struct { + uint8_t connecting : 1; + uint8_t disconnecting : 1; + uint8_t _unused : 6; + }; + uint8_t all; + }; +} context; + +static uint32_t scan_result; + +int cli_main(int argc, const char **argv); + +extern struct wpa_global *global; + +/* TODO: Take this an input from shell */ +const char if_name[] = "wlan0"; + +struct wpa_ssid *ssid_0; + +#define MAX_SSID_LEN 32 + + +static void scan_result_cb(struct net_if *iface, + int status, + struct wifi_scan_result *entry) +{ + if (!iface) { + return; + } + + if (!entry) { + if (status) { + shell_fprintf(context.shell, + SHELL_WARNING, + "Scan request failed (%d)\n", + status); + } else { + shell_fprintf(context.shell, + SHELL_NORMAL, + "Scan request done\n"); + } + + return; + } + + scan_result++; + + if (scan_result == 1U) { + shell_fprintf(context.shell, + SHELL_NORMAL, + "\n%-4s | %-32s %-5s | %-4s | %-4s | %-5s\n", "Num", "SSID", + "(len)", "Chan", "RSSI", "Sec"); + } + + shell_fprintf(context.shell, + SHELL_NORMAL, + "%-4d | %-32s %-5u | %-4u | %-4d | %-5s\n", + scan_result, + entry->ssid, + entry->ssid_length, + entry->channel, + entry->rssi, + (entry->security == WIFI_SECURITY_TYPE_PSK ? "WPA/WPA2" : "Open")); +} + + +static int cmd_wifi_scan(const struct shell *shell, + size_t argc, + const char *argv[]) +{ + struct net_if *iface = net_if_get_default(); + const struct device *dev = net_if_get_device(iface); + const struct wifi_nrf_dev_ops *dev_ops = dev->api; + + context.shell = shell; + + return dev_ops->off_api.disp_scan(dev, + scan_result_cb); +} + + +#ifdef CONFIG_WPA_SUPP +static int cmd_supplicant(const struct shell *shell, + size_t argc, + const char *argv[]) +{ + struct wpa_supplicant *wpa_s = wpa_supplicant_get_iface(global, if_name); + + if (!wpa_s) { + shell_fprintf(shell, + SHELL_ERROR, + "%s: wpa_supplicant is not initialized, dropping connect\n", + __func__); + return -1; + } + + return cli_main(argc, + argv); +} +#endif /* CONFIG_WPA_SUPP */ + + +SHELL_STATIC_SUBCMD_SET_CREATE( + wpa_cli_cmds, + SHELL_CMD(scan, + NULL, + "Scan AP", + cmd_wifi_scan), +#ifdef CONFIG_WPA_SUPP + SHELL_CMD(add_network, + NULL, + "\"Add Network network id/number\"", + cmd_supplicant), + SHELL_CMD(set_network, + NULL, + "\"Set Network params\"", + cmd_supplicant), + SHELL_CMD(set, + NULL, + "\"Set Global params\"", + cmd_supplicant), + SHELL_CMD(get, + NULL, "\"Get Global params\"", + cmd_supplicant), + SHELL_CMD(enable_network, + NULL, + "\"Enable Network\"", + cmd_supplicant), + SHELL_CMD(remove_network, + NULL, + "\"Remove Network\"", + cmd_supplicant), + SHELL_CMD(get_network, + NULL, + "\"Get Network\"", + cmd_supplicant), + SHELL_CMD(select_network, + NULL, + "\"Select Network which will be enabled; rest of the networks will be disabled\"", + cmd_supplicant), + SHELL_CMD(disable_network, + NULL, + "\"\"", + cmd_supplicant), + SHELL_CMD(disconnect, + NULL, + "\"\"", + cmd_supplicant), + SHELL_CMD(reassociate, + NULL, + "\"\"", + cmd_supplicant), + SHELL_CMD(status, + NULL, + "\"Get client status\"", + cmd_supplicant), + SHELL_CMD(bssid, + NULL, + "\"Associate with this BSSID\"", + cmd_supplicant), + SHELL_CMD(sta_autoconnect, + NULL, + "\"\"", + cmd_supplicant), + SHELL_CMD(signal_poll, + NULL, + "\"\"", + cmd_supplicant), +#endif /* CONFIG_WPA_SUPP */ + SHELL_SUBCMD_SET_END); + +/* Persisting with "wpa_cli" naming for compatibility with Wi-Fi + * certification applications and scripts. + */ +SHELL_CMD_REGISTER(wpa_cli, + &wpa_cli_cmds, + "wpa_supplicant commands (only for internal use)", + NULL); + + +static int wifi_shell_init(const struct device *unused) +{ + ARG_UNUSED(unused); + + context.shell = NULL; + context.all = 0U; + scan_result = 0U; + + return 0; +} + + +SYS_INIT(wifi_shell_init, + APPLICATION, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From 1508f2ba60f8f606a32daaa48914c3376df45132 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 29 Aug 2022 21:39:34 +0530 Subject: [PATCH 023/150] Remove display scan Now that display scan is natively supported using wifi_mgmt, remove it from WPA supplicant API and wpa_cli. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 10 +------ zephyr/src/supp_api.h | 11 -------- zephyr/src/wpa_cli.c | 65 ------------------------------------------- 3 files changed, 1 insertion(+), 85 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index fde1cf74bf..0f2ae7db5f 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -14,7 +14,6 @@ #include "wpa_supplicant_i.h" #include "driver_i.h" -#include "zephyr_fmac_main.h" #include "supp_main.h" #include "supp_api.h" @@ -105,14 +104,6 @@ static void supp_shell_connect_status(struct k_work *work) } } -int zephyr_supp_scan(const struct device *dev, scan_result_cb_t cb) -{ - const struct wifi_nrf_dev_ops *dev_ops = dev->api; - - return dev_ops->off_api.disp_scan(dev, cb); -} - - static inline void wpa_supp_restart_status_work(void) { k_work_cancel_delayable_sync(&wpa_supp_status_work, @@ -121,6 +112,7 @@ static inline void wpa_supp_restart_status_work(void) K_MSEC(10)); } + int zephyr_supp_connect(const struct device *dev, struct wifi_connect_req_params *params) { diff --git a/zephyr/src/supp_api.h b/zephyr/src/supp_api.h index fe5dc31987..48c6c22bb7 100644 --- a/zephyr/src/supp_api.h +++ b/zephyr/src/supp_api.h @@ -13,17 +13,6 @@ #define MAX_SSID_LEN 32 #define MAC_ADDR_LEN 6 -/** - * @brief Request a scan - * - * @param iface_name: Wi-Fi interface name to use - * @param scan_result_cb_t: Application specific callback when the scan - * attempt is completed. - * - * @return: 0 for OK; -1 for ERROR - */ -int zephyr_supp_scan(const struct device *dev, scan_result_cb_t cb); - /** * @brief Request a connection * diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index 6e67176d46..0c5dbaf291 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -19,7 +19,6 @@ #include #include #include -#include #ifdef CONFIG_WPA_SUPP #include @@ -40,7 +39,6 @@ static struct { }; } context; -static uint32_t scan_result; int cli_main(int argc, const char **argv); @@ -49,69 +47,6 @@ extern struct wpa_global *global; /* TODO: Take this an input from shell */ const char if_name[] = "wlan0"; -struct wpa_ssid *ssid_0; - -#define MAX_SSID_LEN 32 - - -static void scan_result_cb(struct net_if *iface, - int status, - struct wifi_scan_result *entry) -{ - if (!iface) { - return; - } - - if (!entry) { - if (status) { - shell_fprintf(context.shell, - SHELL_WARNING, - "Scan request failed (%d)\n", - status); - } else { - shell_fprintf(context.shell, - SHELL_NORMAL, - "Scan request done\n"); - } - - return; - } - - scan_result++; - - if (scan_result == 1U) { - shell_fprintf(context.shell, - SHELL_NORMAL, - "\n%-4s | %-32s %-5s | %-4s | %-4s | %-5s\n", "Num", "SSID", - "(len)", "Chan", "RSSI", "Sec"); - } - - shell_fprintf(context.shell, - SHELL_NORMAL, - "%-4d | %-32s %-5u | %-4u | %-4d | %-5s\n", - scan_result, - entry->ssid, - entry->ssid_length, - entry->channel, - entry->rssi, - (entry->security == WIFI_SECURITY_TYPE_PSK ? "WPA/WPA2" : "Open")); -} - - -static int cmd_wifi_scan(const struct shell *shell, - size_t argc, - const char *argv[]) -{ - struct net_if *iface = net_if_get_default(); - const struct device *dev = net_if_get_device(iface); - const struct wifi_nrf_dev_ops *dev_ops = dev->api; - - context.shell = shell; - - return dev_ops->off_api.disp_scan(dev, - scan_result_cb); -} - #ifdef CONFIG_WPA_SUPP static int cmd_supplicant(const struct shell *shell, From 449aad825f5d84916e2386d8caedce5d97f21079 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 31 Aug 2022 19:01:35 +0530 Subject: [PATCH 024/150] Use UNIX sockets instead of networking sockets Using UDP sockets need an interface with properly configured IP address and then either IPv4/IPv6 enabled, UNIX socket don't need any of those and work perfectly well for IPC. This solves two bugs: * Matter doesn't enable IPv4, so, the events stop working, as the code doesn't support IPv6 sockets and also doesn't protect with IPv4 define. * Wi-Fi sample assigns IP address in the `prj.conf` but if an application doesn't do that, then socket send fails. Signed-off-by: Krishna T --- zephyr/Kconfig | 1 + zephyr/src/supp_main.c | 46 +++++++++--------------------------------- 2 files changed, 11 insertions(+), 36 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 458b98e097..b6cf1f9fe5 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -10,6 +10,7 @@ config WPA_SUPP depends on NET_SOCKETS depends on NET_SOCKETS_POSIX_NAMES || POSIX_API select NET_SOCKETS_PACKET + select NET_SOCKETPAIR select NET_L2_NRF_WIFI_MGMT help WPA WPA_SUPP diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 9e38d2c8ef..6441279466 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -30,12 +30,9 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "supp_main.h" - -#define DUMMY_SOCKET_PORT 9999 - struct wpa_global *global; -static int wpa_event_sock = -1; +static int wpa_event_sockpair[2]; static void start_wpa_supplicant(void); @@ -129,28 +126,16 @@ static void wpa_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) static int register_wpa_event_sock(void) { - struct sockaddr_in addr; int ret; - wpa_event_sock = socket(PF_INET, SOCK_DGRAM, 0); + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, wpa_event_sockpair); - if (wpa_event_sock < 0) { + if (ret != 0) { wpa_printf(MSG_ERROR, "Failed to initialize socket: %s", strerror(errno)); return -1; } - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_family = AF_INET; - addr.sin_port = DUMMY_SOCKET_PORT; - - ret = bind(wpa_event_sock, (struct sockaddr *) &addr, sizeof(addr)); - if (ret < 0) { - wpa_printf(MSG_ERROR, "Failed to bind socket: %s", strerror(errno)); - return -1; - } - - eloop_register_read_sock(wpa_event_sock, wpa_event_sock_handler, NULL, NULL); + eloop_register_read_sock(wpa_event_sockpair[0], wpa_event_sock_handler, NULL, NULL); return 0; } @@ -159,23 +144,13 @@ int send_wpa_supplicant_event(const struct wpa_supplicant_event_msg *msg) { int ret; unsigned int retry = 0; - struct sockaddr_in dst = { - .sin_addr = { - .s4_addr[0] = 127, - .s4_addr[1] = 0, - .s4_addr[2] = 0, - .s4_addr[3] = 2 - }, - .sin_family = AF_INET, - .sin_port = DUMMY_SOCKET_PORT - }; - - if (wpa_event_sock < 0) { + + if (wpa_event_sockpair[1] < 0) { return -1; } retry_send: - ret = sendto(wpa_event_sock, msg, sizeof(*msg), 0, (struct sockaddr *)&dst, sizeof(dst)); + ret = send(wpa_event_sockpair[1], msg, sizeof(*msg), 0); if (ret < 0) { if (errno == EINTR || errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK) { k_msleep(2); @@ -284,15 +259,14 @@ static void start_wpa_supplicant(void) exitcode = wpa_supplicant_run(global); } - eloop_unregister_read_sock(wpa_event_sock); + eloop_unregister_read_sock(wpa_event_sockpair[0]); wpa_supplicant_deinit(global); fst_global_deinit(); - if (wpa_event_sock) { - close(wpa_event_sock); - } + close(wpa_event_sockpair[0]); + close(wpa_event_sockpair[1]); out: os_free(ifaces); From 8c5ed9a2d35543bed588018353f7fd2106c0d2ae Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 31 Aug 2022 15:35:57 +0530 Subject: [PATCH 025/150] Restart DHCP for every association After every successful association, restart DHCP to get a fresh lease. For the initial association this avoid delay due to DHCP exponential retries, and also handles the case where interface has changed IP subnet. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 953124016a..fb692fff1d 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -709,9 +709,7 @@ static int wpa_drv_zep_set_supp_port(void *priv, #ifdef CONFIG_NET_DHCPV4 if (authorized) { - net_dhcpv4_stop(iface); - k_msleep(500); - net_dhcpv4_start(iface); + net_dhcpv4_restart(iface); } #endif From 5c474aa047cbf274f1eefa5b2cc779a5d0368cad Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 5 Sep 2022 13:19:31 +0530 Subject: [PATCH 026/150] Fix WPA CLI build With recent changes, WPA CLI build is broken. Signed-off-by: Krishna T --- zephyr/CMakeLists.txt | 2 +- zephyr/src/wpa_cli.c | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b8bfe6d15a..1b1add1ebd 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -85,7 +85,7 @@ zephyr_library_sources( ${WPA_SUPPLICANT_BASE}/robust_av.c ${WPA_SUPPLICANT_BASE}/ctrl_iface.c ${WPA_SUPPLICANT_BASE}/ctrl_iface_udp.c - ${WPA_SUPPLICANT_BASE}/wpa_cli.c + ${WPA_SUPPLICANT_BASE}/wpa_cli.c # Zephyr main src/supp_main.c src/utils/wpa_debug.c diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index 0c5dbaf291..e7f1f73e06 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -20,11 +20,9 @@ #include #include -#ifdef CONFIG_WPA_SUPP #include #include #include -#endif /* CONFIG_WPA_SUPP */ static struct { const struct shell *shell; @@ -48,7 +46,6 @@ extern struct wpa_global *global; const char if_name[] = "wlan0"; -#ifdef CONFIG_WPA_SUPP static int cmd_supplicant(const struct shell *shell, size_t argc, const char *argv[]) @@ -66,16 +63,9 @@ static int cmd_supplicant(const struct shell *shell, return cli_main(argc, argv); } -#endif /* CONFIG_WPA_SUPP */ - SHELL_STATIC_SUBCMD_SET_CREATE( wpa_cli_cmds, - SHELL_CMD(scan, - NULL, - "Scan AP", - cmd_wifi_scan), -#ifdef CONFIG_WPA_SUPP SHELL_CMD(add_network, NULL, "\"Add Network network id/number\"", @@ -135,7 +125,6 @@ SHELL_STATIC_SUBCMD_SET_CREATE( NULL, "\"\"", cmd_supplicant), -#endif /* CONFIG_WPA_SUPP */ SHELL_SUBCMD_SET_END); /* Persisting with "wpa_cli" naming for compatibility with Wi-Fi @@ -153,7 +142,6 @@ static int wifi_shell_init(const struct device *unused) context.shell = NULL; context.all = 0U; - scan_result = 0U; return 0; } From 13ff9dafab2b51fa5bf13d11abc2a5075a9b311f Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 5 Sep 2022 13:20:51 +0530 Subject: [PATCH 027/150] Enable sub-menu only if menu is selected All options depend on WPA_SUPP, so, add a check. Signed-off-by: Krishna T --- zephyr/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index b6cf1f9fe5..c1eef4536b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -15,6 +15,8 @@ config WPA_SUPP help WPA WPA_SUPP +if WPA_SUPP + config WPA_SUPP_THREAD_STACK_SIZE int "Stack size for wpa_supplicant thread" default 8192 @@ -68,3 +70,4 @@ config WPA_SUPP_DEBUG_LEVEL available levels and functions for emitting the messages. Note that runtime filtering can also be configured in addition to the compile-time filtering. +endif From 76bd09efa5424a4039a234a7244fe32fa495d9cf Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 5 Sep 2022 13:22:21 +0530 Subject: [PATCH 028/150] Fix the WPA_SUPP help Don't use the same acronym in help. Signed-off-by: Krishna T --- zephyr/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index c1eef4536b..2430a6eec5 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -6,14 +6,14 @@ # config WPA_SUPP - bool "WPA WPA_SUPP" + bool "WPA supplicant support" depends on NET_SOCKETS depends on NET_SOCKETS_POSIX_NAMES || POSIX_API select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_NRF_WIFI_MGMT help - WPA WPA_SUPP + WPA supplicant implements 802.1X related functions. if WPA_SUPP From 106aea4cc93e0741c08c8d83db06b525d9be7fd9 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 8 Sep 2022 19:09:12 +0530 Subject: [PATCH 029/150] COV-177625: Fix double free The scan result is always freed in the driver for both success and failure cases, so, no need for wpa_supplicant to free in failure case. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index fb692fff1d..34c1bf1936 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -121,7 +121,6 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, if (!tmp) { wpa_printf(MSG_ERROR, "%s: Failed to realloc scan result array\n", __func__); - os_free(r); goto err; } From 8d34988f485c6547067ad318699bbc590dd3bfbc Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 8 Sep 2022 19:28:17 +0530 Subject: [PATCH 030/150] COV-176030: Fix resource leak If a second configuration is defined but failed to read, then the first configuration is leaked. Signed-off-by: Krishna T --- wpa_supplicant/wpa_supplicant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 1c7df4b46e..54f232f318 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1178,6 +1178,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration file '%s' - exiting", wpa_s->confanother); + os_free(conf); return -1; } From 7bcefa72d03e0161d82073db550834de0ba41dc9 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 8 Sep 2022 20:41:36 +0530 Subject: [PATCH 031/150] COV-175739: Fix use after free Move the print before freeing l2. Signed-off-by: Krishna T --- src/l2_packet/l2_packet_zephyr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index 7469c6dabe..2bd48ac8c0 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -148,9 +148,9 @@ l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol, l2->ifindex = net_if_get_by_iface(l2->iface); if (!l2->ifindex) { - os_free(l2); wpa_printf(MSG_ERROR, "Cannot get interface index for: %s\n", l2->ifname); + os_free(l2); return NULL; } From fed22d420c8aa663e7903007c722c5e038fe904d Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 8 Sep 2022 21:13:48 +0530 Subject: [PATCH 032/150] COV-175332: Fix memory leak Free ifname before returning. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 6441279466..b127f59e16 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -89,6 +89,8 @@ static void iface_cb(struct net_if *iface, void *user_data) /* TODO : make this user configurable*/ ifaces[0].ifname = "wlan0"; + + os_free(ifname); } static void wpa_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) From f0031e9bd6786cfd52a95cc5ca78c11dcf77fc81 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 8 Sep 2022 21:24:14 +0530 Subject: [PATCH 033/150] COV-175218: Fix L2 handle leak Close the socket in failure cases. Signed-off-by: Krishna T --- src/l2_packet/l2_packet_zephyr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index 2bd48ac8c0..d7d5ce5a89 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -190,6 +190,8 @@ l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol, return l2; fail: + if (l2->fd >= 0) + close(l2->fd); os_free(l2); wpa_printf(MSG_ERROR, "Failed to create l2_packet: %d\n", ret); return NULL; From 9d2d405d0f4bf0b9d83f82f1ce7d11d90ecfe12a Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 8 Sep 2022 22:13:26 +0530 Subject: [PATCH 034/150] Use 64bit data type to store time Depending on OS and Compiler, time can be 32bit/64bit, so, use 64bit to store to accommodate both. This fixes below coverity warnings * COV-176118 * COV-176071 * COV-175162 Signed-off-by: Krishna T --- src/utils/os.h | 2 +- wpa_supplicant/ctrl_iface.c | 2 +- wpa_supplicant/events.c | 4 ++-- wpa_supplicant/p2p_supplicant.c | 6 +++--- wpa_supplicant/wpa_supplicant.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/utils/os.h b/src/utils/os.h index dd611f0538..de1ac943c5 100644 --- a/src/utils/os.h +++ b/src/utils/os.h @@ -9,7 +9,7 @@ #ifndef OS_H #define OS_H -typedef long os_time_t; +typedef uint64_t os_time_t; /** * os_sleep - Sleep (sec, usec) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2688eb2ba0..665df690b2 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8612,7 +8612,7 @@ static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s, int ret; os_reltime_sub(&now, &work->time, &diff); - ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n", + ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%lld.%06lld\n", work->type, work->wpa_s->ifname, work->freq, work->started, diff.sec, diff.usec); if (os_snprintf_error(end - pos, ret)) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 603ac33d1b..b1b243b00d 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -5002,7 +5002,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, os_get_reltime(&wpa_s->scan_start_time); os_reltime_sub(&wpa_s->scan_start_time, &wpa_s->scan_trigger_time, &diff); - wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds", + wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %lld.%06lld seconds", diff.sec, diff.usec); wpa_s->own_scan_requested = 0; wpa_s->own_scan_running = 1; @@ -5037,7 +5037,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, os_reltime_sub(&now, &wpa_s->scan_start_time, &diff); wpa_s->scan_start_time.sec = 0; wpa_s->scan_start_time.usec = 0; - wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds", + wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %lld.%06lld seconds", diff.sec, diff.usec); } if (wpa_supplicant_event_scan_results(wpa_s, data)) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index a996b436b4..90d0f81fda 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -5210,7 +5210,7 @@ static int wpas_p2p_peer_go(struct wpa_supplicant *wpa_s, updated = os_reltime_before(&wpa_s->p2p_auto_started, &bss->last_update); wpa_printf(MSG_DEBUG, "P2P: Current BSS entry for peer updated at " - "%ld.%06ld (%supdated in last scan)", + "%lld.%06lld (%supdated in last scan)", bss->last_update.sec, bss->last_update.usec, updated ? "": "not "); @@ -5986,7 +5986,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, if (auto_join) { os_get_reltime(&wpa_s->p2p_auto_started); wpa_printf(MSG_DEBUG, "P2P: Auto join started at " - "%ld.%06ld", + "%lld.%06lld", wpa_s->p2p_auto_started.sec, wpa_s->p2p_auto_started.usec); } @@ -7271,7 +7271,7 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpas_p2p_stop_find(wpa_s); wpa_s->p2p_join_scan_count = 0; os_get_reltime(&wpa_s->p2p_auto_started); - wpa_printf(MSG_DEBUG, "P2P: Auto PD started at %ld.%06ld", + wpa_printf(MSG_DEBUG, "P2P: Auto PD started at %lld.%06lld", wpa_s->p2p_auto_started.sec, wpa_s->p2p_auto_started.usec); wpas_p2p_join_scan(wpa_s, NULL); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 54f232f318..5b8ec2f705 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6246,7 +6246,7 @@ static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx) os_get_reltime(&now); os_reltime_sub(&now, &work->time, &diff); wpa_dbg(wpa_s, MSG_DEBUG, - "Starting radio work '%s'@%p after %ld.%06ld second wait", + "Starting radio work '%s'@%p after %lld.%06lld second wait", work->type, work, diff.sec, diff.usec); work->started = 1; work->time = now; @@ -6444,7 +6444,7 @@ void radio_work_done(struct wpa_radio_work *work) os_get_reltime(&now); os_reltime_sub(&now, &work->time, &diff); - wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds", + wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %lld.%06lld seconds", work->type, work, started ? "done" : "canceled", diff.sec, diff.usec); radio_work_free(work); From 47399f055431513b5dfcd9d1fd1ec5dc5c96a252 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 9 Sep 2022 13:19:53 +0530 Subject: [PATCH 035/150] Add a null check for ifname ifname can be null if memory allocation fails. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index b127f59e16..e46d335404 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -84,8 +84,8 @@ static void iface_cb(struct net_if *iface, void *user_data) wpa_printf( MSG_INFO, "iface_cb: iface %s ifindex %d %02x:%02x:%02x:%02x:%02x:%02x", - ifname, ifindex, own_addr[0], own_addr[1], own_addr[2], - own_addr[3], own_addr[4], own_addr[5]); + ifname ? ifname: "Unknown", ifindex, own_addr[0], own_addr[1], + own_addr[2], own_addr[3], own_addr[4], own_addr[5]); /* TODO : make this user configurable*/ ifaces[0].ifname = "wlan0"; From e41edadff8c585695d26a237d83c66b127f5ff20 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Fri, 2 Sep 2022 16:07:15 +0530 Subject: [PATCH 036/150] Support signal polling Add support to handle signal polling requests from application. Signed-off-by: Ravi Dondaputi --- src/drivers/driver_zephyr.c | 38 +++++++++++++++++++++++++++++++++++++ src/drivers/driver_zephyr.h | 2 ++ zephyr/src/supp_api.c | 10 ++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 34c1bf1936..45a2db3079 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -716,6 +716,43 @@ static int wpa_drv_zep_set_supp_port(void *priv, } +static int wpa_drv_zep_signal_poll(void *priv, struct wpa_signal_info *si) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if (!priv) { + wpa_printf(MSG_ERROR, "%s: Invalid handle\n", __func__); + goto out; + } + + if (!si) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + dev_ops = if_ctx->dev_ctx->config; + + os_memset(si, 0, sizeof(*si)); + + if (dev_ops && dev_ops->signal_poll) { + ret = dev_ops->signal_poll(if_ctx->dev_priv, si, if_ctx->bssid); + if (ret) { + wpa_printf(MSG_ERROR, "%s: Signal polling failed: %d\n", __func__, ret); + goto out; + } + } else { + wpa_printf(MSG_ERROR, "%s: Signal polling not supported\n", __func__); + goto out; + } + +out: + return ret; +} + + const struct wpa_driver_ops wpa_driver_zep_ops = { .name = "zephyr", .desc = "Zephyr wpa_supplicant driver", @@ -734,4 +771,5 @@ const struct wpa_driver_ops wpa_driver_zep_ops = { .set_supp_port = wpa_drv_zep_set_supp_port, .deauthenticate = wpa_drv_zep_deauthenticate, .set_key = wpa_drv_zep_set_key, + .signal_poll = wpa_drv_zep_signal_poll, }; diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 0ab1a01087..9b19e5cf52 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -98,6 +98,8 @@ struct zep_wpa_supp_dev_ops { int (*set_supp_port)(void *if_priv, int authorized, char *bssid); + int (*signal_poll)(void *if_priv, struct wpa_signal_info *si, + unsigned char *bssid); }; #endif /* DRIVER_ZEPHYR_H */ diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 0f2ae7db5f..71a5e3091f 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -241,6 +241,8 @@ int zephyr_supp_status(const struct device *dev, struct wifi_iface_status *status) { struct wpa_supplicant *wpa_s; + struct wpa_signal_info si; + int ret = -1; wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { @@ -280,6 +282,14 @@ int zephyr_supp_status(const struct device *dev, /* TODO: Derive this based on association IEs */ status->link_mode = WIFI_6; } + ret = wpa_drv_signal_poll(wpa_s, &si); + if (!ret) { + status->rssi = si.current_signal; + } else { + wpa_printf(MSG_ERROR, "%s:Failed to read RSSI\n", + __func__); + status->rssi = -WPA_INVALID_NOISE; + } } return 0; From 4848da7c1a45aee06f8b3475daf1ea37f5684060 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 19 Sep 2022 17:45:05 +0530 Subject: [PATCH 037/150] Wait for WPA supplicant initialization Before processing wifi_mgmt APIs check and wait for WPA supplicant initialization. This solves bus fault when wifi_mgmt API is called too early (before WPA supplicant populates "global" pointer). This is done using a binary semaphore with initial value as 1. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 13 ++++++++++++- zephyr/src/supp_main.c | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 71a5e3091f..5677e41799 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -18,6 +18,7 @@ #include "supp_api.h" int cli_main(int, const char **); +extern struct k_sem wpa_supplicant_ready_sem; extern struct wpa_global *global; enum requested_ops { @@ -53,7 +54,17 @@ static int send_wpa_supplicant_dummy_event(void) static inline struct wpa_supplicant * get_wpa_s_handle(const struct device *dev) { - struct wpa_supplicant *wpa_s = wpa_supplicant_get_iface(global, dev->name); + struct wpa_supplicant *wpa_s = NULL; + int ret = k_sem_take(&wpa_supplicant_ready_sem, K_SECONDS(2)); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: WPA supplicant not ready: %d", __func__, ret); + return NULL; + } + + k_sem_give(&wpa_supplicant_ready_sem); + + wpa_s = wpa_supplicant_get_iface(global, dev->name); if (!wpa_s) { wpa_printf(MSG_ERROR, "%s: Unable to get wpa_s handle for %s\n", __func__, dev->name); diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index e46d335404..3b54eac5a5 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -30,6 +30,8 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "supp_main.h" +K_SEM_DEFINE(wpa_supplicant_ready_sem, 0, 1); + struct wpa_global *global; static int wpa_event_sockpair[2]; @@ -258,6 +260,7 @@ static void start_wpa_supplicant(void) #endif /* CONFIG_MATCH_IFACE */ if (exitcode == 0) { + k_sem_give(&wpa_supplicant_ready_sem); exitcode = wpa_supplicant_run(global); } From 74352f6ebf87c50039a646c1f2c7fbfaaeb73805 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 26 Sep 2022 00:06:59 +0530 Subject: [PATCH 038/150] Fix both API and Shell usage When both API and Shell commands are invoked, crashes were observed due to missing locking and using stack memory to pass down to the driver. Use a lock to serialize all APIs, both when invoked from using API directly or viz shell and also calling multiple APIs, and for status use the dynamic memory to avoid passing stack memory when there is concurrent access. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 5677e41799..c4f9a5cbdf 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -28,6 +28,9 @@ enum requested_ops { #define OP_STATUS_POLLING_INTERVAL 1 +K_MUTEX_DEFINE(wpa_supplicant_mutex); + + struct wpa_supp_api_ctrl { const struct device *dev; enum requested_ops requested_op; @@ -80,6 +83,8 @@ static void supp_shell_connect_status(struct k_work *work) struct wpa_supplicant *wpa_s; struct wpa_supp_api_ctrl *ctrl = &wpa_supp_api_ctrl; + k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); + wpa_s = get_wpa_s_handle(ctrl->dev); if (!wpa_s) { status = 1; @@ -93,6 +98,7 @@ static void supp_shell_connect_status(struct k_work *work) { k_work_reschedule(&wpa_supp_status_work, K_SECONDS(OP_STATUS_POLLING_INTERVAL)); + k_mutex_unlock(&wpa_supplicant_mutex); return; } @@ -113,6 +119,8 @@ static void supp_shell_connect_status(struct k_work *work) */ wifi_mgmt_raise_disconnect_result_event(net_if_lookup_by_dev(ctrl->dev), 0); } + + k_mutex_unlock(&wpa_supplicant_mutex); } static inline void wpa_supp_restart_status_work(void) @@ -131,6 +139,8 @@ int zephyr_supp_connect(const struct device *dev, bool pmf = true; struct wpa_supplicant *wpa_s; + k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); + wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { return -1; @@ -198,6 +208,8 @@ int zephyr_supp_connect(const struct device *dev, wpa_supp_restart_status_work(); + k_mutex_unlock(&wpa_supplicant_mutex); + return 0; } @@ -205,6 +217,8 @@ int zephyr_supp_disconnect(const struct device *dev) { struct wpa_supplicant *wpa_s; + k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); + wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { return -1; @@ -215,6 +229,8 @@ int zephyr_supp_disconnect(const struct device *dev) wpa_supp_restart_status_work(); + k_mutex_unlock(&wpa_supplicant_mutex); + return 0; } @@ -252,12 +268,19 @@ int zephyr_supp_status(const struct device *dev, struct wifi_iface_status *status) { struct wpa_supplicant *wpa_s; - struct wpa_signal_info si; int ret = -1; + struct wpa_signal_info *si = NULL; + + k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { - return -1; + goto out; + } + + si = os_zalloc(sizeof(struct wpa_signal_info)); + if (!si) { + goto out; } status->state = wpa_s->wpa_state; /* 1-1 Mapping */ @@ -293,15 +316,19 @@ int zephyr_supp_status(const struct device *dev, /* TODO: Derive this based on association IEs */ status->link_mode = WIFI_6; } - ret = wpa_drv_signal_poll(wpa_s, &si); + ret = wpa_drv_signal_poll(wpa_s, si); if (!ret) { - status->rssi = si.current_signal; + status->rssi = si->current_signal; } else { wpa_printf(MSG_ERROR, "%s:Failed to read RSSI\n", __func__); status->rssi = -WPA_INVALID_NOISE; } + } else { + ret = 0; } - - return 0; +out: + os_free(si); + k_mutex_unlock(&wpa_supplicant_mutex); + return ret; } From b97910271916d734195eb395664e332d4afe57dc Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 26 Sep 2022 17:24:27 +0530 Subject: [PATCH 039/150] Add support for channel selection If a channel is provided pass it WPA supplicant to use that in both scan and connection. The conversion from channel to frequency without any regulatory information (country code, OP class) is tricky, but use Global with widest OP classes common to most countries (81 and 128). Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index c4f9a5cbdf..7839b74a1f 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -156,6 +156,38 @@ int zephyr_supp_connect(const struct device *dev, ssid->disabled = 1; ssid->key_mgmt = WPA_KEY_MGMT_NONE; + if (params->channel != WIFI_CHANNEL_ANY) { + /* We use global channel list here and also use the widest + * op_class for 5GHz channels as there is no user input + * for these. + */ + int freq = ieee80211_chan_to_freq(NULL, 81, params->channel); + + if (freq <= 0) { + freq = ieee80211_chan_to_freq(NULL, 128, params->channel); + } + + if (freq <= 0) { + wpa_printf(MSG_ERROR, "Invalid channel %d", params->channel); + return -EINVAL; + } + + ssid->scan_freq = os_zalloc(2 * sizeof(int)); + if (!ssid->scan_freq) { + return -ENOMEM; + } + ssid->scan_freq[0] = freq; + ssid->scan_freq[1] = 0; + + ssid->freq_list = os_zalloc(2 * sizeof(int)); + if (!ssid->freq_list) { + os_free(ssid->scan_freq); + return -ENOMEM; + } + ssid->freq_list[0] = freq; + ssid->freq_list[1] = 0; + } + wpa_s->conf->filter_ssids = 1; wpa_s->conf->ap_scan = 1; From 6754055fca6c6d26795e5a21b00554ef891c8afc Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Tue, 27 Sep 2022 13:17:04 +0530 Subject: [PATCH 040/150] Enable support for MBO MBO is multi-band operation, this is needed for WFA certification for Wi-Fi 6. Signed-off-by: Ajay Parida --- wpa_supplicant/wnm_sta.c | 2 +- zephyr/CMakeLists.txt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 96160dccbf..11e09f3041 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -762,7 +762,7 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs, os_reltime_expired(&now, &target->last_update, age_secs)) { wpa_printf(MSG_DEBUG, - "Candidate BSS is more than %ld seconds old", + "Candidate BSS is more than %lld seconds old", age_secs); continue; } diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 1b1add1ebd..46570c9ba9 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -37,6 +37,8 @@ zephyr_library_compile_definitions( CONFIG_CTRL_IFACE CONFIG_CTRL_IFACE_UDP CONFIG_NO_RANDOM_POOL + CONFIG_MBO + CONFIG_WNM ) zephyr_library_include_directories( @@ -86,6 +88,8 @@ zephyr_library_sources( ${WPA_SUPPLICANT_BASE}/ctrl_iface.c ${WPA_SUPPLICANT_BASE}/ctrl_iface_udp.c ${WPA_SUPPLICANT_BASE}/wpa_cli.c + ${WPA_SUPPLICANT_BASE}/mbo.c + ${WPA_SUPPLICANT_BASE}/wnm_sta.c # Zephyr main src/supp_main.c src/utils/wpa_debug.c From a6da521b0f8a93ca485c45039c1133b052e3c0b8 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 4 Oct 2022 23:45:42 +0530 Subject: [PATCH 041/150] Increase log buffer size * Debug logging is excessive and needs larger buffer size to avoid truncating/dropping logs * Also, in general supplicant outputs bunch of logs, so, even for non-debug case increase the buffer size Signed-off-by: Krishna T --- zephyr/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 2430a6eec5..fa878f7ef6 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -70,4 +70,9 @@ config WPA_SUPP_DEBUG_LEVEL available levels and functions for emitting the messages. Note that runtime filtering can also be configured in addition to the compile-time filtering. + +# Debug logs need more buffer space +config LOG_BUFFER_SIZE + default 4096 if WPA_SUPP_LOG_LEVEL_DBG + default 2048 endif From cbc3ae3e91d93e05a7ae60f17f70bb41d64c1ace Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 5 Oct 2022 00:18:04 +0530 Subject: [PATCH 042/150] Fix mutex unlock In case of failure scenarions, mutex is not unlocked causing next command to block forever (shell thread is blocked). Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 7839b74a1f..1303ec3bad 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -138,12 +138,13 @@ int zephyr_supp_connect(const struct device *dev, struct wpa_ssid *ssid = NULL; bool pmf = true; struct wpa_supplicant *wpa_s; + int ret = -1; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { - return -1; + goto out; } wpa_supplicant_remove_all_networks(wpa_s); @@ -169,12 +170,14 @@ int zephyr_supp_connect(const struct device *dev, if (freq <= 0) { wpa_printf(MSG_ERROR, "Invalid channel %d", params->channel); - return -EINVAL; + ret = -EINVAL; + goto out; } ssid->scan_freq = os_zalloc(2 * sizeof(int)); if (!ssid->scan_freq) { - return -ENOMEM; + ret = -ENOMEM; + goto out; } ssid->scan_freq[0] = freq; ssid->scan_freq[1] = 0; @@ -182,7 +185,8 @@ int zephyr_supp_connect(const struct device *dev, ssid->freq_list = os_zalloc(2 * sizeof(int)); if (!ssid->freq_list) { os_free(ssid->scan_freq); - return -ENOMEM; + ret = -ENOMEM; + goto out; } ssid->freq_list[0] = freq; ssid->freq_list[1] = 0; @@ -199,9 +203,10 @@ int zephyr_supp_connect(const struct device *dev, ssid->sae_password = dup_binstr(params->psk, params->psk_length); if (ssid->sae_password == NULL) { - wpa_printf(MSG_ERROR, "%s:Failed t copy sae_password\n", + wpa_printf(MSG_ERROR, "%s:Failed to copy sae_password\n", __func__); - return -1; + ret = -ENOMEM; + goto out; } } else { if (params->security == 2) @@ -213,9 +218,10 @@ int zephyr_supp_connect(const struct device *dev, ssid->passphrase = dup_binstr(params->psk, params->psk_length); if (ssid->passphrase == NULL) { - wpa_printf(MSG_ERROR, "%s:Failed t copy passphrase\n", + wpa_printf(MSG_ERROR, "%s:Failed to copy passphrase\n", __func__); - return -1; + ret = -ENOMEM; + goto out; } } @@ -240,20 +246,24 @@ int zephyr_supp_connect(const struct device *dev, wpa_supp_restart_status_work(); + ret = 0; + +out: k_mutex_unlock(&wpa_supplicant_mutex); - return 0; + return ret; } int zephyr_supp_disconnect(const struct device *dev) { struct wpa_supplicant *wpa_s; + int ret = -1; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { - return -1; + goto out; } wpa_supp_api_ctrl.dev = dev; wpa_supp_api_ctrl.requested_op = DISCONNECT; @@ -261,9 +271,12 @@ int zephyr_supp_disconnect(const struct device *dev) wpa_supp_restart_status_work(); + ret = 0; + +out: k_mutex_unlock(&wpa_supplicant_mutex); - return 0; + return ret; } From 4ee2a9c76e28dfd590f289960b44e7b100cb4e04 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 6 Oct 2022 19:39:39 +0530 Subject: [PATCH 043/150] Choose necessary MbedTLS Kconfig symbols by default MbedTLS is only used by sdk-hostap, choose the necessary Kconfig options by default instead of relying on samples. Signed-off-by: Krishna T --- zephyr/Kconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index fa878f7ef6..dfa0cda10d 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -27,8 +27,24 @@ config WEP config WPA_SUPP_CRYPTO bool "Crypto support for WiFi" select WEP + select MBEDTLS + select NRF_SECURITY + select MBEDTLS_LEGACY_CRYPTO_C + select MBEDTLS_ECP_C + select MBEDTLS_CTR_DRBG_C + select MBEDTLS_ENTROPY_C + select MBEDTLS_PK_WRITE_C + select MBEDTLS_KEY_EXCHANGE_ALL_ENABLED default y +# Needed for internal entropy +config MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + default n if WPA_SUPP_CRYPTO + +# To fix MAC_MD5 Kconfig warning +config NET_TCP_ISN_RFC6528 + default n if WPA_SUPP_CRYPTO + config WPA_SUPP_CRYPTO_ENTERPRISE bool "Enterprise Crypto support for WiFi" From 35ede8ea325e13e23adc4a3c873c3824abd35536 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 10 Oct 2022 19:41:04 +0530 Subject: [PATCH 044/150] Fix Zephyr includes with latest up-merge Zephyr has deprecated including "zephyr" directory in includes, so, all references should mandatory use "zephyr" prefix. Also, reordered the include groups. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.h | 5 +++-- src/l2_packet/l2_packet_zephyr.c | 18 +++++++----------- src/utils/common.c | 2 +- src/utils/includes.h | 14 +++++++------- src/utils/os_zephyr.c | 8 +++++--- wpa_supplicant/ctrl_iface.c | 2 +- zephyr/src/supp_main.c | 2 +- zephyr/src/wpa_cli.c | 10 +++++----- 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 9b19e5cf52..e73e56e37a 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -9,8 +9,9 @@ #ifndef DRIVER_ZEPHYR_H #define DRIVER_ZEPHYR_H -#include -#include +#include +#include + #include "driver.h" #include "wpa_supplicant_i.h" #include "bss.h" diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index d7d5ce5a89..dd48a312fb 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -4,22 +4,18 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#include "includes.h" +#include +#include +#include +#include +#include +#include +#include "includes.h" #include "common.h" #include "eloop.h" #include "l2_packet.h" #include "common/eapol_common.h" - -#include - -#include -#include - -#include -#include -#include - struct l2_packet_data { char ifname[17]; u8 own_addr[ETH_ALEN]; diff --git a/src/utils/common.c b/src/utils/common.c index 7bed4600c4..9db7ce32e9 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -1304,7 +1304,7 @@ void forced_memzero(void *ptr, size_t len) } #ifdef CONFIG_ZEPHYR -#include +#include extern char *inet_ntoa(struct in_addr in) { char addr[NET_IPV4_ADDR_LEN]; diff --git a/src/utils/includes.h b/src/utils/includes.h index 523bb088c7..fad478dea7 100644 --- a/src/utils/includes.h +++ b/src/utils/includes.h @@ -45,15 +45,15 @@ #if defined(CONFIG_ZEPHYR) #if defined(CONFIG_POSIX_API) -#include -#include -#include -#include +#include +#include +#include +#include #else /* defined(CONFIG_POSIX_API) */ -#include -#include +#include +#include #endif /* defined(CONFIG_POSIX_API) */ -#include +#include #endif /* defined(CONFIG_ZEPHYR) */ #endif /* INCLUDES_H */ diff --git a/src/utils/os_zephyr.c b/src/utils/os_zephyr.c index 747a66ced1..cbc68ae6f4 100644 --- a/src/utils/os_zephyr.c +++ b/src/utils/os_zephyr.c @@ -4,10 +4,12 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#include "includes.h" -#include #include -#include + +#include +#include + +#include "includes.h" #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 665df690b2..2d1c14fbab 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -62,7 +62,7 @@ #ifdef __NetBSD__ #include #elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS) -#include +#include #endif static int wpa_supplicant_global_iface_list(struct wpa_global *global, diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 3b54eac5a5..16eaebf993 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -12,7 +12,7 @@ * See README for more details. */ -#include +#include #include LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index e7f1f73e06..73fb180cd7 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -12,15 +12,15 @@ #include #include -#include +#include #include #include -#include -#include -#include +#include +#include +#include -#include +#include #include #include From 9337fe02c9c29c8815706c5728223fc3df82f428 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 11 Oct 2022 01:32:40 +0530 Subject: [PATCH 045/150] Fix deadlock during connect If a connect has been issued before the first connect timeout/success, then there is a deadlock as connect API holds the mutex but calls the connect status worker which tries to get mutex. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 1303ec3bad..6d84b2db35 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -138,7 +138,7 @@ int zephyr_supp_connect(const struct device *dev, struct wpa_ssid *ssid = NULL; bool pmf = true; struct wpa_supplicant *wpa_s; - int ret = -1; + int ret = 0; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); @@ -244,38 +244,39 @@ int zephyr_supp_connect(const struct device *dev, wpa_supp_api_ctrl.requested_op = CONNECT; wpa_supp_api_ctrl.connection_timeout = params->timeout; - wpa_supp_restart_status_work(); - - ret = 0; - out: k_mutex_unlock(&wpa_supplicant_mutex); + if (!ret) { + wpa_supp_restart_status_work(); + } + return ret; } int zephyr_supp_disconnect(const struct device *dev) { struct wpa_supplicant *wpa_s; - int ret = -1; + int ret = 0; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { + ret = -EINVAL; goto out; } wpa_supp_api_ctrl.dev = dev; wpa_supp_api_ctrl.requested_op = DISCONNECT; wpas_request_disconnection(wpa_s); - wpa_supp_restart_status_work(); - - ret = 0; - out: k_mutex_unlock(&wpa_supplicant_mutex); + if (!ret) { + wpa_supp_restart_status_work(); + } + return ret; } From 7d084aa372af1d2d2a698c67bf8f58fe0eda7601 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 11 Oct 2022 01:41:49 +0530 Subject: [PATCH 046/150] (dis)connection status: Terminate gracefully If we get a new connection request, gracefully terminate it by sending a failure event before starting tracking of the new connection status. This also avoid a case where old work is rescheduled even though its cancelled successfully. Also, return a different status for this termination. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 6d84b2db35..7b59be25c7 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -36,6 +36,7 @@ struct wpa_supp_api_ctrl { enum requested_ops requested_op; int connection_timeout; struct k_work_sync sync; + bool terminate; }; static struct wpa_supp_api_ctrl wpa_supp_api_ctrl; @@ -85,6 +86,11 @@ static void supp_shell_connect_status(struct k_work *work) k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); + if (ctrl->terminate) { + status = 2; + goto out; + } + wpa_s = get_wpa_s_handle(ctrl->dev); if (!wpa_s) { status = 1; @@ -125,8 +131,13 @@ static void supp_shell_connect_status(struct k_work *work) static inline void wpa_supp_restart_status_work(void) { - k_work_cancel_delayable_sync(&wpa_supp_status_work, - &wpa_supp_api_ctrl.sync); + /* Terminate synchronously */ + wpa_supp_api_ctrl.terminate = 1; + k_work_flush_delayable(&wpa_supp_status_work, + &wpa_supp_api_ctrl.sync); + wpa_supp_api_ctrl.terminate = 0; + + /* Start afresh */ k_work_reschedule(&wpa_supp_status_work, K_MSEC(10)); } From f89bd529660f611ca5677d8bea79525a6514b313 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 11 Oct 2022 13:50:24 +0530 Subject: [PATCH 047/150] Fix header file prefix This is an internal header file. Signed-off-by: Krishna T --- zephyr/src/wpa_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index 73fb180cd7..4ce82017ef 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include From 306b36c1f02579c1988c3dbab64baac4ec7b9224 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 10 Oct 2022 17:39:06 +0530 Subject: [PATCH 048/150] Remove nRF Wi-Fi management Now that nRF Wi-Fi management is merged with Zephyr's Wi-Fi management, use Zephyr's Wi-Fi management. Signed-off-by: Krishna T --- zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index dfa0cda10d..e949925a8a 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -11,7 +11,7 @@ config WPA_SUPP depends on NET_SOCKETS_POSIX_NAMES || POSIX_API select NET_SOCKETS_PACKET select NET_SOCKETPAIR - select NET_L2_NRF_WIFI_MGMT + select NET_L2_WIFI_MGMT help WPA supplicant implements 802.1X related functions. From b5033d1ae4a95ea1f789a1e2db9a39802ca74801 Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Tue, 18 Oct 2022 16:12:32 +0530 Subject: [PATCH 049/150] wifi: MBO Pre-certification bugfixes Support for handling MLME frames. Enable RRM support in capabilities. Support for wnm_bss_query wpa_cli cmd. Signed-off-by: Sridhar Nuvusetty --- src/drivers/driver_zephyr.c | 63 +++++++++++++++++++++++++++++++++++++ src/drivers/driver_zephyr.h | 9 ++++++ zephyr/src/wpa_cli.c | 4 +++ 3 files changed, 76 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 45a2db3079..2ec746a61e 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -195,6 +195,30 @@ void wpa_drv_zep_event_proc_disassoc(struct zep_drv_if_ctx *if_ctx, event); } +static void wpa_drv_zep_event_mgmt_tx_status(struct zep_drv_if_ctx *if_ctx, + const u8 *frame, size_t len, bool ack) +{ + union wpa_event_data event; + const struct ieee80211_hdr *hdr; + u16 fc; + + wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event"); + + hdr = (const struct ieee80211_hdr *) frame; + fc = le_to_host16(hdr->frame_control); + + os_memset(&event, 0, sizeof(event)); + event.tx_status.type = WLAN_FC_GET_TYPE(fc); + event.tx_status.stype = WLAN_FC_GET_STYPE(fc); + event.tx_status.dst = hdr->addr1; + event.tx_status.data = frame; + event.tx_status.data_len = len; + event.tx_status.ack = ack; + + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_TX_STATUS, + &event); +} static void *wpa_drv_zep_global_init(void *ctx) { @@ -282,6 +306,7 @@ static void *wpa_drv_zep_init(void *ctx, callbk_fns.assoc_resp = wpa_drv_zep_event_proc_assoc_resp; callbk_fns.deauth = wpa_drv_zep_event_proc_deauth; callbk_fns.disassoc = wpa_drv_zep_event_proc_disassoc; + callbk_fns.mgmt_tx_status = wpa_drv_zep_event_mgmt_tx_status; if_ctx->dev_priv = dev_ops->init(if_ctx, ifname, @@ -643,6 +668,7 @@ static int wpa_drv_zep_get_capa(void *priv, capa->flags = 0; capa->flags |= WPA_DRIVER_FLAGS_SME; capa->flags |= WPA_DRIVER_FLAGS_SAE; + capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_RRM; return 0; } @@ -752,6 +778,42 @@ static int wpa_drv_zep_signal_poll(void *priv, struct wpa_signal_info *si) return ret; } +static int wpa_drv_zep_send_action(void *priv, unsigned int freq, + unsigned int wait_time, + const u8 *dst, const u8 *src, + const u8 *bssid, + const u8 *data, size_t data_len, + int no_cck) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + u8 *buf; + struct ieee80211_hdr *hdr; + + if_ctx = priv; + dev_ops = if_ctx->dev_ctx->config; + + wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (" + "freq=%u MHz wait=%d ms no_cck=%d)", + freq, wait_time, no_cck); + + buf = os_zalloc(24 + data_len); + if (buf == NULL) + return ret; + os_memcpy(buf + 24, data, data_len); + hdr = (struct ieee80211_hdr *)buf; + hdr->frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); + os_memcpy(hdr->addr1, dst, ETH_ALEN); + os_memcpy(hdr->addr2, src, ETH_ALEN); + os_memcpy(hdr->addr3, bssid, ETH_ALEN); + + + return dev_ops->send_mlme(if_ctx->dev_priv, buf, 24 + data_len, + 0, freq, no_cck, 1, + wait_time, 0); +} const struct wpa_driver_ops wpa_driver_zep_ops = { .name = "zephyr", @@ -772,4 +834,5 @@ const struct wpa_driver_ops wpa_driver_zep_ops = { .deauthenticate = wpa_drv_zep_deauthenticate, .set_key = wpa_drv_zep_set_key, .signal_poll = wpa_drv_zep_signal_poll, + .send_action = wpa_drv_zep_send_action, }; diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index e73e56e37a..3c7b2e242f 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -66,6 +66,9 @@ struct zep_wpa_supp_dev_callbk_fns { void (*disassoc)(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event); + + void (*mgmt_tx_status)(struct zep_drv_if_ctx *if_ctx, + const u8 *frame, size_t len, bool ack); }; @@ -101,6 +104,12 @@ struct zep_wpa_supp_dev_ops { char *bssid); int (*signal_poll)(void *if_priv, struct wpa_signal_info *si, unsigned char *bssid); + int (*send_mlme)(void *if_priv, const u8 *data, + size_t data_len, int noack, + unsigned int freq, int no_cck, + int offchanok, + unsigned int wait_time, + int cookie); }; #endif /* DRIVER_ZEPHYR_H */ diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index 4ce82017ef..3b3285ae60 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -125,6 +125,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( NULL, "\"\"", cmd_supplicant), + SHELL_CMD(wnm_bss_query, + NULL, + "\"\"", + cmd_supplicant), SHELL_SUBCMD_SET_END); /* Persisting with "wpa_cli" naming for compatibility with Wi-Fi From 8578a9dac562629b217c9e55342373081f488c64 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 19 Oct 2022 00:08:27 +0530 Subject: [PATCH 050/150] Fix link address buffer overflow When 802.15.4 is enabled the link address is 8, but we only allocate 6 bytes on stack causing buffer overflow. Use proper macro for the link address length and also add a length check just in case. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 16eaebf993..22fc2512ed 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -75,11 +75,16 @@ static void iface_cb(struct net_if *iface, void *user_data) struct wpa_interface *ifaces = user_data; struct net_linkaddr *link_addr = NULL; int ifindex; - char own_addr[6]; + char own_addr[NET_LINK_ADDR_MAX_LENGTH]; char *ifname; ifindex = net_if_get_by_iface(iface); link_addr = &iface->if_dev->link_addr; + if (link_addr->len > NET_LINK_ADDR_MAX_LENGTH) { + wpa_printf(MSG_ERROR, "Invalid link address length, %d max %d", + link_addr->len, NET_LINK_ADDR_MAX_LENGTH); + return; + } os_memcpy(own_addr, link_addr->addr, link_addr->len); ifname = os_strdup(iface->if_dev->dev->name); From 2e7d29c4868ada9cc4c7bc2c434b3b0c1af08527 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 19 Oct 2022 00:10:08 +0530 Subject: [PATCH 051/150] Fix build warnings with Zephyr toolchain 0.15.1 Zephyr toolchain has these build warnings about unnecessary null checks. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 4 ---- src/l2_packet/l2_packet_zephyr.c | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 2ec746a61e..a918276c33 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -696,10 +696,6 @@ static int wpa_drv_zep_get_ssid(void *priv, if_ctx = priv; - if (!if_ctx->ssid) { - return 0; - } - wpa_printf(MSG_INFO, "%s: SSID size: %d\n", __func__, diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index dd48a312fb..43018e14e9 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -169,8 +169,7 @@ l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol, ll.sll_protocol = htons(protocol); // FIXME: This should skip bind_default to ETH_P_ALL, but its not. - if (l2->own_addr) - memcpy(ll.sll_addr, l2->own_addr, ETH_ALEN); + memcpy(ll.sll_addr, l2->own_addr, ETH_ALEN); ret = bind(l2->fd, (const struct sockaddr *) &ll, sizeof(ll)); if (ret < 0) { From 4b6dba3bf17add13dd196abefef9ec6cf3f40a3b Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 26 Oct 2022 01:26:29 +0530 Subject: [PATCH 052/150] Use the PMF setting from the user Now that Zephyr supports taking PMF setting from the user, use that instead of hard-coding to optional. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 7b59be25c7..cad8c64b95 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -238,8 +238,10 @@ int zephyr_supp_connect(const struct device *dev, wpa_config_update_psk(ssid); - if (pmf) - ssid->ieee80211w = 1; + if (pmf) { + /* 1-1 Mapping */ + ssid->ieee80211w = params->mfp; + } } From f665cad9361eab62d3eea077b04e68613c7e93a6 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 24 Oct 2022 17:39:14 +0530 Subject: [PATCH 053/150] Fix sending terminate event for first requests Whenever a connection/disconnection is requested, a terminated event is sent first always before sending the result event. Fix to send terminate event only if a second connection/disconnection is requested. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index cad8c64b95..9e0a90bd05 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -26,6 +26,11 @@ enum requested_ops { DISCONNECT }; +enum status_thread_state { + STATUS_THREAD_STOPPED = 0, + STATUS_THREAD_RUNNING, +}; + #define OP_STATUS_POLLING_INTERVAL 1 K_MUTEX_DEFINE(wpa_supplicant_mutex); @@ -34,6 +39,7 @@ K_MUTEX_DEFINE(wpa_supplicant_mutex); struct wpa_supp_api_ctrl { const struct device *dev; enum requested_ops requested_op; + enum status_thread_state status_thread_state; int connection_timeout; struct k_work_sync sync; bool terminate; @@ -86,7 +92,7 @@ static void supp_shell_connect_status(struct k_work *work) k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); - if (ctrl->terminate) { + if (ctrl->status_thread_state == STATUS_THREAD_RUNNING && ctrl->terminate) { status = 2; goto out; } @@ -105,6 +111,7 @@ static void supp_shell_connect_status(struct k_work *work) k_work_reschedule(&wpa_supp_status_work, K_SECONDS(OP_STATUS_POLLING_INTERVAL)); k_mutex_unlock(&wpa_supplicant_mutex); + ctrl->status_thread_state = STATUS_THREAD_RUNNING; return; } @@ -126,6 +133,7 @@ static void supp_shell_connect_status(struct k_work *work) wifi_mgmt_raise_disconnect_result_event(net_if_lookup_by_dev(ctrl->dev), 0); } + ctrl->status_thread_state = STATUS_THREAD_STOPPED; k_mutex_unlock(&wpa_supplicant_mutex); } From 6a4ba89719881f3420eaac76862f55bca0cf5ff0 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 28 Oct 2022 20:52:44 +0530 Subject: [PATCH 054/150] Remove unncessary error message If a 802.15.4 interface is present, then this is expected and not an error, so, just silently ignore. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 22fc2512ed..b84b7463e7 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -80,9 +80,8 @@ static void iface_cb(struct net_if *iface, void *user_data) ifindex = net_if_get_by_iface(iface); link_addr = &iface->if_dev->link_addr; + /* 802.15.4 interface, ignore */ if (link_addr->len > NET_LINK_ADDR_MAX_LENGTH) { - wpa_printf(MSG_ERROR, "Invalid link address length, %d max %d", - link_addr->len, NET_LINK_ADDR_MAX_LENGTH); return; } os_memcpy(own_addr, link_addr->addr, link_addr->len); From 931582121d7dea4364b7b4b886a9735ba5aee0f4 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 31 Oct 2022 15:26:05 +0530 Subject: [PATCH 055/150] Explicitly enabled CBC/CTR If we enable OpenThread then these are disabled by default, so, enable them explicitly. Signed-off-by: Krishna T --- zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e949925a8a..5b6baeea1b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -29,6 +29,8 @@ config WPA_SUPP_CRYPTO select WEP select MBEDTLS select NRF_SECURITY + select MBEDTLS_CIPHER_MODE_CBC + select MBEDTLS_CIPHER_MODE_CTR select MBEDTLS_LEGACY_CRYPTO_C select MBEDTLS_ECP_C select MBEDTLS_CTR_DRBG_C From 5ee5972d527ede375f982fcedaeea26f2fb03f10 Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Tue, 1 Nov 2022 12:59:22 +0530 Subject: [PATCH 056/150] wifi: PMF Pre-certification bugfixes Support for handling un-protected deauth/disassoc frame. Signed-off-by: Ajay Parida --- src/drivers/driver_zephyr.c | 18 ++++++++++++++++++ src/drivers/driver_zephyr.h | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index a918276c33..01afaa770a 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -220,6 +220,22 @@ static void wpa_drv_zep_event_mgmt_tx_status(struct zep_drv_if_ctx *if_ctx, &event); } +static void wpa_drv_zep_event_proc_unprot_deauth(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event) +{ + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_UNPROT_DEAUTH, + event); +} + +static void wpa_drv_zep_event_proc_unprot_disassoc(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event) +{ + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_UNPROT_DISASSOC, + event); +} + static void *wpa_drv_zep_global_init(void *ctx) { struct zep_drv_ctx *drv_ctx = NULL; @@ -307,6 +323,8 @@ static void *wpa_drv_zep_init(void *ctx, callbk_fns.deauth = wpa_drv_zep_event_proc_deauth; callbk_fns.disassoc = wpa_drv_zep_event_proc_disassoc; callbk_fns.mgmt_tx_status = wpa_drv_zep_event_mgmt_tx_status; + callbk_fns.unprot_deauth = wpa_drv_zep_event_proc_unprot_deauth; + callbk_fns.unprot_disassoc = wpa_drv_zep_event_proc_unprot_disassoc; if_ctx->dev_priv = dev_ops->init(if_ctx, ifname, diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 3c7b2e242f..34573b5a1a 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -69,6 +69,13 @@ struct zep_wpa_supp_dev_callbk_fns { void (*mgmt_tx_status)(struct zep_drv_if_ctx *if_ctx, const u8 *frame, size_t len, bool ack); + + void (*unprot_deauth)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event); + + void (*unprot_disassoc)(struct zep_drv_if_ctx *if_ctx, + union wpa_event_data *event); + }; From 9424933fd9fe39a19e67946b653d3a8f6885d142 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 1 Nov 2022 01:26:14 +0530 Subject: [PATCH 057/150] Fix spurious hash Not sure how this crept in. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index 4a4b939e1d..0f06c26040 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -182,7 +182,7 @@ int crypto_bignum_mulmod( res = mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, &temp, (mbedtls_mpi *)c); mbedtls_mpi_free(&temp); -# + return res ? -1 : 0; } From 1e7b71608d00f137fa5cfa11dc86fdaa6849ee77 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 2 Nov 2022 17:30:32 +0530 Subject: [PATCH 058/150] Fix MbedTLS addmod operation "addmod" operation should do "d = (a + b) % c" instead it was doing "a = ( b + c ) %d " where "a" is a const, and d is not assigned any value, this is totally wrong. This fixes the SAE-PWE=2 (H2E) option. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index 0f06c26040..63ca5512bf 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -293,20 +293,17 @@ int crypto_bignum_addmod( const struct crypto_bignum *c, struct crypto_bignum *d) { struct crypto_bignum *tmp = crypto_bignum_init(); - int ret = -1; + int ret; - if (mbedtls_mpi_add_mpi( - (mbedtls_mpi *)tmp, (const mbedtls_mpi *)b, - (const mbedtls_mpi *)c) < 0) - goto fail; + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi( + (mbedtls_mpi *)tmp, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b)); - if (mbedtls_mpi_mod_mpi( - (mbedtls_mpi *)a, (const mbedtls_mpi *)tmp, - (const mbedtls_mpi *)d) < 0) - goto fail; + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi( + (mbedtls_mpi *)d, (const mbedtls_mpi *)tmp, + (const mbedtls_mpi *)c)); - ret = 0; -fail: +cleanup: crypto_bignum_deinit(tmp, 0); return ret; } From cf083650b92b17c46fe968e418535ef3b9c003aa Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 7 Nov 2022 15:36:41 +0530 Subject: [PATCH 059/150] Fix square modulo operation We are using the MbedTLS modulo exponentiation API for doing square, but instead of doing "a^2" we are doing "a^a". This fixes WPA3-SAE (H2E). Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index 63ca5512bf..f840e003cf 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -212,9 +212,16 @@ int crypto_bignum_sqrmod( const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { - return mbedtls_mpi_exp_mod( - (mbedtls_mpi *)c, (mbedtls_mpi *)a, (mbedtls_mpi *)a, - (mbedtls_mpi *)b, NULL); + struct crypto_bignum *two = crypto_bignum_init_uint(2); + int ret; + + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + (mbedtls_mpi *)c, (mbedtls_mpi *)a, (mbedtls_mpi *)two, + (mbedtls_mpi *)b, NULL)); + +cleanup: + crypto_bignum_deinit(two, 1); + return ret; } int crypto_bignum_rshift( From c636389a266576e478ff68bff8e65ac6060a8f5b Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 7 Nov 2022 15:43:00 +0530 Subject: [PATCH 060/150] Use MbedTLS macro to check for return value To be consistent use the MbedTLS macro to check for return value of MbedTLS APIs, this is readable as well. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index f840e003cf..f7fe28a921 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -169,21 +169,19 @@ int crypto_bignum_mulmod( const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d) { - int res; + int ret; mbedtls_mpi temp; mbedtls_mpi_init(&temp); - res = mbedtls_mpi_mul_mpi( - &temp, (const mbedtls_mpi *)a, (const mbedtls_mpi *)b); - if (res) { - return -1; - } + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi( + &temp, (const mbedtls_mpi *)a, (const mbedtls_mpi *)b)); - res = mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, &temp, (mbedtls_mpi *)c); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, &temp, (mbedtls_mpi *)c)); mbedtls_mpi_free(&temp); - return res ? -1 : 0; +cleanup: + return ret; } int crypto_bignum_cmp( @@ -227,11 +225,13 @@ int crypto_bignum_sqrmod( int crypto_bignum_rshift( const struct crypto_bignum *a, int n, struct crypto_bignum *r) { + int ret; - if (mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)) { - return -1; - } - return mbedtls_mpi_shift_r((mbedtls_mpi *)r, n); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r((mbedtls_mpi *)r, n)); + +cleanup: + return ret; } int crypto_bignum_legendre( From 454c4f99d6aff07156cf3d9b340471774656dc61 Mon Sep 17 00:00:00 2001 From: Marcin Kajor Date: Fri, 25 Nov 2022 19:34:15 +0100 Subject: [PATCH 061/150] Fixed the connection timeout handling, * Since the supp_shell_connect_status is called (queued) recursively the counter of connection retries (with second interval) needs to persist between consecutive calls. Without this change the supplicant retries to connect to the AP endlessly. * Also got rid of some magic numbers. Signed-off-by: Marcin Kajor --- zephyr/src/supp_api.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 9e0a90bd05..478b00f9f2 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -33,6 +33,10 @@ enum status_thread_state { #define OP_STATUS_POLLING_INTERVAL 1 +#define CONNECTION_SUCCESS 0 +#define CONNECTION_FAILURE 1 +#define CONNECTION_TERMINATED 2 + K_MUTEX_DEFINE(wpa_supplicant_mutex); @@ -40,7 +44,7 @@ struct wpa_supp_api_ctrl { const struct device *dev; enum requested_ops requested_op; enum status_thread_state status_thread_state; - int connection_timeout; + int connection_timeout; // in seconds struct k_work_sync sync; bool terminate; }; @@ -86,27 +90,28 @@ static inline struct wpa_supplicant * get_wpa_s_handle(const struct device *dev) static void supp_shell_connect_status(struct k_work *work) { - int i = 0, status = 0; + static int seconds_counter = 0; + int status = CONNECTION_SUCCESS; struct wpa_supplicant *wpa_s; struct wpa_supp_api_ctrl *ctrl = &wpa_supp_api_ctrl; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); if (ctrl->status_thread_state == STATUS_THREAD_RUNNING && ctrl->terminate) { - status = 2; + status = CONNECTION_TERMINATED; goto out; } wpa_s = get_wpa_s_handle(ctrl->dev); if (!wpa_s) { - status = 1; + status = CONNECTION_FAILURE; goto out; } if (ctrl->requested_op == CONNECT) { if (wpa_s->wpa_state != WPA_COMPLETED && (ctrl->connection_timeout == SYS_FOREVER_MS || - i++ <= ctrl->connection_timeout)) + seconds_counter++ <= ctrl->connection_timeout)) { k_work_reschedule(&wpa_supp_status_work, K_SECONDS(OP_STATUS_POLLING_INTERVAL)); @@ -115,10 +120,10 @@ static void supp_shell_connect_status(struct k_work *work) return; } - if (i > ctrl->connection_timeout){ + if (seconds_counter > ctrl->connection_timeout){ if (wpa_s->wpa_state != WPA_COMPLETED){ wpas_request_disconnection(wpa_s); - status = 1; + status = CONNECTION_FAILURE; goto out; } } @@ -128,10 +133,12 @@ static void supp_shell_connect_status(struct k_work *work) wifi_mgmt_raise_connect_result_event(net_if_lookup_by_dev(ctrl->dev), status); } else if (ctrl->requested_op == DISCONNECT) { /* Disconnect is a synchronous operation i.e., we are already disconnected - * we are just using this to post net_mgmt event asynchrnously. + * we are just using this to post net_mgmt event asynchronously. */ wifi_mgmt_raise_disconnect_result_event(net_if_lookup_by_dev(ctrl->dev), 0); } + /* The connection handling is done, so reset the counter (connection timeout) */ + seconds_counter = 0; ctrl->status_thread_state = STATUS_THREAD_STOPPED; k_mutex_unlock(&wpa_supplicant_mutex); From 49fddb8f5bb9511cf8d9e56bf680576b26fe2fc8 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Tue, 29 Nov 2022 14:24:13 +0100 Subject: [PATCH 062/150] Fix handling connection timeout equal to 0 When the connection timeout was 0 the code would always fail the connection. Change the condition to handle the timeout only if it is positive. By the way, simplify the conditions and unlock the mutex after modifying the shared variable. Signed-off-by: Damian Krolik --- zephyr/src/supp_api.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 478b00f9f2..f973c09e5a 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -108,25 +108,17 @@ static void supp_shell_connect_status(struct k_work *work) goto out; } - if (ctrl->requested_op == CONNECT) { - if (wpa_s->wpa_state != WPA_COMPLETED && - (ctrl->connection_timeout == SYS_FOREVER_MS || - seconds_counter++ <= ctrl->connection_timeout)) - { - k_work_reschedule(&wpa_supp_status_work, - K_SECONDS(OP_STATUS_POLLING_INTERVAL)); - k_mutex_unlock(&wpa_supplicant_mutex); - ctrl->status_thread_state = STATUS_THREAD_RUNNING; - return; + if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) { + if (ctrl->connection_timeout > 0 && seconds_counter++ > ctrl->connection_timeout) { + wpas_request_disconnection(wpa_s); + status = CONNECTION_FAILURE; + goto out; } - if (seconds_counter > ctrl->connection_timeout){ - if (wpa_s->wpa_state != WPA_COMPLETED){ - wpas_request_disconnection(wpa_s); - status = CONNECTION_FAILURE; - goto out; - } - } + k_work_reschedule(&wpa_supp_status_work, K_SECONDS(OP_STATUS_POLLING_INTERVAL)); + ctrl->status_thread_state = STATUS_THREAD_RUNNING; + k_mutex_unlock(&wpa_supplicant_mutex); + return; } out: if (ctrl->requested_op == CONNECT) { From 8bac62ccae57a606fa3229bbd17a033d741307df Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Thu, 27 Oct 2022 17:19:20 +0530 Subject: [PATCH 063/150] Correct the logic to check for 11b rates Mask the MSB of supported and extended supported rates since MSB identifies if its a basic rate or not, and is not required to check if the rate is one of the 11b rates. Signed-off-by: Ravi Dondaputi --- src/common/ieee802_11_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 5b74ddcdf6..c642264b67 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1556,7 +1556,7 @@ int supp_rates_11b_only(struct ieee802_11_elems *elems) return 0; for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) { - if (is_11b(elems->supp_rates[i])) + if (is_11b(elems->supp_rates[i] & 0x7f)) num_11b++; else num_others++; @@ -1564,7 +1564,7 @@ int supp_rates_11b_only(struct ieee802_11_elems *elems) for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len; i++) { - if (is_11b(elems->ext_supp_rates[i])) + if (is_11b(elems->ext_supp_rates[i] & 0x7f)) num_11b++; else num_others++; From 9526c7fd09f52b02b7f5b6e67e41ecc9f18e79bf Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Thu, 27 Oct 2022 17:27:24 +0530 Subject: [PATCH 064/150] Identify legacy mode connections Add following checks to identify legacy (a, b and g) mode connections: 1) Is a legacy connection if all of HE, HE and VHT capabilities are not present. 2) If operating in a 5GHz band, identify as "a". 3) If operating in 2.4GHz band and supported/extended supported rates match 11b rates, identify as "b", else identify as "g". Signed-off-by: Ravi Dondaputi --- wpa_supplicant/events.c | 17 +++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b1b243b00d..7fbc74484c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2931,6 +2931,7 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, wpa_s->connection_set = 0; if (data->assoc_info.req_ies && data->assoc_info.resp_ies) { struct ieee802_11_elems req_elems, resp_elems; + memset(&resp_elems, 0, sizeof(struct ieee802_11_elems)); if (ieee802_11_parse_elems(data->assoc_info.req_ies, data->assoc_info.req_ies_len, @@ -2951,6 +2952,22 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, BAND_2_4_GHZ); wpa_s->connection_he = req_elems.he_capabilities && resp_elems.he_capabilities; + if (!wpa_s->connection_ht && !wpa_s->connection_vht && + !wpa_s->connection_he) { + wpa_s->connection_a = 0; + wpa_s->connection_b = 0; + wpa_s->connection_g = 0; + if (wpas_freq_to_band(data->assoc_info.freq) == BAND_5_GHZ) { + wpa_s->connection_a = 1; + } else if (wpas_freq_to_band(data->assoc_info.freq) == + BAND_2_4_GHZ) { + if (supp_rates_11b_only(&resp_elems)) { + wpa_s->connection_b = 1; + } else { + wpa_s->connection_g = 1; + } + } + } } } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 5d2f23d1b3..e79cd62602 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -960,6 +960,9 @@ struct wpa_supplicant { unsigned int connection_vht:1; unsigned int connection_he:1; unsigned int disable_mbo_oce:1; + unsigned int connection_a:1; + unsigned int connection_b:1; + unsigned int connection_g:1; struct os_reltime last_mac_addr_change; int last_mac_addr_style; From d92b1bd441b41a146f04fb658fd120b70000ac73 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Thu, 27 Oct 2022 17:39:16 +0530 Subject: [PATCH 065/150] Display correct link mode in "wifi status" output Add checks to read and print the link mode correctly. Signed-off-by: Ravi Dondaputi --- zephyr/src/supp_api.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index f973c09e5a..1c556b9c97 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -379,8 +379,16 @@ int zephyr_supp_status(const struct device *dev, os_memcpy(status->ssid, _ssid, ssid_len); status->ssid_len = ssid_len; status->iface_mode = ssid->mode; - /* TODO: Derive this based on association IEs */ - status->link_mode = WIFI_6; + if (wpa_s->connection_set == 1) { + status->link_mode = wpa_s->connection_he ? WIFI_6 : + wpa_s->connection_vht ? WIFI_5 : + wpa_s->connection_ht ? WIFI_4 : + wpa_s->connection_g ? WIFI_3 : + wpa_s->connection_a ? WIFI_2 : + wpa_s->connection_b ? WIFI_1 : WIFI_0; + } else { + status->link_mode = WIFI_LINK_MODE_UNKNOWN; + } } ret = wpa_drv_signal_poll(wpa_s, si); if (!ret) { From 23d54fde78f15bde4b2cf263802b30893bce864e Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Thu, 17 Nov 2022 13:16:03 +0530 Subject: [PATCH 066/150] wifi : Add support for handling WIPHY cap., RX MLME frames SHEL-888: Supported Operating classes IE missing in the Assoc Request. SHEL-877: DUT not responding to AP beacon request frame using case 3 SHEL-859 : No BTM response for the BTM request frame from the AP. Signed-off-by: Sridhar Nuvusetty --- src/drivers/driver_zephyr.c | 450 +++++++++++++++++++++++++++++++++++- src/drivers/driver_zephyr.h | 91 ++++++++ 2 files changed, 539 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 01afaa770a..6bf6accb0d 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -12,6 +12,7 @@ #include "eloop.h" #include "driver_zephyr.h" #include "supp_main.h" +#include "common/ieee802_11_common.h" #define SCAN_TIMEOUT 30 @@ -202,7 +203,7 @@ static void wpa_drv_zep_event_mgmt_tx_status(struct zep_drv_if_ctx *if_ctx, const struct ieee80211_hdr *hdr; u16 fc; - wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event"); + wpa_printf(MSG_DEBUG, "wpa_supp: Frame TX status event"); hdr = (const struct ieee80211_hdr *) frame; fc = le_to_host16(hdr->frame_control); @@ -236,6 +237,444 @@ static void wpa_drv_zep_event_proc_unprot_disassoc(struct zep_drv_if_ctx *if_ctx event); } +struct phy_info_arg { + u16 *num_modes; + struct hostapd_hw_modes *modes; + int last_mode, last_chan_idx; + int failed; + u8 dfs_domain; +}; + +static void phy_info_freq_cfg(struct hostapd_hw_modes *mode, + struct hostapd_channel_data *chan, + struct wpa_supp_event_channel *chnl_info) +{ + u8 channel = 0; + + chan->freq = chnl_info->center_frequency; + chan->flag = 0; + chan->allowed_bw = ~0; + chan->dfs_cac_ms = 0; + + if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES) { + chan->chan = channel; + } + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_DISABLED) + chan->flag |= HOSTAPD_CHAN_DISABLED; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_IR) + chan->flag |= HOSTAPD_CHAN_NO_IR; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_RADAR) + chan->flag |= HOSTAPD_CHAN_RADAR; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_INDOOR_ONLY) + chan->flag |= HOSTAPD_CHAN_INDOOR_ONLY; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_GO_CONCURRENT) + chan->flag |= HOSTAPD_CHAN_GO_CONCURRENT; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_10MHZ) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_10; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_20MHZ) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_20; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_HT40_PLUS) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_40P; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_HT40_MINUS) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_40M; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_80MHZ) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_80; + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_160MHZ) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_160; + + if (chnl_info->wpa_supp_flags & WPA_SUPP_CHAN_DFS_CAC_TIME_VALID) { + chan->dfs_cac_ms = (chnl_info->wpa_supp_time); + } + + /* Other elements are not present */ + chan->wmm_rules_valid = 0; + chan->wmm_rules_valid = 0; +} + + +static int phy_info_freqs_cfg(struct phy_info_arg *phy_info, + struct hostapd_hw_modes *mode, + struct wpa_supp_event_supported_band *band_info) +{ + int new_channels = 0; + struct hostapd_channel_data *channel = NULL; + int idx; + + if (!phy_info || !mode || !band_info) + return -1; + + new_channels = band_info->wpa_supp_n_channels; + + if (!new_channels) + return 0; + + channel = os_realloc_array(mode->channels, + mode->num_channels + new_channels, + sizeof(struct hostapd_channel_data)); + + if (!channel) + return -1; + + mode->channels = channel; + mode->num_channels += new_channels; + + idx = phy_info->last_chan_idx; + + for (int i = 0; i < new_channels; i++) { + phy_info_freq_cfg(mode, &mode->channels[idx], &band_info->channels[i]); + idx++; + } + + phy_info->last_chan_idx = idx; + + return 0; +} + +static int phy_info_rates_cfg(struct hostapd_hw_modes *mode, + struct wpa_supp_event_supported_band *band_info) +{ + int idx; + + if (!mode || !band_info) + return -1; + + mode->num_rates = band_info->wpa_supp_n_bitrates; + + if (!mode->num_rates) + return 0; + + mode->rates = os_calloc(mode->num_rates, sizeof(int)); + + if (!mode->rates) + return -1; + + idx = 0; + + for (int i = 0; i < mode->num_rates; i++) { + if (!band_info->bitrates[i].wpa_supp_bitrate) + continue; + mode->rates[idx] = band_info->bitrates[i].wpa_supp_bitrate; + idx++; + } + + return 0; +} + + + +static void phy_info_ht_capa_cfg(struct hostapd_hw_modes *mode, u16 capa, + u8 ampdu_factor, + u8 ampdu_density, + struct wpa_supp_event_mcs_info *mcs_set) +{ + if (capa) + mode->ht_capab = (capa); + + if (ampdu_factor) + mode->a_mpdu_params |= (ampdu_factor) & WPA_SUPP_AMPDU_FACTOR_MASK; + + if (ampdu_density) + mode->a_mpdu_params |= (ampdu_density) << WPA_SUPP_AMPDU_DENSITY_SHIFT; + + if (mcs_set) { + os_memcpy(mode->mcs_set, mcs_set, sizeof(*mcs_set)); + } + +} + +static void phy_info_vht_capa_cfg(struct hostapd_hw_modes *mode, + unsigned int capa, + struct wpa_supp_event_vht_mcs_info *vht_mcs_set) +{ + if (capa) + mode->vht_capab = (capa); + + if (vht_mcs_set) { + os_memcpy(mode->vht_mcs_set, vht_mcs_set, 8); + } +} + +static int phy_info_band_cfg(struct phy_info_arg *phy_info, + struct wpa_supp_event_supported_band *band_info) +{ + struct hostapd_hw_modes *mode; + int ret; + + if (phy_info->last_mode != band_info->band) { + mode = os_realloc_array(phy_info->modes, + *phy_info->num_modes + 1, + sizeof(*mode)); + + if (!mode) { + phy_info->failed = 1; + return -1; + } + + phy_info->modes = mode; + + mode = &phy_info->modes[*(phy_info->num_modes)]; + + os_memset(mode, 0, sizeof(*mode)); + + mode->mode = NUM_HOSTAPD_MODES; + mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN | + HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN; + + /* + * Unsupported VHT MCS stream is defined as value 3, so the VHT + * MCS RX/TX map must be initialized with 0xffff to mark all 8 + * possible streams as unsupported. This will be overridden if + * driver advertises VHT support. + */ + mode->vht_mcs_set[0] = 0xff; + mode->vht_mcs_set[1] = 0xff; + mode->vht_mcs_set[4] = 0xff; + mode->vht_mcs_set[5] = 0xff; + + *(phy_info->num_modes) += 1; + + phy_info->last_mode = band_info->band; + phy_info->last_chan_idx = 0; + } + else + mode = &phy_info->modes[*(phy_info->num_modes) - 1]; + + phy_info_ht_capa_cfg(mode, band_info->ht_cap.wpa_supp_cap, + band_info->ht_cap.wpa_supp_ampdu_factor, + band_info->ht_cap.wpa_supp_ampdu_density, + &band_info->ht_cap.mcs); + + phy_info_vht_capa_cfg(mode, band_info->vht_cap.wpa_supp_cap, + &band_info->vht_cap.vht_mcs); + + ret = phy_info_freqs_cfg(phy_info, mode, band_info); + + if (ret == 0) + ret = phy_info_rates_cfg(mode, band_info); + + if (ret != 0) { + phy_info->failed = 1; + return ret; + } + + return 0; +} + +static void wpa_drv_zep_event_get_wiphy(struct zep_drv_if_ctx *if_ctx, void *band_info) +{ + if (!band_info) { + if_ctx->get_wiphy_in_progress = false; + return; + } + + phy_info_band_cfg(if_ctx->phy_info_arg, band_info); +} + +static int wpa_drv_register_frame(struct zep_drv_if_ctx *if_ctx, + u16 type, const u8 *match, size_t match_len, + bool multicast) +{ + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->register_frame) + return -1; + + return dev_ops->register_frame(if_ctx->dev_priv, type, match, match_len, false); +} + +static int wpa_drv_register_action_frame(struct zep_drv_if_ctx *if_ctx, + const u8 *match, size_t match_len) +{ + u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); + + return wpa_drv_register_frame(if_ctx, type, match, match_len, false); +} + +static int wpa_drv_mgmt_subscribe_non_ap(struct zep_drv_if_ctx *if_ctx) +{ + int ret = 0; + + /* WNM - BSS Transition Management Request */ + if (wpa_drv_register_action_frame(if_ctx, (u8 *)"\x0a\x07", 2) < 0) + ret = -1; + + return ret; +} + +static void wpa_drv_zep_event_mgmt_rx(struct zep_drv_if_ctx *if_ctx, + char *frame, int frame_len, + int frequency, int rx_signal_dbm) +{ + const struct ieee80211_mgmt *mgmt; + + union wpa_event_data event; + u16 fc, stype; + int rx_freq = 0; + + wpa_printf(MSG_MSGDUMP, "wpa_supp: Frame event"); + mgmt = (const struct ieee80211_mgmt *)frame; + + if (frame_len < 24) { + wpa_printf(MSG_DEBUG, "wpa_supp: Too short management frame"); + return; + } + + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + + os_memset(&event, 0, sizeof(event)); + + if (frequency) { + event.rx_mgmt.freq = frequency; + rx_freq = event.rx_mgmt.freq; + } + + event.rx_mgmt.frame = frame; + event.rx_mgmt.frame_len = frame_len; + event.rx_mgmt.ssi_signal = rx_signal_dbm; + + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_RX_MGMT, &event); +} + +static struct hostapd_hw_modes * +wpa_driver_wpa_supp_postprocess_modes(struct hostapd_hw_modes *modes, + u16 *num_modes) +{ + u16 m; + struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; + int i, mode11g_idx = -1; + + /* heuristic to set up modes */ + for (m = 0; m < *num_modes; m++) { + if (!modes[m].num_channels) + continue; + if (modes[m].channels[0].freq < 4000) { + modes[m].mode = HOSTAPD_MODE_IEEE80211B; + for (i = 0; i < modes[m].num_rates; i++) { + if (modes[m].rates[i] > 200) { + modes[m].mode = HOSTAPD_MODE_IEEE80211G; + break; + } + } + } else if (modes[m].channels[0].freq > 50000) + modes[m].mode = HOSTAPD_MODE_IEEE80211AD; + else + modes[m].mode = HOSTAPD_MODE_IEEE80211A; + } + + /* If only 802.11g mode is included, use it to construct matching + * 802.11b mode data. */ + + for (m = 0; m < *num_modes; m++) { + if (modes[m].mode == HOSTAPD_MODE_IEEE80211B) + return modes; /* 802.11b already included */ + if (modes[m].mode == HOSTAPD_MODE_IEEE80211G) + mode11g_idx = m; + } + + if (mode11g_idx < 0) + return modes; /* 2.4 GHz band not supported at all */ + + nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes)); + if (nmodes == NULL) + return modes; /* Could not add 802.11b mode */ + + mode = &nmodes[*num_modes]; + os_memset(mode, 0, sizeof(*mode)); + (*num_modes)++; + modes = nmodes; + + mode->mode = HOSTAPD_MODE_IEEE80211B; + mode11g = &modes[mode11g_idx]; + mode->num_channels = mode11g->num_channels; + mode->channels = os_memdup(mode11g->channels, + mode11g->num_channels * + sizeof(struct hostapd_channel_data)); + if (mode->channels == NULL) { + (*num_modes)--; + return modes; /* Could not add 802.11b mode */ + } + + mode->num_rates = 0; + mode->rates = os_malloc(4 * sizeof(int)); + if (mode->rates == NULL) { + os_free(mode->channels); + (*num_modes)--; + return modes; /* Could not add 802.11b mode */ + } + + for (i = 0; i < mode11g->num_rates; i++) { + if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 && + mode11g->rates[i] != 55 && mode11g->rates[i] != 110) + continue; + mode->rates[mode->num_rates] = mode11g->rates[i]; + mode->num_rates++; + if (mode->num_rates == 4) + break; + } + + if (mode->num_rates == 0) { + os_free(mode->channels); + os_free(mode->rates); + (*num_modes)--; + return modes; /* No 802.11b rates */ + } + + wpa_printf(MSG_DEBUG, "wpa_supp: Added 802.11b mode based on 802.11g " + "information"); + + return modes; +} + +struct hostapd_hw_modes *wpa_drv_get_hw_feature_data(void *priv, + u16 *num_modes, + u16 *flags, u8 *dfs_domain) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + int i=0; + + if_ctx = priv; + + dev_ops = if_ctx->dev_ctx->config; + + struct phy_info_arg result = { + .num_modes = num_modes, + .modes = NULL, + .last_mode = -1, + .failed = 0, + .dfs_domain = 0, + }; + + *num_modes = 0; + *flags = 0; + *dfs_domain = 0; + + if_ctx->phy_info_arg = &result; + + if_ctx->get_wiphy_in_progress = true; + + ret = dev_ops->get_wiphy(if_ctx->dev_priv); + + while ((if_ctx->get_wiphy_in_progress) && (i < SCAN_TIMEOUT)) { + k_yield(); + os_sleep(1, 0); + i++; + } + + struct hostapd_hw_modes *modes; + + *dfs_domain = result.dfs_domain; + + modes = wpa_driver_wpa_supp_postprocess_modes(result.modes, + num_modes); + + return modes; +} + static void *wpa_drv_zep_global_init(void *ctx) { struct zep_drv_ctx *drv_ctx = NULL; @@ -325,6 +764,8 @@ static void *wpa_drv_zep_init(void *ctx, callbk_fns.mgmt_tx_status = wpa_drv_zep_event_mgmt_tx_status; callbk_fns.unprot_deauth = wpa_drv_zep_event_proc_unprot_deauth; callbk_fns.unprot_disassoc = wpa_drv_zep_event_proc_unprot_disassoc; + callbk_fns.get_wiphy_res = wpa_drv_zep_event_get_wiphy; + callbk_fns.mgmt_rx = wpa_drv_zep_event_mgmt_rx; if_ctx->dev_priv = dev_ops->init(if_ctx, ifname, @@ -339,6 +780,8 @@ static void *wpa_drv_zep_init(void *ctx, goto out; } + wpa_drv_mgmt_subscribe_non_ap(if_ctx); + out: return if_ctx; } @@ -808,7 +1251,7 @@ static int wpa_drv_zep_send_action(void *priv, unsigned int freq, if_ctx = priv; dev_ops = if_ctx->dev_ctx->config; - wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (" + wpa_printf(MSG_DEBUG, "wpa_supp: Send Action frame (" "freq=%u MHz wait=%d ms no_cck=%d)", freq, wait_time, no_cck); @@ -829,6 +1272,8 @@ static int wpa_drv_zep_send_action(void *priv, unsigned int freq, wait_time, 0); } + + const struct wpa_driver_ops wpa_driver_zep_ops = { .name = "zephyr", .desc = "Zephyr wpa_supplicant driver", @@ -849,4 +1294,5 @@ const struct wpa_driver_ops wpa_driver_zep_ops = { .set_key = wpa_drv_zep_set_key, .signal_poll = wpa_drv_zep_signal_poll, .send_action = wpa_drv_zep_send_action, + .get_hw_feature_data = wpa_drv_get_hw_feature_data, }; diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 34573b5a1a..128eaa5daa 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -15,6 +15,84 @@ #include "driver.h" #include "wpa_supplicant_i.h" #include "bss.h" + +#define __WPA_SUPP_PKD __attribute__((__packed__)) + +struct wpa_supp_event_channel { +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_IR (1 << 0) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_IBSS (1 << 1) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_RADAR (1 << 2) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_HT40_MINUS (1 << 3) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_HT40_PLUS (1 << 4) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_80MHZ (1 << 5) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_160MHZ (1 << 6) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_INDOOR_ONLY (1 << 7) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_GO_CONCURRENT (1 << 8) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_20MHZ (1 << 9) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_ATTR_NO_10MHZ (1 << 10) +#define WPA_SUPP_CHAN_FLAG_FREQUENCY_DISABLED (1 << 11) + +#define WPA_SUPP_CHAN_DFS_VALID (1 << 12) +#define WPA_SUPP_CHAN_DFS_CAC_TIME_VALID (1 << 13) + unsigned short wpa_supp_flags; + signed int wpa_supp_max_power; + unsigned int wpa_supp_time; + unsigned int dfs_cac_msec; + signed char ch_valid; + unsigned short center_frequency; + signed char dfs_state; +} __WPA_SUPP_PKD; + +struct wpa_supp_event_rate { +#define WPA_SUPP_EVENT_GET_WIPHY_FLAG_RATE_SHORT_PREAMBLE (1 << 0) + unsigned short wpa_supp_flags; + unsigned short wpa_supp_bitrate; +} __WPA_SUPP_PKD; + +struct wpa_supp_event_mcs_info { +#define WPA_SUPP_HT_MCS_MASK_LEN 10 +#define WPA_SUPP_HT_MCS_RES_LEN 3 + unsigned short wpa_supp_rx_highest; + unsigned char wpa_supp_rx_mask[WPA_SUPP_HT_MCS_MASK_LEN]; + unsigned char wpa_supp_tx_params; + unsigned char wpa_supp_reserved[WPA_SUPP_HT_MCS_RES_LEN]; +} __WPA_SUPP_PKD; + +struct wpa_supp_event_sta_ht_cap { + signed int wpa_supp_ht_supported; + unsigned short wpa_supp_cap; + struct wpa_supp_event_mcs_info mcs; +#define WPA_SUPP_AMPDU_FACTOR_MASK 0x03 +#define WPA_SUPP_AMPDU_DENSITY_SHIFT 2 + unsigned char wpa_supp_ampdu_factor; + unsigned char wpa_supp_ampdu_density; +} __WPA_SUPP_PKD; + +struct wpa_supp_event_vht_mcs_info { + unsigned short rx_mcs_map; + unsigned short rx_highest; + unsigned short tx_mcs_map; + unsigned short tx_highest; +} __WPA_SUPP_PKD; + +struct wpa_supp_event_sta_vht_cap { + signed char wpa_supp_vht_supported; + unsigned int wpa_supp_cap; + struct wpa_supp_event_vht_mcs_info vht_mcs; +} __WPA_SUPP_PKD; + +struct wpa_supp_event_supported_band { + unsigned short wpa_supp_n_channels; + unsigned short wpa_supp_n_bitrates; +#define WPA_SUPP_SBAND_MAX_CHANNELS 29 +#define WPA_SUPP_SBAND_MAX_RATES 13 + struct wpa_supp_event_channel channels[WPA_SUPP_SBAND_MAX_CHANNELS]; + struct wpa_supp_event_rate bitrates[WPA_SUPP_SBAND_MAX_RATES]; + struct wpa_supp_event_sta_ht_cap ht_cap; + struct wpa_supp_event_sta_vht_cap vht_cap; + signed char band; +} __WPA_SUPP_PKD; + struct wpa_bss; struct zep_wpa_supp_mbox_msg_data { @@ -43,6 +121,9 @@ struct zep_drv_if_ctx { size_t ssid_len; unsigned char bssid[6]; bool associated; + + void *phy_info_arg; + bool get_wiphy_in_progress; }; @@ -76,6 +157,11 @@ struct zep_wpa_supp_dev_callbk_fns { void (*unprot_disassoc)(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event); + void (*get_wiphy_res)(struct zep_drv_if_ctx *if_ctx, + void *band); + + void (*mgmt_rx)(struct zep_drv_if_ctx *if_ctx, + char *frame, int frame_len, int frequency, int rx_signal_dbm); }; @@ -117,6 +203,11 @@ struct zep_wpa_supp_dev_ops { int offchanok, unsigned int wait_time, int cookie); + int (*get_wiphy)(void *if_priv); + + int (*register_frame)(void *if_priv, + u16 type, const u8 *match, size_t match_len, + bool multicast); }; #endif /* DRIVER_ZEPHYR_H */ From bd9013f8d117d4fb094307e5f591f6a93cd750cc Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 2 Dec 2022 13:01:21 +0530 Subject: [PATCH 067/150] Fix MbedTLS EC parameter A MbedTLS uses an undocumented optimization where 0/null is used for A for all NIST curves to avoid doing `-3 mod P` calculation (saves a few computations). So, instead of returning A as is, derive it using `-3 mod P` to handle the optimization. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-ec.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/crypto/crypto_mbedtls-ec.c b/src/crypto/crypto_mbedtls-ec.c index 4f62e7d862..bf3767cab8 100644 --- a/src/crypto/crypto_mbedtls-ec.c +++ b/src/crypto/crypto_mbedtls-ec.c @@ -31,6 +31,8 @@ static int f_rng(void *p_rng, unsigned char *buf, size_t len) } struct crypto_ec { + /* To WAR MbedTLS optimization as A is stored 0 but assumed "-3 mod P" internally*/ + mbedtls_mpi A; mbedtls_ecp_group group; }; @@ -41,7 +43,19 @@ int crypto_rng_wrapper(void *ctx, unsigned char *buf, size_t len) const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e) { - return (const struct crypto_bignum *)&e->group.A; + int ret; + mbedtls_mpi minus_three, one; + + mbedtls_mpi_init(&e->A); + mbedtls_mpi_init(&minus_three); + mbedtls_mpi_init(&one); + + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&minus_three, -3)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); + /* A = -3 mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&e->A, &minus_three, &one, &e->group.P, NULL)); +cleanup: + return (const struct crypto_bignum *)&e->A; } const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e) From 2b288d5a5a487a4e5c4015f0b48450a30ca6f31d Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 9 Dec 2022 00:07:26 +0530 Subject: [PATCH 068/150] Fix SAE-H2E sliding window exponentiation For some passwords using SAE-H2E the Mbedtls PWE derivation fails with invalid public key (-0x4C80) i.e., the point is not on the elliptic curve. This is because of the MbedTLS API mbedtls_mpi_exp_mod (called from sae_derive_pwe_from_pt_ecc using crypto_ec_point_mul) warns about using aliasing b/w its input and output arguments, but the general style of WPA supplicant is to pass same pointer as input and output, this causes wrong computation, but this is only checked when deriving PWE not when computing the point. The dependency of password comes in with pwd_seed which is based on both SSID and password (see "sae_derive_pt_ecc" for details) as these are used to calculate hash which is used to map to an element on the curve. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index f7fe28a921..6b1b4c5b3f 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -125,11 +125,20 @@ int crypto_bignum_exptmod( const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d) { - return mbedtls_mpi_exp_mod( - (mbedtls_mpi *)d, (const mbedtls_mpi *)a, - (const mbedtls_mpi *)b, (const mbedtls_mpi *)c, NULL) - ? -1 - : 0; + int ret; + + mbedtls_mpi res; + + mbedtls_mpi_init(&res); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + (mbedtls_mpi *)&res, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b, (const mbedtls_mpi *)c, NULL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi *)d, (const mbedtls_mpi *)&res)); + +cleanup: + mbedtls_mpi_free(&res); + return ret; + } int crypto_bignum_inverse( From 903c774b73802123e165dc001368406642d47972 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 9 Dec 2022 00:37:50 +0530 Subject: [PATCH 069/150] MbedTLS: Remove aliasing of inputs and outputs MbedTLS docs warn not to use aliasing for some inputs and outputs but only for some APIs, use an intermediate variable to avoid wrong computations. Signed-off-by: Krishna T --- src/crypto/crypto_mbedtls-bignum.c | 18 +++++++++++++----- src/crypto/crypto_mbedtls-ec.c | 6 ++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c index 6b1b4c5b3f..7c0358e6f7 100644 --- a/src/crypto/crypto_mbedtls-bignum.c +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -167,11 +167,19 @@ int crypto_bignum_div( const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { - return mbedtls_mpi_div_mpi( - (mbedtls_mpi *)c, NULL, (const mbedtls_mpi *)a, - (const mbedtls_mpi *)b) - ? -1 - : 0; + int ret; + + mbedtls_mpi res; + mbedtls_mpi_init(&res); + + MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi( + (mbedtls_mpi *)&res, NULL, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi *)c, (const mbedtls_mpi *)&res)); + +cleanup: + mbedtls_mpi_free(&res); + return ret; } int crypto_bignum_mulmod( diff --git a/src/crypto/crypto_mbedtls-ec.c b/src/crypto/crypto_mbedtls-ec.c index bf3767cab8..f79be24864 100644 --- a/src/crypto/crypto_mbedtls-ec.c +++ b/src/crypto/crypto_mbedtls-ec.c @@ -358,9 +358,10 @@ int crypto_ec_point_solve_y_coord( struct crypto_ec *e, struct crypto_ec_point *p, const struct crypto_bignum *x, int y_bit) { - mbedtls_mpi temp; + mbedtls_mpi temp, temp_no_alias; mbedtls_mpi *y_sqr, *y; mbedtls_mpi_init(&temp); + mbedtls_mpi_init(&temp_no_alias); int ret = 0; y = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); @@ -381,7 +382,8 @@ int crypto_ec_point_solve_y_coord( if (y_sqr) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&temp, &e->group.P, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp, NULL, &temp, 4)); + MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp_no_alias, NULL, &temp, 4)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&temp_no_alias, &temp)); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod(y, y_sqr, &temp, &e->group.P, NULL)); From 93f17e21540eda5d2568e68b8313555fe65b4986 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 12 Dec 2022 18:22:38 +0530 Subject: [PATCH 070/150] Add support for list_networks Useful to know the network status. Signed-off-by: Krishna T --- zephyr/src/wpa_cli.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index 3b3285ae60..997aa04966 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -129,6 +129,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( NULL, "\"\"", cmd_supplicant), + SHELL_CMD(list_networks, + NULL, + "\"\"", + cmd_supplicant), SHELL_SUBCMD_SET_END); /* Persisting with "wpa_cli" naming for compatibility with Wi-Fi From 6a9684e7b1b4b9f34bed6cdfb3220d98268b9d3e Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 12 Dec 2022 18:32:50 +0530 Subject: [PATCH 071/150] Formatting changes Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 6bf6accb0d..b805f7d804 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -255,7 +255,7 @@ static void phy_info_freq_cfg(struct hostapd_hw_modes *mode, chan->flag = 0; chan->allowed_bw = ~0; chan->dfs_cac_ms = 0; - + if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES) { chan->chan = channel; } @@ -304,7 +304,7 @@ static int phy_info_freqs_cfg(struct phy_info_arg *phy_info, return -1; new_channels = band_info->wpa_supp_n_channels; - + if (!new_channels) return 0; @@ -987,7 +987,7 @@ static int wpa_drv_zep_authenticate(void *priv, os_memcpy(if_ctx->ssid, params->ssid, params->ssid_len); - + if_ctx->ssid_len = params->ssid_len; curr_bss = wpa_bss_get(if_ctx->supp_if_ctx, params->bssid, params->ssid, params->ssid_len); @@ -1071,7 +1071,7 @@ static int _wpa_drv_zep_set_key(void *priv, } if_ctx = priv; - dev_ops = if_ctx->dev_ctx->config; + dev_ops = if_ctx->dev_ctx->config; wpa_printf(MSG_DEBUG, "%s: priv:%p alg %d addr %p key_idx %d set_tx %d seq %p " "seq_len %d key %p key_len %d\n", From 2a54d32bf170f6a7461b3244fffd4278e53d0300 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 12 Dec 2022 18:33:13 +0530 Subject: [PATCH 072/150] Set encryption capabilities These capabilities need to be advertised to the WPA supplicant to enable encryption, else, some encryptions e.g., WEP will not be supported. Also, move the capabilities setting to the driver by introducing a new op, though we do yet have the provision to query these from the RPU. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 35 ++++++++++++++++++++++++++++------- src/drivers/driver_zephyr.h | 3 +++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index b805f7d804..8674b18aaa 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -1124,14 +1124,35 @@ static int wpa_drv_zep_set_key(void* priv, static int wpa_drv_zep_get_capa(void *priv, struct wpa_driver_capa *capa) { - os_memset(capa, 0, sizeof(*capa)); - /* Use SME */ - capa->flags = 0; - capa->flags |= WPA_DRIVER_FLAGS_SME; - capa->flags |= WPA_DRIVER_FLAGS_SAE; - capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_RRM; - return 0; + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if ((!priv) || (!capa)) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops->get_capa) { + wpa_printf(MSG_ERROR, "%s: get_capa op not supported\n", __func__); + goto out; + } + + ret = dev_ops->get_capa(if_ctx->dev_priv, + capa); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: get_capa op failed\n", __func__); + goto out; + } + + ret = 0; +out: + return ret; } diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 128eaa5daa..9b7721966a 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -208,6 +208,9 @@ struct zep_wpa_supp_dev_ops { int (*register_frame)(void *if_priv, u16 type, const u8 *match, size_t match_len, bool multicast); + + int (*get_capa)(void *if_priv, + struct wpa_driver_capa *capa); }; #endif /* DRIVER_ZEPHYR_H */ From 28ac1ba828300da01dd03e25e2284ebcdd3ecfcb Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 13 Dec 2022 15:59:12 +0530 Subject: [PATCH 073/150] Fix reply processing In case of failure the reply length is still positive, so, check for the length and reply message for success/failure. Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface.c | 2 ++ wpa_supplicant/wpa_cli.c | 16 +++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2d1c14fbab..dae1ec4145 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11478,6 +11478,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply = os_malloc(reply_size); if (reply == NULL) { + wpa_printf(MSG_ERROR, "ctrl_iface: reply malloc of %d failed %s", + reply_size, strerror(errno)); *resp_len = 1; return NULL; } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 211a8eab3a..1961367ff5 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -307,14 +307,16 @@ static int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) } repl_buf = wpa_supplicant_ctrl_iface_process (wpa_s, (char *) cmd, &len); - - if (len > 0 && os_strcmp(repl_buf, "OK") != 0) - printf ("Reply: %s\n", repl_buf); - - if (len > 0 && repl_buf) - os_free(repl_buf); - return 0; + if (repl_buf) { + printf("%s\n", repl_buf); + } else { + printf("Reply: unknown failure\n"); + } + + os_free(repl_buf); + + return 0; } From ace84528b94f5636bb226f1690a6752d5bbd8fbb Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 13 Dec 2022 16:03:38 +0530 Subject: [PATCH 074/150] Reduce the control interface reply size We only support a few wpa_cli commands in Zephyr, and the lengthiest command is "status" which doesn't need 4K buffer, so, reduce to 1K to avoid memory allocation failures. Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index dae1ec4145..da28100bd1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11449,7 +11449,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { char *reply; - const int reply_size = 4096; + const int reply_size = 1024; int reply_len; if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || From c1f1e0593d5bde73ba5d512b44fb765472829574 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 19 Dec 2022 22:30:21 +0530 Subject: [PATCH 075/150] Fix WEP key installation sequence number is only needed for TKIP/CCMP, and is optional, remove enforcing it as a mandatory parameter. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 8674b18aaa..b2cc44da28 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -1062,11 +1062,8 @@ static int _wpa_drv_zep_set_key(void *priv, wpa_printf(MSG_ERROR, "%s: Invalid handle\n", __func__); goto out; } - if ((alg != WPA_ALG_NONE) && - ((!seq) || (!key))) { - wpa_printf(MSG_ERROR, - "%s: Missing mandatory params\n", - __func__); + if (alg != WPA_ALG_NONE && !key) { + wpa_printf(MSG_ERROR, "%s: Missing key\n", __func__); goto out; } From dd364272f6341618a8352b4618202887b1908354 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 5 Jan 2023 21:39:47 +0530 Subject: [PATCH 076/150] Implement connect and disconnect events to Zephyr These are needed for LED support for STA sample to track WPA supplicant connection state changes and blink LEDs. Signed-off-by: Krishna T --- wpa_supplicant/events.c | 7 +++++++ wpa_supplicant/wpa_supplicant.c | 7 +++++++ zephyr/CMakeLists.txt | 1 + zephyr/src/supp_events.c | 29 +++++++++++++++++++++++++++++ zephyr/src/supp_events.h | 8 ++++++++ 5 files changed, 52 insertions(+) create mode 100644 zephyr/src/supp_events.c create mode 100644 zephyr/src/supp_events.h diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 7fbc74484c..04092dfc08 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -6,6 +6,10 @@ * See README for more details. */ +#ifdef CONFIG_ZEPHYR +#include +#endif /* CONFIG_ZEPHYR */ + #include "includes.h" #include "common.h" @@ -3584,6 +3588,9 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, " reason=%d%s", MAC2STR(bssid), reason_code, locally_generated ? " locally_generated=1" : ""); +#ifdef CONFIG_ZEPHYR + send_wifi_mgmt_event(wpa_s->ifname, NET_EVENT_WIFI_CMD_DISCONNECT_RESULT, 0); +#endif /* CONFIG_ZEPHYR */ } } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 5b8ec2f705..46f73c987f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -10,6 +10,10 @@ * functions for managing network connections. */ +#ifdef CONFIG_ZEPHYR +#include +#endif /* CONFIG_ZEPHYR */ + #include "includes.h" #ifdef CONFIG_MATCH_IFACE #include @@ -1023,6 +1027,9 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, ssid && ssid->id_str ? ssid->id_str : "", fils_hlp_sent ? " FILS_HLP_SENT" : ""); #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ +#ifdef CONFIG_ZEPHYR + send_wifi_mgmt_event(wpa_s->ifname, NET_EVENT_WIFI_CMD_CONNECT_RESULT, 0); +#endif /* CONFIG_ZEPHYR */ wpas_clear_temp_disabled(wpa_s, ssid, 1); wpa_s->consecutive_conn_failures = 0; wpa_s->new_connection = 0; diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 46570c9ba9..c95c16fec0 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -94,6 +94,7 @@ zephyr_library_sources( src/supp_main.c src/utils/wpa_debug.c src/supp_api.c + src/supp_events.c ) zephyr_library_sources_ifdef(CONFIG_WPA_CLI diff --git a/zephyr/src/supp_events.c b/zephyr/src/supp_events.c new file mode 100644 index 0000000000..d2bddd50f4 --- /dev/null +++ b/zephyr/src/supp_events.c @@ -0,0 +1,29 @@ +#include "supp_events.h" + +#include "includes.h" +#include "common.h" + +int send_wifi_mgmt_event(const char *ifname, enum net_event_wifi_cmd event, int status) +{ + const struct device *dev = device_get_binding(ifname); + struct net_if *iface = net_if_lookup_by_dev(dev); + + if (!iface) { + wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname); + return -ENODEV; + } + + switch (event) { + case NET_EVENT_WIFI_CMD_CONNECT_RESULT: + wifi_mgmt_raise_connect_result_event(iface, status); + break; + case NET_EVENT_WIFI_CMD_DISCONNECT_RESULT: + wifi_mgmt_raise_disconnect_result_event(iface, status); + break; + default: + wpa_printf(MSG_ERROR, "Unsupported event %d", event); + return -EINVAL; + } + + return 0; +} diff --git a/zephyr/src/supp_events.h b/zephyr/src/supp_events.h new file mode 100644 index 0000000000..4290fea348 --- /dev/null +++ b/zephyr/src/supp_events.h @@ -0,0 +1,8 @@ +#ifndef __SUPP_EVENTS_H__ +#define __SUPP_EVENTS_H__ + +#include + +int send_wifi_mgmt_event(const char *ifname, enum net_event_wifi_cmd event, int status); + +#endif /* __SUPP_EVENTS_H__ */ \ No newline at end of file From 9b039d8427edaecd59370c04c8dd646b3100025f Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 10 Jan 2023 01:15:03 +0530 Subject: [PATCH 077/150] Fix BSS age underflow While checking for stale BSSes, the current time is used as a basis and then based on age the stale check time is calculated, but if this is done too early in the boot and if either BOOTTIME/MONOTONIC (the one Zephyr uses by default) are used then the stale check time underflows and goes to future causing active BSS entries in the scan to be treated as stale and flushed. Fix this by adding a check before calculating stale time and ignore this check till the system reaches the BSS expiration time (this would never happen with REALTIME clock). Signed-off-by: Krishna T Signed-off-by: Sridhar Nuvusetty --- wpa_supplicant/bss.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index e13783ce19..65b58bd790 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -936,6 +936,10 @@ void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age) return; os_get_reltime(&t); + + if (t.sec < age) + return; /* avoid underflow */ + t.sec -= age; dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { From fdb6774206906bbc8434e030c7f01e7fa321fe05 Mon Sep 17 00:00:00 2001 From: Sachin D Kulkarni Date: Mon, 9 Jan 2023 18:27:23 +0530 Subject: [PATCH 078/150] Add interface up check for connect Allow connect only if interface is up. Signed-off-by: Sridhar Nuvusetty Signed-off-by: Sachin D Kulkarni --- zephyr/src/supp_api.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 1c556b9c97..bf7093d884 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -158,6 +158,13 @@ int zephyr_supp_connect(const struct device *dev, struct wpa_supplicant *wpa_s; int ret = 0; + if (!net_if_is_up(net_if_lookup_by_dev(dev))) { + wpa_printf(MSG_ERROR, + "Interface %s is down, dropping connect", + dev->name); + return -1; + } + k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); wpa_s = get_wpa_s_handle(dev); From 15af888aeed5e960a265d0bfafd6dc2eb5562b56 Mon Sep 17 00:00:00 2001 From: Sachin D Kulkarni Date: Mon, 9 Jan 2023 18:30:21 +0530 Subject: [PATCH 079/150] Add callback for MAC address change Allow callback to inform wpa_supplicant of a MAC address change on an interface. Signed-off-by: Sridhar Nuvusetty Signed-off-by: Sachin D Kulkarni --- src/drivers/driver_zephyr.c | 8 ++++++++ src/drivers/driver_zephyr.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index b2cc44da28..7b9d37c1b4 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -35,6 +35,13 @@ void wpa_supplicant_event_wrapper(void *ctx, send_wpa_supplicant_event(&msg); } +void wpa_drv_zep_event_mac_changed(struct zep_drv_if_ctx *if_ctx) +{ + wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, + EVENT_INTERFACE_MAC_CHANGED, + NULL); +} + static int wpa_drv_zep_abort_scan(void *priv, u64 scan_cookie) { @@ -766,6 +773,7 @@ static void *wpa_drv_zep_init(void *ctx, callbk_fns.unprot_disassoc = wpa_drv_zep_event_proc_unprot_disassoc; callbk_fns.get_wiphy_res = wpa_drv_zep_event_get_wiphy; callbk_fns.mgmt_rx = wpa_drv_zep_event_mgmt_rx; + callbk_fns.mac_changed = wpa_drv_zep_event_mac_changed; if_ctx->dev_priv = dev_ops->init(if_ctx, ifname, diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 9b7721966a..8ef2a73f62 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -162,6 +162,8 @@ struct zep_wpa_supp_dev_callbk_fns { void (*mgmt_rx)(struct zep_drv_if_ctx *if_ctx, char *frame, int frame_len, int frequency, int rx_signal_dbm); + + void (*mac_changed)(struct zep_drv_if_ctx *if_ctx); }; From 00da43beb860447a5f0353647c9d91d8954f2065 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Thu, 12 Jan 2023 03:22:54 +0530 Subject: [PATCH 080/150] Mark WPA supplicant as experimental This is needed for automated software maturity. Signed-off-by: Krishna T --- zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 5b6baeea1b..7499a2dc55 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -12,6 +12,7 @@ config WPA_SUPP select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT + select EXPERIMENTAL help WPA supplicant implements 802.1X related functions. From 7856cabe59a96466cafd27cad7e2fed0bb18cfc5 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 17 Jan 2023 14:56:19 +0530 Subject: [PATCH 081/150] Fix duplicate (dis)connection events Now that WPA supplicant sends events to Zephyr directly to handle AP initiated (dis)connection events, remove sending the events from Wi-Fi management wrapper to avoid sending duplicate events. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index bf7093d884..999418095b 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -121,15 +121,6 @@ static void supp_shell_connect_status(struct k_work *work) return; } out: - if (ctrl->requested_op == CONNECT) { - wifi_mgmt_raise_connect_result_event(net_if_lookup_by_dev(ctrl->dev), status); - } else if (ctrl->requested_op == DISCONNECT) { - /* Disconnect is a synchronous operation i.e., we are already disconnected - * we are just using this to post net_mgmt event asynchronously. - */ - wifi_mgmt_raise_disconnect_result_event(net_if_lookup_by_dev(ctrl->dev), 0); - } - /* The connection handling is done, so reset the counter (connection timeout) */ seconds_counter = 0; ctrl->status_thread_state = STATUS_THREAD_STOPPED; From fc38654592971a7a214344ca6ac16bc16848b4c7 Mon Sep 17 00:00:00 2001 From: krishna T Date: Sat, 21 Jan 2023 21:57:16 +0530 Subject: [PATCH 082/150] Rename the namespace Use z_wpa_supplicant as the name space instead of zephyr_supp. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 6 +++--- zephyr/src/supp_api.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 999418095b..f9b3cfbf55 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -141,7 +141,7 @@ static inline void wpa_supp_restart_status_work(void) } -int zephyr_supp_connect(const struct device *dev, +int z_wpa_supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params) { struct wpa_ssid *ssid = NULL; @@ -272,7 +272,7 @@ int zephyr_supp_connect(const struct device *dev, return ret; } -int zephyr_supp_disconnect(const struct device *dev) +int z_wpa_supplicant_disconnect(const struct device *dev) { struct wpa_supplicant *wpa_s; int ret = 0; @@ -328,7 +328,7 @@ static inline enum wifi_security_type wpas_key_mgmt_to_zephyr(int key_mgmt) } -int zephyr_supp_status(const struct device *dev, +int z_wpa_supplicant_status(const struct device *dev, struct wifi_iface_status *status) { struct wpa_supplicant *wpa_s; diff --git a/zephyr/src/supp_api.h b/zephyr/src/supp_api.h index 48c6c22bb7..7568124887 100644 --- a/zephyr/src/supp_api.h +++ b/zephyr/src/supp_api.h @@ -21,7 +21,7 @@ * * @return: 0 for OK; -1 for ERROR */ -int zephyr_supp_connect(const struct device *dev, +int z_wpa_supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params); /** * @brief Forces station to disconnect and stops any subsequent scan @@ -31,16 +31,16 @@ int zephyr_supp_connect(const struct device *dev, * * @return: 0 for OK; -1 for ERROR */ -int zephyr_supp_disconnect(const struct device *dev); +int z_wpa_supplicant_disconnect(const struct device *dev); /** * @brief * * @param iface_name: Wi-Fi interface name to use * @param wifi_iface_status: Status structure to fill - * + * * @return: 0 for OK; -1 for ERROR */ -int zephyr_supp_status(const struct device *dev, +int z_wpa_supplicant_status(const struct device *dev, struct wifi_iface_status *status); #endif /* ZEPHYR_SUPP_MGMT_H */ From ea26378a32c1325776b54422a051372424cfdae0 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 23 Jan 2023 00:40:21 +0530 Subject: [PATCH 083/150] Add support for WPA CLI zephyr In Linux WPA CLI is a standalone application that uses sockets to communicate with ctrl_iface (uses Eloop), in Zephyr we have replaced sockets with direct function calls, but this introduces concurrency as we don't go through Eloop which causes instability and crashes esp. in the deinitialization path. Implement Zephyr's version of WPA CLI and control interface using socketpair UNIX style sockets, here WPA CLI can be invoked as a standard function rather than an executable. To avoid code duplication move all commands processing to a separate file that can be used by wpa_cli application and also wpa_cli_zephyr library (all other changes to wpa_cli are restored). Signed-off-by: Krishna T --- src/common/wpa_ctrl.c | 33 +- src/common/wpa_ctrl.h | 16 + src/utils/edit_simple.c | 3 + wpa_supplicant/ctrl_iface.c | 1 - wpa_supplicant/ctrl_iface.h | 2 +- wpa_supplicant/ctrl_iface_zephyr.c | 133 + wpa_supplicant/ctrl_iface_zephyr.h | 30 + wpa_supplicant/wpa_cli.c | 4143 ++-------------------------- wpa_supplicant/wpa_cli_cmds.c | 3692 +++++++++++++++++++++++++ wpa_supplicant/wpa_cli_zephyr.c | 340 +++ wpa_supplicant/wpa_cli_zephyr.h | 38 + wpa_supplicant/wpa_supplicant.c | 2 - zephyr/CMakeLists.txt | 9 +- 13 files changed, 4466 insertions(+), 3976 deletions(-) create mode 100644 wpa_supplicant/ctrl_iface_zephyr.c create mode 100644 wpa_supplicant/ctrl_iface_zephyr.h create mode 100644 wpa_supplicant/wpa_cli_cmds.c create mode 100644 wpa_supplicant/wpa_cli_zephyr.c create mode 100644 wpa_supplicant/wpa_cli_zephyr.h diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c index 5f16bca492..5107837e82 100644 --- a/src/common/wpa_ctrl.c +++ b/src/common/wpa_ctrl.c @@ -13,7 +13,9 @@ #ifdef CONFIG_CTRL_IFACE_UNIX #include #include +#ifndef CONFIG_ZEPHYR #include +#endif #include #include #endif /* CONFIG_CTRL_IFACE_UNIX */ @@ -35,7 +37,7 @@ #include "wpa_ctrl.h" #include "common.h" -#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) +#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_ZEPHYR) #define CTRL_IFACE_SOCKET #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ @@ -71,6 +73,9 @@ struct wpa_ctrl { #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE HANDLE pipe; #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ +#ifdef CONFIG_CTRL_IFACE_ZEPHYR + int s; +#endif /* CONFIG_CTRL_IFACE_ZEPHYR */ }; @@ -578,6 +583,32 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, } #endif /* CTRL_IFACE_SOCKET */ +#ifdef CONFIG_CTRL_IFACE_ZEPHYR +struct wpa_ctrl * wpa_ctrl_open(const int sock) +{ + struct wpa_ctrl *ctrl; + + if (sock < 0) { + wpa_printf(MSG_ERROR, "Invalid socket"); + return NULL; + } + + ctrl = os_zalloc(sizeof(*ctrl)); + if (ctrl == NULL) + return NULL; + + /* We use one of the socketpair opened in ctrl_iface_zephyr.c */ + ctrl->s = sock; + + return ctrl; +} + +void wpa_ctrl_close(struct wpa_ctrl *ctrl) +{ + close(ctrl->s); + os_free(ctrl); +} +#endif static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) { diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 3d3a62a17c..efa85fa826 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -12,6 +12,8 @@ #ifdef __cplusplus extern "C" { #endif +extern struct wpa_ctrl *ctrl_conn; +extern char *ifname_prefix; /* wpa_supplicant control interface - fixed message prefixes */ @@ -476,6 +478,17 @@ enum wpa_vendor_elem_frame { /* wpa_supplicant/hostapd control interface access */ +#ifdef CONFIG_CTRL_IFACE_ZEPHYR +/** + * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd + * @sock: one of the pair of UNIX domain socket (socketpair) + * Returns: Pointer to abstract control interface data or %NULL on failure + * + * This function is used to open a control interface to wpa_supplicant/hostapd + * using a connected socketpair. + */ +struct wpa_ctrl * wpa_ctrl_open(const int sock); +#else /** * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. @@ -487,6 +500,7 @@ enum wpa_vendor_elem_frame { * interface need to use matching path configuration. */ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); +#endif /** * wpa_ctrl_open2 - Open a control interface to wpa_supplicant/hostapd @@ -634,6 +648,8 @@ void wpa_ctrl_cleanup(void); char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl); #endif /* CONFIG_CTRL_IFACE_UDP */ +int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd); +int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]); #ifdef __cplusplus } diff --git a/src/utils/edit_simple.c b/src/utils/edit_simple.c index 2ffd1a2a2b..5f0cc81089 100644 --- a/src/utils/edit_simple.c +++ b/src/utils/edit_simple.c @@ -13,6 +13,9 @@ #include "edit.h" +#ifdef CONFIG_ZEPHYR +#define STDIN_FILENO 1 +#endif #define CMD_BUF_LEN 4096 static char cmdbuf[CMD_BUF_LEN]; static int cmdbuf_pos = 0; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index da28100bd1..d6f6ad2fff 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11484,7 +11484,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, return NULL; } - memset(reply, '\0', reply_size); os_memcpy(reply, "OK\n", 3); reply_len = 3; diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h index dfbd25a03b..79135db459 100644 --- a/wpa_supplicant/ctrl_iface.h +++ b/wpa_supplicant/ctrl_iface.h @@ -12,7 +12,7 @@ #ifdef CONFIG_CTRL_IFACE #ifndef CTRL_IFACE_MAX_LEN -#define CTRL_IFACE_MAX_LEN 8192 +#define CTRL_IFACE_MAX_LEN 4096 #endif /* CTRL_IFACE_MAX_LEN */ /* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ diff --git a/wpa_supplicant/ctrl_iface_zephyr.c b/wpa_supplicant/ctrl_iface_zephyr.c new file mode 100644 index 0000000000..4b3bca27c3 --- /dev/null +++ b/wpa_supplicant/ctrl_iface_zephyr.c @@ -0,0 +1,133 @@ +/* + * WPA Supplicant / Zephyr socket pair -based control interface + * Copyright (c) 2022, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "ctrl_iface_zephyr.h" + +static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, + void *sock_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + char *buf, *pos; + int res; + char *reply = NULL; + size_t reply_len = 0; + + buf = os_zalloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recv(sock, buf, CTRL_IFACE_MAX_LEN, 0); + if (res < 0) { + wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", + strerror(errno)); + os_free(buf); + return; + } + + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } + buf[res] = '\0'; + + pos = buf; + while (*pos == ' ') + pos++; + + reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, + &reply_len); + + if (reply) { + send(sock, reply, reply_len, 0); + os_free(reply); + } else if (reply_len == 1) { + send(sock, "FAIL\n", 5, 0); + } else if (reply_len == 2) { + send(sock, "OK\n", 3, 0); + } + + os_free(buf); +} + + +struct ctrl_iface_priv * +wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) +{ + struct ctrl_iface_priv *priv; + int ret; + + priv = os_zalloc(sizeof(*priv)); + if (priv == NULL) + return NULL; + priv->wpa_s = wpa_s; + memset(priv->sock_pair, -1, sizeof(priv->sock_pair)); + + if (wpa_s->conf->ctrl_interface == NULL) + return priv; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, priv->sock_pair); + if (ret != 0) { + wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); + goto fail; + } + + os_free(wpa_s->conf->ctrl_interface); + wpa_s->conf->ctrl_interface = os_strdup("zephyr:"); + if (!wpa_s->conf->ctrl_interface) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface"); + goto fail; + } + + eloop_register_read_sock(priv->sock_pair[1], wpa_supplicant_ctrl_iface_receive, + wpa_s, priv); + + return priv; + +fail: + if (priv->sock_pair[0] >= 0) + close(priv->sock_pair[0]); + if (priv->sock_pair[1] >= 0) + close(priv->sock_pair[1]); + os_free(priv); + return NULL; +} + + +void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s, + struct ctrl_iface_priv *priv) +{ + if (!priv) + return; + + if (priv->sock_pair[0] > -1) { + eloop_unregister_read_sock(priv->sock_pair[0]); + close(priv->sock_pair[0]); + priv->sock_pair[0] = -1; + } + + if (priv->sock_pair[1] >= 0) + close(priv->sock_pair[1]); + + os_free(priv); +} + +void +wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) +{ +} + +struct ctrl_iface_global_priv * +wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) +{ + return (void *) 1; +} + +void +wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) +{ +} \ No newline at end of file diff --git a/wpa_supplicant/ctrl_iface_zephyr.h b/wpa_supplicant/ctrl_iface_zephyr.h new file mode 100644 index 0000000000..bad0102640 --- /dev/null +++ b/wpa_supplicant/ctrl_iface_zephyr.h @@ -0,0 +1,30 @@ +/* + * WPA Supplicant / Zephyr socket pair -based control interface + * Copyright (c) 2022, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +/* Per-interface ctrl_iface */ +#include "includes.h" + +#include "common.h" +#include "eloop.h" +#include "config.h" +#include "eapol_supp/eapol_supp_sm.h" +#include "wpa_supplicant_i.h" +#include "ctrl_iface.h" +#include "common/wpa_ctrl.h" + +struct ctrl_iface_priv { + struct wpa_supplicant *wpa_s; + /* 0 - wpa_cli, 1 - ctrl_iface */ + int sock_pair[2]; +}; + +struct ctrl_iface_global_priv { + struct wpa_global *global; + /* 0 - wpa_cli, 1 - ctrl_iface */ + int sock_pair[2]; +}; + diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 1961367ff5..298d9b868e 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -10,7 +10,6 @@ #ifdef CONFIG_CTRL_IFACE -#include #ifdef CONFIG_CTRL_IFACE_UNIX #include #endif /* CONFIG_CTRL_IFACE_UNIX */ @@ -21,3186 +20,211 @@ #include "utils/eloop.h" #include "utils/edit.h" #include "utils/list.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" #include "common/version.h" #include "common/ieee802_11_defs.h" #ifdef ANDROID #include #endif /* ANDROID */ -#define CMD_BUF_LEN 4096 static const char *const wpa_cli_version = "wpa_cli v" VERSION_STR "\n" "Copyright (c) 2004-2022, Jouni Malinen and contributors"; -#define VENDOR_ELEM_FRAME_ID \ - " 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \ - "3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \ - "7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \ - "11: Assoc Req (P2P), 12: Assoc Resp (P2P)" +struct wpa_ctrl *ctrl_conn; +char *ifname_prefix = NULL; -static struct wpa_ctrl *ctrl_conn; -#ifdef notyet static struct wpa_ctrl *mon_conn; static int wpa_cli_quit = 0; -#endif /* notyet */ -#ifdef INTERACTIVE static int wpa_cli_attached = 0; static int wpa_cli_connected = -1; static int wpa_cli_last_id = 0; -#endif /* INTERACTIVE */ #ifndef CONFIG_CTRL_IFACE_DIR #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant" #endif /* CONFIG_CTRL_IFACE_DIR */ static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR; static const char *client_socket_dir = NULL; static char *ctrl_ifname = NULL; -#ifndef CONFIG_ZEPHYR static const char *global = NULL; -#else -extern struct wpa_global *global; -#endif static const char *pid_file = NULL; static const char *action_file = NULL; static int reconnect = 0; static int ping_interval = 5; static int interactive = 0; -static char *ifname_prefix = NULL; - -static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */ -static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */ -static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */ -static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */ -static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */ -static DEFINE_DL_LIST(creds); /* struct cli_txt_entry */ -#ifdef CONFIG_AP -static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */ -#endif /* CONFIG_AP */ - - -static void print_help(const char *cmd); -#ifdef notyet -static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx); -static void wpa_cli_close_connection(void); -static char * wpa_cli_get_default_ifname(void); -static char ** wpa_list_cmd_list(void); -static void update_stations(struct wpa_ctrl *ctrl); -static void update_ifnames(struct wpa_ctrl *ctrl); -#endif /* notyet */ -static void update_creds(struct wpa_ctrl *ctrl); -static void update_networks(struct wpa_ctrl *ctrl); - - -static void usage(void) -{ - printf("wpa_cli [-p] [-i] [-hvBr] " - "[-a] \\\n" - " [-P] [-g] [-G] " - "\\\n" - " [-s] " - "[command..]\n" - " -h = help (show this usage text)\n" - " -v = shown version information\n" - " -a = run in daemon mode executing the action file based on " - "events from\n" - " wpa_supplicant\n" - " -r = try to reconnect when client socket is disconnected.\n" - " This is useful only when used with -a.\n" - " -B = run a daemon in the background\n" - " default path: " CONFIG_CTRL_IFACE_DIR "\n" - " default interface: first interface found in socket path\n"); - print_help(NULL); -} - -#ifdef INTERACTIVE -static int wpa_cli_show_event(const char *event) -{ - const char *start; - - start = os_strchr(event, '>'); - if (start == NULL) - return 1; - - start++; - /* - * Skip BSS added/removed events since they can be relatively frequent - * and are likely of not much use for an interactive user. - */ - if (str_starts(start, WPA_EVENT_BSS_ADDED) || - str_starts(start, WPA_EVENT_BSS_REMOVED)) - return 0; - - return 1; -} - -static int wpa_cli_open_connection(const char *ifname, int attach) -{ -#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) - ctrl_conn = wpa_ctrl_open(ifname); - if (ctrl_conn == NULL) - return -1; - - if (attach && interactive) - mon_conn = wpa_ctrl_open(ifname); - else - mon_conn = NULL; -#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ - char *cfile = NULL; - int flen, res; - - if (ifname == NULL) - return -1; - -#ifdef ANDROID - if (access(ctrl_iface_dir, F_OK) < 0) { - cfile = os_strdup(ifname); - if (cfile == NULL) - return -1; - } -#endif /* ANDROID */ - - if (client_socket_dir && client_socket_dir[0] && - access(client_socket_dir, F_OK) < 0) { - perror(client_socket_dir); - os_free(cfile); - return -1; - } - - if (cfile == NULL) { - flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; - cfile = os_malloc(flen); - if (cfile == NULL) - return -1; - res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, - ifname); - if (os_snprintf_error(flen, res)) { - os_free(cfile); - return -1; - } - } - - ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir); - if (ctrl_conn == NULL) { - os_free(cfile); - return -1; - } - - if (attach && interactive) - mon_conn = wpa_ctrl_open2(cfile, client_socket_dir); - else - mon_conn = NULL; - os_free(cfile); -#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ - - if (mon_conn) { - if (wpa_ctrl_attach(mon_conn) == 0) { - wpa_cli_attached = 1; - if (interactive) - eloop_register_read_sock( - wpa_ctrl_get_fd(mon_conn), - wpa_cli_mon_receive, NULL, NULL); - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - wpa_cli_close_connection(); - return -1; - } - } - - return 0; -} - -static void wpa_cli_close_connection(void) -{ - if (ctrl_conn == NULL) - return; - - if (wpa_cli_attached) { - wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); - wpa_cli_attached = 0; - } - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - if (mon_conn) { - eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn)); - wpa_ctrl_close(mon_conn); - mon_conn = NULL; - } -} -#endif /* INTERACTIVE */ - -static void wpa_cli_msg_cb(char *msg, size_t len) -{ - printf("%s\n", msg); -} - -#ifdef INTERACTIVE -static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print) -{ - char * buf = NULL; - unsigned int buf_size = CMD_BUF_LEN; - size_t len; - int ret; - - buf = os_zalloc(sizeof(u8) * buf_size); - if (!buf){ - printf ("Failed to allocate mem for command buf\n"); - return -1; - } - if (ctrl_conn == NULL) { - printf("Not connected to wpa_supplicant - command dropped.\n"); - ret = -1; - goto err; - } - if (ifname_prefix) { - os_snprintf(buf, buf_size, "IFNAME=%s %s", - ifname_prefix, cmd); - buf[buf_size - 1] = '\0'; - cmd = buf; - } - len = buf_size - 1; - ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, - wpa_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - ret = -2; - goto err; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - ret = -1; - goto err; - } - if (print) { - buf[len] = '\0'; - printf("%s", buf); - if (interactive && len > 0 && buf[len - 1] != '\n') - printf("\n"); - } - return 0; -err: - os_free(buf); - return ret; -} -#endif /* INTERACTIVE */ - -static int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) -{ - - char * repl_buf; - int len = 0; /* len of the reply */ - char *ifname; - struct wpa_supplicant *wpa_s; - - if (ifname_prefix) { - ifname = ifname_prefix; - } else { - /* Default */ - ifname = "wlan0"; - } - - wpa_s = wpa_supplicant_get_iface(global, ifname); - if (!wpa_s) { - printf("Unable to find the interface: %s, quitting", ifname); - return -1; - } - - repl_buf = wpa_supplicant_ctrl_iface_process (wpa_s, (char *) cmd, &len); - - if (repl_buf) { - printf("%s\n", repl_buf); - } else { - printf("Reply: unknown failure\n"); - } - - os_free(repl_buf); - - return 0; -} - - -static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, - int argc, char *argv[]) -{ - char * buf = NULL; - int ret = 0; - if (argc < min_args) { - printf("Invalid %s command - at least %d argument%s " - "required.\n", cmd, min_args, - min_args > 1 ? "s are" : " is"); - return -1; - } - buf = os_zalloc(sizeof(char) * CMD_BUF_LEN); - if (!buf){ - printf ("Failed to allocate mem for command buf\n"); - return -1; - } - memset(buf, '\0', CMD_BUF_LEN); - if (write_cmd(buf, CMD_BUF_LEN, cmd, argc-1, argv) < 0){ - ret = -1; - goto out; - } - ret = wpa_ctrl_command(ctrl, buf); - - out: - - if (buf) - os_free(buf); - - return ret; -} - - -static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "IFNAME"); -} - - -static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc > 0 && os_strcmp(argv[0], "verbose") == 0) - return wpa_ctrl_command(ctrl, "STATUS-VERBOSE"); - if (argc > 0 && os_strcmp(argv[0], "wps") == 0) - return wpa_ctrl_command(ctrl, "STATUS-WPS"); - if (argc > 0 && os_strcmp(argv[0], "driver") == 0) - return wpa_ctrl_command(ctrl, "STATUS-DRIVER"); -#ifdef ANDROID - if (argc > 0 && os_strcmp(argv[0], "no_events") == 0) - return wpa_ctrl_command(ctrl, "STATUS-NO_EVENTS"); -#endif /* ANDROID */ - return wpa_ctrl_command(ctrl, "STATUS"); -} - - -static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PING"); -} - - -static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RELOG"); -} - - -static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv); -} - - -static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "MIB"); -} - - -static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PMKSA"); -} - - -static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PMKSA_FLUSH"); -} - - -#ifdef CONFIG_PMKSA_CACHE_EXTERNAL - -static int wpa_cli_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PMKSA_GET", 1, argc, argv); -} - - -static int wpa_cli_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PMKSA_ADD", 8, argc, argv); -} - - -#ifdef CONFIG_MESH - -static int wpa_cli_mesh_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_PMKSA_GET", 1, argc, argv); -} - - -static int wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_PMKSA_ADD", 4, argc, argv); -} - -#endif /* CONFIG_MESH */ -#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ - -#ifdef notyet -static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - print_help(argc > 0 ? argv[0] : NULL); - return 0; -} - - -static char ** wpa_cli_complete_help(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = wpa_list_cmd_list(); - break; - } - - return res; -} - - -static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s\n\n%s\n", wpa_cli_version, cli_full_license); - return 0; -} - - -static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - wpa_cli_quit = 1; - if (interactive) - eloop_terminate(); - return 0; -} -#endif /* notyet */ - -static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc == 1) { - res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]); - if (os_snprintf_error(sizeof(cmd), res)) { - printf("Too long SET command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); - } - - return wpa_cli_cmd(ctrl, "SET", 2, argc, argv); -} - - -static char ** wpa_cli_complete_set(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - const char *fields[] = { - /* runtime values */ - "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod", - "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime", - "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout", - "wps_fragment_size", "wps_version_number", "ampdu", - "tdls_testing", "tdls_disabled", "pno", "radio_disabled", - "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps", - "no_keep_alive", - /* global configuration parameters */ -#ifdef CONFIG_CTRL_IFACE - "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group", -#endif /* CONFIG_CTRL_IFACE */ - "eapol_version", "ap_scan", "bgscan", -#ifdef CONFIG_MESH - "user_mpm", "max_peer_links", "mesh_max_inactivity", - "dot11RSNASAERetransPeriod", -#endif /* CONFIG_MESH */ - "disable_scan_offload", "fast_reauth", "opensc_engine_path", - "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers", - "pcsc_reader", "pcsc_pin", "external_sim", "driver_param", - "dot11RSNAConfigPMKLifetime", - "dot11RSNAConfigPMKReauthThreshold", - "dot11RSNAConfigSATimeout", -#ifndef CONFIG_NO_CONFIG_WRITE - "update_config", -#endif /* CONFIG_NO_CONFIG_WRITE */ - "load_dynamic_eap", -#ifdef CONFIG_WPS - "uuid", "device_name", "manufacturer", "model_name", - "model_number", "serial_number", "device_type", "os_version", - "config_methods", "wps_cred_processing", "wps_vendor_ext_m1", -#endif /* CONFIG_WPS */ -#ifdef CONFIG_P2P - "sec_device_type", - "p2p_listen_reg_class", "p2p_listen_channel", - "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent", - "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss", - "p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan", - "p2p_no_go_freq", "p2p_add_cli_chan", - "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht", - "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface", - "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask", - "ip_addr_start", "ip_addr_end", "p2p_go_edmg", -#endif /* CONFIG_P2P */ - "country", "bss_max_count", "bss_expiration_age", - "bss_expiration_scan_count", "filter_ssids", "filter_rssi", - "max_num_sta", "disassoc_low_ack", "ap_isolate", -#ifdef CONFIG_HS20 - "hs20", -#endif /* CONFIG_HS20 */ - "interworking", "hessid", "access_network_type", "pbc_in_m1", - "go_interworking", "go_access_network_type", "go_internet", - "go_venue_group", "go_venue_type", - "autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", - "wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend", - "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf", - "sae_groups", "dtim_period", "beacon_int", - "ap_vendor_elements", "ignore_old_scan_res", "freq_list", - "scan_cur_freq", "scan_res_valid_for_connect", - "sched_scan_interval", - "tdls_external_control", "osu_dir", "wowlan_triggers", - "p2p_search_delay", "mac_addr", "rand_addr_lifetime", - "preassoc_mac_addr", "key_mgmt_offload", "passive_scan", - "reassoc_same_bss_optim", "wps_priority", - "ap_assocresp_elements", -#ifdef CONFIG_TESTING_OPTIONS - "ignore_auth_resp", -#endif /* CONFIG_TESTING_OPTIONS */ - "relative_rssi", "relative_band_adjust", - "extended_key_id", - }; - int i, num_fields = ARRAY_SIZE(fields); - - if (arg == 1) { - char **res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(fields[i]); - if (res[i] == NULL) - return res; - } - return res; - } - - if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0) - return cli_txt_list_array(&bsses); - - return NULL; -} - -static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "DUMP"); -} - - -static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); -} - - -static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "GET", 1, argc, argv); -} - - -static char ** wpa_cli_complete_get(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - const char *fields[] = { -#ifdef CONFIG_CTRL_IFACE - "ctrl_interface", "ctrl_interface_group", -#endif /* CONFIG_CTRL_IFACE */ - "eapol_version", "ap_scan", -#ifdef CONFIG_MESH - "user_mpm", "max_peer_links", "mesh_max_inactivity", -#endif /* CONFIG_MESH */ - "disable_scan_offload", "fast_reauth", "opensc_engine_path", - "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers", - "pcsc_reader", "pcsc_pin", "external_sim", "driver_param", - "dot11RSNAConfigPMKLifetime", - "dot11RSNAConfigPMKReauthThreshold", - "dot11RSNAConfigSATimeout", -#ifndef CONFIG_NO_CONFIG_WRITE - "update_config", -#endif /* CONFIG_NO_CONFIG_WRITE */ -#ifdef CONFIG_WPS - "device_name", "manufacturer", "model_name", "model_number", - "serial_number", "config_methods", "wps_cred_processing", -#endif /* CONFIG_WPS */ -#ifdef CONFIG_P2P - "p2p_listen_reg_class", "p2p_listen_channel", - "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent", - "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss", - "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan", - "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht", - "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface", - "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask", - "ip_addr_start", "ip_addr_end", -#endif /* CONFIG_P2P */ - "bss_max_count", "bss_expiration_age", - "bss_expiration_scan_count", "filter_ssids", "filter_rssi", - "max_num_sta", "disassoc_low_ack", "ap_isolate", -#ifdef CONFIG_HS20 - "hs20", -#endif /* CONFIG_HS20 */ - "interworking", "access_network_type", "pbc_in_m1", "autoscan", - "go_interworking", "go_access_network_type", "go_internet", - "go_venue_group", "go_venue_type", - "wps_nfc_dev_pw_id", "ext_password_backend", - "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf", - "dtim_period", "beacon_int", "ignore_old_scan_res", - "scan_cur_freq", "scan_res_valid_for_connect", - "sched_scan_interval", - "sched_scan_start_delay", - "tdls_external_control", "osu_dir", "wowlan_triggers", - "p2p_search_delay", "mac_addr", "rand_addr_lifetime", - "preassoc_mac_addr", "key_mgmt_offload", "passive_scan", - "reassoc_same_bss_optim", "extended_key_id" - }; - int i, num_fields = ARRAY_SIZE(fields); - - if (arg == 1) { - char **res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(fields[i]); - if (res[i] == NULL) - return res; - } - return res; - } - - return NULL; -} - - -static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LOGOFF"); -} - - -static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LOGON"); -} - - -static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "REASSOCIATE"); -} - - -static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "REATTACH"); -} - - -static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv); -} - - -static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv); -} - - -static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv); -} - - -static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv); -} - - -static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv); -} - - -static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc < 1) - res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0"); - else - res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]); - if (os_snprintf_error(sizeof(cmd), res)) { - printf("Too long BSS_FLUSH command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv); -} - - -static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc == 0) { - printf("Invalid WPS_PIN command: need one or two arguments:\n" - "- BSSID: use 'any' to select any\n" - "- PIN: optional, used only with devices that have no " - "display\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "WPS_CANCEL"); -} - - -#ifdef CONFIG_WPS_NFC - -static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv); -} - - -static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - int ret; - char *buf; - size_t buflen; - - if (argc != 1) { - printf("Invalid 'wps_nfc_tag_read' command - one argument " - "is required.\n"); - return -1; - } - - buflen = 18 + os_strlen(argv[0]); - buf = os_malloc(buflen); - if (buf == NULL) - return -1; - os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]); - - ret = wpa_ctrl_command(ctrl, buf); - os_free(buf); - - return ret; -} - - -static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv); -} - - -static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv); -} - - -static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv); -} - -#endif /* CONFIG_WPS_NFC */ - - -static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc == 2) - res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", - argv[0], argv[1]); - else if (argc == 5 || argc == 6) { - char ssid_hex[2 * SSID_MAX_LEN + 1]; - char key_hex[2 * 64 + 1]; - int i; - - ssid_hex[0] = '\0'; - for (i = 0; i < SSID_MAX_LEN; i++) { - if (argv[2][i] == '\0') - break; - os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); - } - - key_hex[0] = '\0'; - if (argc == 6) { - for (i = 0; i < 64; i++) { - if (argv[5][i] == '\0') - break; - os_snprintf(&key_hex[i * 2], 3, "%02x", - argv[5][i]); - } - } - - res = os_snprintf(cmd, sizeof(cmd), - "WPS_REG %s %s %s %s %s %s", - argv[0], argv[1], ssid_hex, argv[3], argv[4], - key_hex); - } else { - printf("Invalid WPS_REG command: need two arguments:\n" - "- BSSID of the target AP\n" - "- AP PIN\n"); - printf("Alternatively, six arguments can be used to " - "reconfigure the AP:\n" - "- BSSID of the target AP\n" - "- AP PIN\n" - "- new SSID\n" - "- new auth (OPEN, WPAPSK, WPA2PSK)\n" - "- new encr (NONE, WEP, TKIP, CCMP)\n" - "- new key\n"); - return -1; - } - - if (os_snprintf_error(sizeof(cmd), res)) { - printf("Too long WPS_REG command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv); -} - - -static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "WPS_ER_STOP"); - -} - - -static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc < 2) { - printf("Invalid WPS_ER_PIN command: need at least two " - "arguments:\n" - "- UUID: use 'any' to select any\n" - "- PIN: Enrollee PIN\n" - "optional: - Enrollee MAC address\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv); -} - - -static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv); -} - - -static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc != 2) { - printf("Invalid WPS_ER_LEARN command: need two arguments:\n" - "- UUID: specify which AP to use\n" - "- PIN: AP PIN\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv); -} - - -static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc != 2) { - printf("Invalid WPS_ER_SET_CONFIG command: need two " - "arguments:\n" - "- UUID: specify which AP to use\n" - "- Network configuration id\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv); -} - - -static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc == 5 || argc == 6) { - char ssid_hex[2 * SSID_MAX_LEN + 1]; - char key_hex[2 * 64 + 1]; - int i; - - ssid_hex[0] = '\0'; - for (i = 0; i < SSID_MAX_LEN; i++) { - if (argv[2][i] == '\0') - break; - os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); - } - - key_hex[0] = '\0'; - if (argc == 6) { - for (i = 0; i < 64; i++) { - if (argv[5][i] == '\0') - break; - os_snprintf(&key_hex[i * 2], 3, "%02x", - argv[5][i]); - } - } - - res = os_snprintf(cmd, sizeof(cmd), - "WPS_ER_CONFIG %s %s %s %s %s %s", - argv[0], argv[1], ssid_hex, argv[3], argv[4], - key_hex); - } else { - printf("Invalid WPS_ER_CONFIG command: need six arguments:\n" - "- AP UUID\n" - "- AP PIN\n" - "- new SSID\n" - "- new auth (OPEN, WPAPSK, WPA2PSK)\n" - "- new encr (NONE, WEP, TKIP, CCMP)\n" - "- new key\n"); - return -1; - } - - if (os_snprintf_error(sizeof(cmd), res)) { - printf("Too long WPS_ER_CONFIG command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -#ifdef CONFIG_WPS_NFC -static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc != 2) { - printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two " - "arguments:\n" - "- WPS/NDEF: token format\n" - "- UUID: specify which AP to use\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv); -} -#endif /* CONFIG_WPS_NFC */ - - -static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv); -} - -#ifdef notyet -static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv); -} -#endif /* notyet */ - -static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid IDENTITY command: needs two arguments " - "(network id and identity)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long IDENTITY command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long IDENTITY command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PASSWORD command: needs two arguments " - "(network id and password)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PASSWORD command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PASSWORD command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid NEW_PASSWORD command: needs two arguments " - "(network id and password)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long NEW_PASSWORD command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long NEW_PASSWORD command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PIN command: needs two arguments " - "(network id and pin)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PIN command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PIN command.\n"); - return -1; - } - pos += ret; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid OTP command: needs two arguments (network " - "id and password)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long OTP command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long OTP command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid SIM command: needs two arguments " - "(network id and SIM operation response)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long SIM command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long SIM command.\n"); - return -1; - } - pos += ret; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_psk_passphrase(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PSK_PASSPHRASE command: needs two arguments (network id and PSK/passphrase)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PSK_PASSPHRASE-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PSK_PASSPHRASE command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PSK_PASSPHRASE command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PASSPHRASE command: needs two arguments " - "(network id and passphrase)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", - argv[0], argv[1]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PASSPHRASE command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (os_snprintf_error(end - pos, ret)) { - printf("Too long PASSPHRASE command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc < 2) { - printf("Invalid BSSID command: needs two arguments (network " - "id and BSSID)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv); -} - - -static int wpa_cli_cmd_bssid_ignore(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "BSSID_IGNORE", 0, argc, argv); -} - - -static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv); -} - - -static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "LIST_NETWORKS", 0, argc, argv); -} - - -static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - int res = wpa_ctrl_command(ctrl, "ADD_NETWORK"); - if (interactive) - update_networks(ctrl); - return res; -} - - -static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv); - if (interactive) - update_networks(ctrl); - return res; -} - - -static void wpa_cli_show_network_variables(void) -{ - printf("set_network variables:\n" - " ssid (network name, SSID)\n" - " psk (WPA passphrase or pre-shared key)\n" - " key_mgmt (key management protocol)\n" - " identity (EAP identity)\n" - " password (EAP password)\n" - " ...\n" - "\n" - "Note: Values are entered in the same format as the " - "configuration file is using,\n" - "i.e., strings values need to be inside double quotation " - "marks.\n" - "For example: set_network 1 ssid \"network name\"\n" - "\n" - "Please see wpa_supplicant.conf documentation for full list " - "of\navailable variables.\n"); -} - - -static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc < 3) { - printf("Invalid SET_NETWORK command: needs three arguments\n" - "(network id, variable name, and value)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv); -} - - -static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc < 2) { - printf("Invalid GET_NETWORK command: needs two arguments\n" - "(network id and variable name)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv); -} - - -static const char *network_fields[] = { - "ssid", "scan_ssid", "bssid", "bssid_ignore", - "bssid_accept", "psk", "proto", "key_mgmt", - "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq", - "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1", - "vht_center_freq2", "ht", "edmg", -#ifdef IEEE8021X_EAPOL - "eap", "identity", "anonymous_identity", "password", "ca_cert", - "ca_path", "client_cert", "private_key", "private_key_passwd", - "dh_file", "subject_match", "altsubject_match", - "check_cert_subject", - "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2", - "client_cert2", "private_key2", "private_key2_passwd", - "dh_file2", "subject_match2", "altsubject_match2", - "check_cert_subject2", - "domain_suffix_match2", "domain_match2", "phase1", "phase2", - "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id", - "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id", - "engine", "engine2", "eapol_flags", "sim_num", - "openssl_ciphers", "erp", -#endif /* IEEE8021X_EAPOL */ - "wep_key0", "wep_key1", "wep_key2", "wep_key3", - "wep_tx_keyidx", "priority", -#ifdef IEEE8021X_EAPOL - "eap_workaround", "pac_file", "fragment_size", "ocsp", -#endif /* IEEE8021X_EAPOL */ - "mode", - "proactive_key_caching", "disabled", "id_str", - "ieee80211w", - "mixed_cell", "frequency", "fixed_freq", -#ifdef CONFIG_MESH - "no_auto_peer", "mesh_rssi_threshold", - "mesh_basic_rates", "dot11MeshMaxRetries", - "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout", - "dot11MeshHoldingTimeout", -#endif /* CONFIG_MESH */ - "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", - "wpa_deny_ptk0_rekey", - "enable_edmg", "edmg_channel", -#ifdef CONFIG_P2P - "go_p2p_dev_addr", "p2p_client_list", "psk_list", -#endif /* CONFIG_P2P */ -#ifdef CONFIG_HT_OVERRIDES - "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc", - "ht40_intolerant", "disable_max_amsdu", "ampdu_factor", - "ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc", -#endif /* CONFIG_HT_OVERRIDES */ -#ifdef CONFIG_VHT_OVERRIDES - "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1", - "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4", - "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7", - "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2", - "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5", - "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8", -#endif /* CONFIG_VHT_OVERRIDES */ -#ifdef CONFIG_HE_OVERRIDES - "disable_he", -#endif /* CONFIG_HE_OVERRIDES */ - "ap_max_inactivity", "dtim_period", "beacon_int", -#ifdef CONFIG_MACSEC - "macsec_policy", - "macsec_integ_only", - "macsec_replay_protect", - "macsec_replay_window", - "macsec_port", - "mka_priority", -#endif /* CONFIG_MACSEC */ -#ifdef CONFIG_HS20 - "update_identifier", -#endif /* CONFIG_HS20 */ - "mac_addr", "pbss", "wps_disabled" -}; - - -static char ** wpa_cli_complete_network(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - int i, num_fields = ARRAY_SIZE(network_fields); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&networks); - break; - case 2: - res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(network_fields[i]); - if (res[i] == NULL) - break; - } - } - return res; -} - - -static char ** wpa_cli_complete_network_id(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - if (arg == 1) - return cli_txt_list_array(&networks); - return NULL; -} - - -static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc < 3) { - printf("Invalid DUP_NETWORK command: needs three arguments\n" - "(src netid, dest netid, and variable name)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv); -} - - -static char ** wpa_cli_complete_dup_network(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - int i, num_fields = ARRAY_SIZE(network_fields); - char **res = NULL; - - switch (arg) { - case 1: - case 2: - res = cli_txt_list_array(&networks); - break; - case 3: - res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(network_fields[i]); - if (res[i] == NULL) - break; - } - } - return res; -} - - -static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LIST_CREDS"); -} - - -static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - int res = wpa_ctrl_command(ctrl, "ADD_CRED"); - if (interactive) - update_creds(ctrl); - return res; -} - - -static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - int res = wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv); - if (interactive) - update_creds(ctrl); - return res; -} - - -static const char * const cred_fields[] = { - "temporary", "priority", "sp_priority", "pcsc", "eap", - "update_identifier", "min_dl_bandwidth_home", "min_ul_bandwidth_home", - "min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load", - "req_conn_capab", "ocsp", "sim_num", "realm", "username", "password", - "ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi", - "ca_cert_id", "cert_id", "key_id", "engine_id", "engine", - "milenage", "domain_suffix_match", "domain", "phase1", "phase2", - "roaming_consortium", "required_roaming_consortium", "excluded_ssid", - "roaming_partner", "provisioning_sp" -}; - - -static char ** wpa_cli_complete_cred(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - int i, num_fields = ARRAY_SIZE(cred_fields); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&creds); - break; - case 2: - res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(cred_fields[i]); - if (res[i] == NULL) - break; - } - } - return res; -} - - -static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc != 3) { - printf("Invalid SET_CRED command: needs three arguments\n" - "(cred id, variable name, and value)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv); -} - - -static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc != 2) { - printf("Invalid GET_CRED command: needs two arguments\n" - "(cred id, variable name)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv); -} - - -static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "DISCONNECT"); -} - - -static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RECONNECT"); -} - - -static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); -} - - -static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv); -} - - -static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); -} - - -static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "ABORT_SCAN"); -} - - -static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv); -} - - -static char ** wpa_cli_complete_bss(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&bsses); - break; - } - - return res; -} - - -static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc < 1 || argc > 3) { - printf("Invalid GET_CAPABILITY command: need at least one argument and max three arguments\n"); - return -1; - } - - if (argc > 1 && os_strcmp(argv[0], "key_mgmt") != 0 && - os_strncmp(argv[1], "iftype=", 7) == 0) { - printf("Invalid GET_CAPABILITY command: 'iftype=' param is allowed only for 'key_mgmt'\n"); - return -1; - } - - if (argc == 2 && os_strcmp(argv[1], "strict") != 0 && - os_strncmp(argv[1], "iftype=", 7) != 0) { - printf("Invalid GET_CAPABILITY command: the second argument, if any, must be 'strict' OR 'iftype='\n"); - return -1; - } - - if (argc == 3 && os_strcmp(argv[2], "strict") != 0) { - printf("Invalid GET_CAPABILITY command: the third argument, if any, must be 'strict'\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv); -} - - -static char ** wpa_cli_complete_get_capability(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - const char *fields[] = { - "eap", "pairwise", "group", "group_mgmt", "key_mgmt", - "proto", "auth_alg", "modes", "channels", "freq", -#ifdef CONFIG_TDLS - "tdls", -#endif /* CONFIG_TDLS */ -#ifdef CONFIG_ERP - "erp", -#endif /* CONFIG_ERP */ -#ifdef CONFIG_FIPS - "fips", -#endif /* CONFIG_FIPS */ -#ifdef CONFIG_ACS - "acs", -#endif /* CONFIG_ACS */ - }; - const char *iftypes[] = { - "iftype=STATION", "iftype=AP", "iftype=P2P_CLIENT", - "iftype=P2P_GO", "iftype=AP_VLAN", "iftype=IBSS", "iftype=NAN", - "iftype=P2P_DEVICE", "iftype=MESH", - }; - int i, num_fields = ARRAY_SIZE(fields); - int num_iftypes = ARRAY_SIZE(iftypes); - char **res = NULL; - - if (arg == 1) { - res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(fields[i]); - if (res[i] == NULL) - return res; - } - } - if (arg == 2) { - /* the second argument can be "iftype=" OR - * "strict" */ - res = os_calloc(num_iftypes + 2, sizeof(char *)); - if (!res) - return NULL; - res[0] = os_strdup("strict"); - if (!res[0]) - return res; - for (i = 0; i < num_iftypes; i++) { - res[i + 1] = os_strdup(iftypes[i]); - if (!res[i + 1]) - return res; - } - } - if (arg == 3) { - res = os_calloc(1 + 1, sizeof(char *)); - if (res == NULL) - return NULL; - res[0] = os_strdup("strict"); - } - return res; -} - -#ifdef notyet -static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) -{ - printf("Available interfaces:\n"); - return wpa_ctrl_command(ctrl, "INTERFACES"); -} - -static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc < 1) { - wpa_cli_list_interfaces(ctrl); - return 0; - } - - wpa_cli_close_connection(); - os_free(ctrl_ifname); - ctrl_ifname = os_strdup(argv[0]); - if (!ctrl_ifname) { - printf("Failed to allocate memory\n"); - return 0; - } - - if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) { - printf("Connected to interface '%s'.\n", ctrl_ifname); - } else { - printf("Could not connect to interface '%s' - re-trying\n", - ctrl_ifname); - } - return 0; -} -#endif /* notyet */ - - -static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RECONFIGURE"); -} - - -static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "TERMINATE"); -} - - -static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc < 1) { - printf("Invalid INTERFACE_ADD command: needs at least one " - "argument (interface name)\n" - "All arguments: ifname confname driver ctrl_interface " - "driver_param bridge_name [create]\n"); - return -1; - } - - /* - * INTERFACE_ADD TABTABTABTAB - * TAB[TAB[TAB]] - */ - res = os_snprintf(cmd, sizeof(cmd), - "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", - argv[0], - argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", - argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", - argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "", - argc > 7 ? argv[7] : ""); - if (os_snprintf_error(sizeof(cmd), res)) - return -1; - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv); -} - - -static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); -} - - -#ifdef CONFIG_AP -static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "STA", 1, argc, argv); -} - - -static char ** wpa_cli_complete_sta(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&stations); - break; - } - - return res; -} - - -static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd, - char *addr, size_t addr_len, int print) -{ - char buf[4096], *pos; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to hostapd - command dropped.\n"); - return -1; - } - if (ifname_prefix) { - os_snprintf(buf, sizeof(buf), "IFNAME=%s %s", - ifname_prefix, cmd); - buf[sizeof(buf) - 1] = '\0'; - cmd = buf; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, - wpa_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - - buf[len] = '\0'; - if (os_memcmp(buf, "FAIL", 4) == 0 || - os_memcmp(buf, "UNKNOWN COMMAND", 15) == 0) - return -1; - if (print) - printf("%s", buf); - - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - *pos = '\0'; - os_strlcpy(addr, buf, addr_len); - return 0; -} - - -static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char addr[32], cmd[64]; - - if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1)) - return 0; - do { - os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); - } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0); - - return -1; -} - - -static int wpa_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char addr[32], cmd[64]; - - if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0)) - return 0; - do { - if (os_strcmp(addr, "") != 0) - printf("%s\n", addr); - os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); - } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0); - - return 0; -} - - -static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv); -} - - -static char ** wpa_cli_complete_deauthenticate(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&stations); - break; - } - - return res; -} - - -static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv); -} - - -static char ** wpa_cli_complete_disassociate(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&stations); - break; - } - - return res; -} - - -static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv); -} - - -static int wpa_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "UPDATE_BEACON"); -} - -#endif /* CONFIG_AP */ - - -static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SUSPEND"); -} - - -static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RESUME"); -} - - -#ifdef CONFIG_TESTING_OPTIONS -static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "DROP_SA"); -} -#endif /* CONFIG_TESTING_OPTIONS */ - - -static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv); -} - - -#ifdef CONFIG_MESH - -static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv); -} - - -static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv); -} - - -static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv); -} - - -static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv); -} - - -static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv); -} - - -static int wpa_cli_cmd_mesh_link_probe(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MESH_LINK_PROBE", 1, argc, argv); -} - -#endif /* CONFIG_MESH */ - - -#ifdef CONFIG_P2P - -static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv); -} - - -static char ** wpa_cli_complete_p2p_find(const char *str, int pos) -{ - char **res = NULL; - int arg = get_cmd_arg_num(str, pos); - - res = os_calloc(6, sizeof(char *)); - if (res == NULL) - return NULL; - res[0] = os_strdup("type=social"); - if (res[0] == NULL) { - os_free(res); - return NULL; - } - res[1] = os_strdup("type=progressive"); - if (res[1] == NULL) - return res; - res[2] = os_strdup("delay="); - if (res[2] == NULL) - return res; - res[3] = os_strdup("dev_id="); - if (res[3] == NULL) - return res; - if (arg == 1) - res[4] = os_strdup("[timeout]"); - - return res; -} - - -static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "P2P_STOP_FIND"); -} - - -static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv); -} - - -static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv); -} - - -static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv); -} - - -static char ** wpa_cli_complete_p2p_connect(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&p2p_peers); - break; - } - - return res; -} - - -static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv); -} - - -static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv); -} - - -static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&p2p_groups); - break; - } - - return res; -} - - -static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv); -} - - -static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc != 2 && argc != 3) { - printf("Invalid P2P_PROV_DISC command: needs at least " - "two arguments, address and config method\n" - "(display, keypad, or pbc) and an optional join\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv); -} - - -static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE"); -} - - -static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[4096]; - - if (argc < 2) { - printf("Invalid P2P_SERV_DISC_REQ command: needs two " - "or more arguments (address and TLVs)\n"); - return -1; - } - - if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0) - return -1; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl, - int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[4096]; - int res; - - if (argc != 4) { - printf("Invalid P2P_SERV_DISC_RESP command: needs four " - "arguments (freq, address, dialog token, and TLVs)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s", - argv[0], argv[1], argv[2], argv[3]); - if (os_snprintf_error(sizeof(cmd), res)) - return -1; - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE"); -} - - -static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl, - int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH"); -} - - -static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc < 3) { - printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv); -} - - -static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc < 5 || argc > 6) { - printf("Invalid P2P_SERVICE_REP command: needs 5-6 " - "arguments\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv); -} - - -static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[4096]; - int res; - - if (argc != 2 && argc != 3) { - printf("Invalid P2P_SERVICE_DEL command: needs two or three " - "arguments\n"); - return -1; - } - - if (argc == 3) - res = os_snprintf(cmd, sizeof(cmd), - "P2P_SERVICE_DEL %s %s %s", - argv[0], argv[1], argv[2]); - else - res = os_snprintf(cmd, sizeof(cmd), - "P2P_SERVICE_DEL %s %s", - argv[0], argv[1]); - if (os_snprintf_error(sizeof(cmd), res)) - return -1; - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl, - int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl, - int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv); -} - - -static char ** wpa_cli_complete_p2p_peer(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&p2p_peers); - break; - } - - return res; -} - - -static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, const char *cmd, - char *addr, size_t addr_len, - int discovered) -{ - char buf[4096], *pos; - size_t len; - int ret; - - if (ctrl_conn == NULL) - return -1; - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, - wpa_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - - buf[len] = '\0'; - if (os_memcmp(buf, "FAIL", 4) == 0) - return -1; - - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - *pos++ = '\0'; - os_strlcpy(addr, buf, addr_len); - if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL) - printf("%s\n", addr); - return 0; -} - - -static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char addr[32], cmd[64]; - int discovered; - - discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0; - - if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST", - addr, sizeof(addr), discovered)) - return -1; - do { - os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr); - } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr), - discovered) == 0); - - return 0; -} - - -static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv); -} - - -static char ** wpa_cli_complete_p2p_set(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - const char *fields[] = { - "discoverability", - "managed", - "listen_channel", - "ssid_postfix", - "noa", - "ps", - "oppps", - "ctwindow", - "disabled", - "conc_pref", - "force_long_sd", - "peer_filter", - "cross_connect", - "go_apsd", - "client_apsd", - "disallow_freq", - "disc_int", - "per_sta_psk", - }; - int i, num_fields = ARRAY_SIZE(fields); - - if (arg == 1) { - char **res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(fields[i]); - if (res[i] == NULL) - return res; - } - return res; - } - - if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0) - return cli_txt_list_array(&p2p_peers); - - return NULL; -} - - -static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "P2P_FLUSH"); -} - - -static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "P2P_CANCEL"); -} - - -static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc != 0 && argc != 2 && argc != 4) { - printf("Invalid P2P_PRESENCE_REQ command: needs two arguments " - "(preferred duration, interval; in microsecods).\n" - "Optional second pair can be used to provide " - "acceptable values.\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv); -} - - -static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc != 0 && argc != 2) { - printf("Invalid P2P_EXT_LISTEN command: needs two arguments " - "(availability period, availability interval; in " - "millisecods).\n" - "Extended Listen Timing can be cancelled with this " - "command when used without parameters.\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv); -} - - -static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv); -} - -#endif /* CONFIG_P2P */ - - -static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv); -} - - -static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv); -} - - -static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv); -} - - -#ifdef CONFIG_WIFI_DISPLAY - -static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[100]; - int res; - - if (argc != 1 && argc != 2) { - printf("Invalid WFD_SUBELEM_SET command: needs one or two " - "arguments (subelem, hexdump)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s", - argv[0], argc > 1 ? argv[1] : ""); - if (os_snprintf_error(sizeof(cmd), res)) - return -1; - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[100]; - int res; - - if (argc != 1) { - printf("Invalid WFD_SUBELEM_GET command: needs one " - "argument (subelem)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s", - argv[0]); - if (os_snprintf_error(sizeof(cmd), res)) - return -1; - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} -#endif /* CONFIG_WIFI_DISPLAY */ - - -#ifdef CONFIG_INTERWORKING -static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "FETCH_ANQP"); -} - - -static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP"); -} - - -static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv); -} - - -static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv); -} - - -static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv); -} - - -static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv); -} - - -static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv); -} -#endif /* CONFIG_INTERWORKING */ - - -#ifdef CONFIG_HS20 - -static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv); -} - - -static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[512]; - - if (argc == 0) { - printf("Command needs one or two arguments (dst mac addr and " - "optional home realm)\n"); - return -1; - } - - if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST", - argc, argv) < 0) - return -1; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[512]; - - if (argc < 2) { - printf("Command needs two arguments (dst mac addr and " - "icon name)\n"); - return -1; - } - - if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0) - return -1; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "FETCH_OSU"); -} - - -static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU"); -} - -#endif /* CONFIG_HS20 */ - - -static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv); -} - - -static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv); -} - - -static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv); -} - - -static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv); -} - - -static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv); -} - - -static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv); -} - - -static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv); -} - - -static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "WMM_AC_STATUS"); -} - - -static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv); -} - - -static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv); -} - - -static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SIGNAL_POLL"); -} - - -static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv); -} - - -static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PKTCNT_POLL"); -} - - -static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "REAUTHENTICATE"); -} - - -#ifdef CONFIG_AUTOSCAN - -static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc == 0) - return wpa_ctrl_command(ctrl, "AUTOSCAN "); - - return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv); -} - -#endif /* CONFIG_AUTOSCAN */ - - -#ifdef CONFIG_WNM - -static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv); -} - - -static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv); -} - -#endif /* CONFIG_WNM */ - - -static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc == 0) - return -1; - return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]); -} - - -#ifdef ANDROID -static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv); -} -#endif /* ANDROID */ - - -static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv); -} - - -static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "FLUSH"); -} - - -static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv); -} - - -static int wpa_cli_cmd_twt_setup(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TWT_SETUP", 0, argc, argv); -} - - -static int wpa_cli_cmd_twt_teardown(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "TWT_TEARDOWN", 0, argc, argv); -} - - -static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "ERP_FLUSH"); -} - - -static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv); -} - - -static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv); -} - - -static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv); -} - - -static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv); -} - - -#ifdef CONFIG_DPP - -static int wpa_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv); -} - - -static int wpa_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv); -} - - -static int wpa_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv); -} - - -static int wpa_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv); -} - - -static int wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv); -} - - -static int wpa_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); -} - -static int wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv); -} +static void print_help(const char *cmd); +static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx); +static void wpa_cli_close_connection(void); +static char * wpa_cli_get_default_ifname(void); +static char ** wpa_list_cmd_list(void); +static void update_creds(struct wpa_ctrl *ctrl); +static void update_networks(struct wpa_ctrl *ctrl); +static void update_stations(struct wpa_ctrl *ctrl); +static void update_ifnames(struct wpa_ctrl *ctrl); -static int wpa_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc, - char *argv[]) +static void usage(void) { - return wpa_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv); + printf("wpa_cli [-p] [-i] [-hvBr] " + "[-a] \\\n" + " [-P] [-g] [-G] " + "\\\n" + " [-s] " + "[command..]\n" + " -h = help (show this usage text)\n" + " -v = shown version information\n" + " -a = run in daemon mode executing the action file based on " + "events from\n" + " wpa_supplicant\n" + " -r = try to reconnect when client socket is disconnected.\n" + " This is useful only when used with -a.\n" + " -B = run a daemon in the background\n" + " default path: " CONFIG_CTRL_IFACE_DIR "\n" + " default interface: first interface found in socket path\n"); + print_help(NULL); } -static int wpa_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc, - char *argv[]) +static int wpa_cli_show_event(const char *event) { - return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN"); -} - + const char *start; -static int wpa_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv); -} + start = os_strchr(event, '>'); + if (start == NULL) + return 1; + start++; + /* + * Skip BSS added/removed events since they can be relatively frequent + * and are likely of not much use for an interactive user. + */ + if (str_starts(start, WPA_EVENT_BSS_ADDED) || + str_starts(start, WPA_EVENT_BSS_REMOVED)) + return 0; -static int wpa_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv); + return 1; } -static int wpa_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl, int argc, - char *argv[]) +static int wpa_cli_open_connection(const char *ifname, int attach) { - return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv); -} +#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) + ctrl_conn = wpa_ctrl_open(ifname); + if (ctrl_conn == NULL) + return -1; + if (attach && interactive) + mon_conn = wpa_ctrl_open(ifname); + else + mon_conn = NULL; +#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ + char *cfile = NULL; + int flen, res; -static int wpa_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv); -} + if (ifname == NULL) + return -1; +#ifdef ANDROID + if (access(ctrl_iface_dir, F_OK) < 0) { + cfile = os_strdup(ifname); + if (cfile == NULL) + return -1; + } +#endif /* ANDROID */ -static int wpa_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv); -} + if (client_socket_dir && client_socket_dir[0] && + access(client_socket_dir, F_OK) < 0) { + perror(client_socket_dir); + os_free(cfile); + return -1; + } + if (cfile == NULL) { + flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; + cfile = os_malloc(flen); + if (cfile == NULL) + return -1; + res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, + ifname); + if (os_snprintf_error(flen, res)) { + os_free(cfile); + return -1; + } + } -static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); -} + ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir); + if (ctrl_conn == NULL) { + os_free(cfile); + return -1; + } + if (attach && interactive) + mon_conn = wpa_ctrl_open2(cfile, client_socket_dir); + else + mon_conn = NULL; + os_free(cfile); +#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ -#ifdef CONFIG_DPP2 + if (mon_conn) { + if (wpa_ctrl_attach(mon_conn) == 0) { + wpa_cli_attached = 1; + if (interactive) + eloop_register_read_sock( + wpa_ctrl_get_fd(mon_conn), + wpa_cli_mon_receive, NULL, NULL); + } else { + printf("Warning: Failed to attach to " + "wpa_supplicant.\n"); + wpa_cli_close_connection(); + return -1; + } + } -static int wpa_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); + return 0; } -static int wpa_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, - char *argv[]) +static void wpa_cli_close_connection(void) { - return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); -} - + if (ctrl_conn == NULL) + return; -static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); + if (wpa_cli_attached) { + wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); + wpa_cli_attached = 0; + } + wpa_ctrl_close(ctrl_conn); + ctrl_conn = NULL; + if (mon_conn) { + eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn)); + wpa_ctrl_close(mon_conn); + mon_conn = NULL; + } } -static int wpa_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, - char *argv[]) +static void wpa_cli_msg_cb(char *msg, size_t len) { - return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); + printf("%s\n", msg); } -#endif /* CONFIG_DPP2 */ -#endif /* CONFIG_DPP */ - -static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) +static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print) { - char buf[512], *pos, *bssid = NULL, *freq = NULL, *level = NULL, - *flags = NULL, *ssid = NULL; + char buf[4096]; size_t len; - int ret, id = -1; + int ret; - if (!ctrl_conn) + if (ctrl_conn == NULL) { + printf("Not connected to wpa_supplicant - command dropped.\n"); return -1; + } + if (ifname_prefix) { + os_snprintf(buf, sizeof(buf), "IFNAME=%s %s", + ifname_prefix, cmd); + buf[sizeof(buf) - 1] = '\0'; + cmd = buf; + } len = sizeof(buf) - 1; ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, wpa_cli_msg_cb); @@ -3211,842 +235,38 @@ static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) printf("'%s' command failed.\n", cmd); return -1; } - - buf[len] = '\0'; - if (os_memcmp(buf, "FAIL", 4) == 0) - return -1; - - pos = buf; - while (*pos != '\0') { - if (str_starts(pos, "id=")) - id = atoi(pos + 3); - if (str_starts(pos, "bssid=")) - bssid = pos + 6; - if (str_starts(pos, "freq=")) - freq = pos + 5; - if (str_starts(pos, "level=")) - level = pos + 6; - if (str_starts(pos, "flags=")) - flags = pos + 6; - if (str_starts(pos, "ssid=")) - ssid = pos + 5; - - while (*pos != '\0' && *pos != '\n') - pos++; - *pos++ = '\0'; + if (print) { + buf[len] = '\0'; + printf("%s", buf); + if (interactive && len > 0 && buf[len - 1] != '\n') + printf("\n"); } - if (id != -1) - printf("%s\t%s\t%s\t%s\t%s\n", bssid ? bssid : "N/A", - freq ? freq : "N/A", level ? level : "N/A", - flags ? flags : "N/A", ssid ? ssid : "N/A"); - return id; -} - - -static int wpa_cli_cmd_all_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[64]; - int id = -1; - unsigned int mask; - - printf("bssid / frequency / signal level / flags / ssid\n"); - - mask = WPA_BSS_MASK_ID | WPA_BSS_MASK_BSSID | WPA_BSS_MASK_FREQ | - WPA_BSS_MASK_LEVEL | WPA_BSS_MASK_FLAGS | WPA_BSS_MASK_SSID; - do { - if (id < 0) - os_snprintf(cmd, sizeof(cmd), "BSS FIRST MASK=0x%x", - mask); - else - os_snprintf(cmd, sizeof(cmd), "BSS NEXT-%d MASK=0x%x", - id, mask); - id = wpa_ctrl_command_bss(ctrl, cmd); - } while (id >= 0); - return 0; } -#ifdef CONFIG_PASN - -static int wpa_cli_cmd_pasn_auth_start(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PASN_AUTH_START", 4, argc, argv); -} - - -static int wpa_cli_cmd_pasn_auth_stop(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PASN_AUTH_STOP", 0, argc, argv); -} - -static int wpa_cli_cmd_ptksa_cache_list(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv); -} - - -static int wpa_cli_cmd_pasn_deauth(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "PASN_DEAUTH", 1, argc, argv); -} - -#endif /* CONFIG_PASN */ - - -static int wpa_cli_cmd_mscs(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "MSCS", 1, argc, argv); -} - - -static int wpa_cli_cmd_scs(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_cli_cmd(ctrl, "SCS", 2, argc, argv); -} - - -static int wpa_cli_cmd_dscp_resp(struct wpa_ctrl *ctrl, int argc, char *argv[]) +int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) { - return wpa_cli_cmd(ctrl, "DSCP_RESP", 1, argc, argv); + return _wpa_ctrl_command(ctrl, cmd, 1); } -static int wpa_cli_cmd_dscp_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) +static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, + int argc, char *argv[]) { - return wpa_cli_cmd(ctrl, "DSCP_QUERY", 1, argc, argv); + char buf[4096]; + if (argc < min_args) { + printf("Invalid %s command - at least %d argument%s " + "required.\n", cmd, min_args, + min_args > 1 ? "s are" : " is"); + return -1; + } + if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0) + return -1; + return wpa_ctrl_command(ctrl, buf); } -enum wpa_cli_cmd_flags { - cli_cmd_flag_none = 0x00, - cli_cmd_flag_sensitive = 0x01 -}; - -struct wpa_cli_cmd { - const char *cmd; - int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); - char ** (*completion)(const char *str, int pos); - enum wpa_cli_cmd_flags flags; - const char *usage; -}; - -static const struct wpa_cli_cmd wpa_cli_commands[] = { - { "status", wpa_cli_cmd_status, NULL, - cli_cmd_flag_none, - "[verbose] = get current WPA/EAPOL/EAP status" }, - { "ifname", wpa_cli_cmd_ifname, NULL, - cli_cmd_flag_none, - "= get current interface name" }, - { "ping", wpa_cli_cmd_ping, NULL, - cli_cmd_flag_none, - "= pings wpa_supplicant" }, - { "relog", wpa_cli_cmd_relog, NULL, - cli_cmd_flag_none, - "= re-open log-file (allow rolling logs)" }, - { "note", wpa_cli_cmd_note, NULL, - cli_cmd_flag_none, - " = add a note to wpa_supplicant debug log" }, - { "mib", wpa_cli_cmd_mib, NULL, - cli_cmd_flag_none, - "= get MIB variables (dot1x, dot11)" }, -#ifdef notyet - { "help", wpa_cli_cmd_help, wpa_cli_complete_help, - cli_cmd_flag_none, - "[command] = show usage help" }, - { "interface", wpa_cli_cmd_interface, NULL, - cli_cmd_flag_none, - "[ifname] = show interfaces/select interface" }, - { "level", wpa_cli_cmd_level, NULL, - cli_cmd_flag_none, - " = change debug level" }, - { "license", wpa_cli_cmd_license, NULL, - cli_cmd_flag_none, - "= show full wpa_cli license" }, - { "quit", wpa_cli_cmd_quit, NULL, - cli_cmd_flag_none, - "= exit wpa_cli" }, -#endif /* notyet */ - { "set", wpa_cli_cmd_set, wpa_cli_complete_set, - cli_cmd_flag_none, - "= set variables (shows list of variables when run without " - "arguments)" }, - { "dump", wpa_cli_cmd_dump, NULL, - cli_cmd_flag_none, - "= dump config variables" }, - { "get", wpa_cli_cmd_get, wpa_cli_complete_get, - cli_cmd_flag_none, - " = get information" }, - { "driver_flags", wpa_cli_cmd_driver_flags, NULL, - cli_cmd_flag_none, - "= list driver flags" }, - { "logon", wpa_cli_cmd_logon, NULL, - cli_cmd_flag_none, - "= IEEE 802.1X EAPOL state machine logon" }, - { "logoff", wpa_cli_cmd_logoff, NULL, - cli_cmd_flag_none, - "= IEEE 802.1X EAPOL state machine logoff" }, - { "pmksa", wpa_cli_cmd_pmksa, NULL, - cli_cmd_flag_none, - "= show PMKSA cache" }, - { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL, - cli_cmd_flag_none, - "= flush PMKSA cache entries" }, -#ifdef CONFIG_PMKSA_CACHE_EXTERNAL - { "pmksa_get", wpa_cli_cmd_pmksa_get, NULL, - cli_cmd_flag_none, - " = fetch all stored PMKSA cache entries" }, - { "pmksa_add", wpa_cli_cmd_pmksa_add, NULL, - cli_cmd_flag_sensitive, - " = store PMKSA cache entry from external storage" }, -#ifdef CONFIG_MESH - { "mesh_pmksa_get", wpa_cli_mesh_cmd_pmksa_get, NULL, - cli_cmd_flag_none, - " = fetch all stored mesh PMKSA cache entries" }, - { "mesh_pmksa_add", wpa_cli_mesh_cmd_pmksa_add, NULL, - cli_cmd_flag_sensitive, - " = store mesh PMKSA cache entry from external storage" }, -#endif /* CONFIG_MESH */ -#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ - { "reassociate", wpa_cli_cmd_reassociate, NULL, - cli_cmd_flag_none, - "= force reassociation" }, - { "reattach", wpa_cli_cmd_reattach, NULL, - cli_cmd_flag_none, - "= force reassociation back to the same BSS" }, - { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss, - cli_cmd_flag_none, - " = force preauthentication" }, - { "identity", wpa_cli_cmd_identity, wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = configure identity for an SSID" }, - { "password", wpa_cli_cmd_password, wpa_cli_complete_network_id, - cli_cmd_flag_sensitive, - " = configure password for an SSID" }, - { "new_password", wpa_cli_cmd_new_password, - wpa_cli_complete_network_id, cli_cmd_flag_sensitive, - " = change password for an SSID" }, - { "pin", wpa_cli_cmd_pin, wpa_cli_complete_network_id, - cli_cmd_flag_sensitive, - " = configure pin for an SSID" }, - { "otp", wpa_cli_cmd_otp, wpa_cli_complete_network_id, - cli_cmd_flag_sensitive, - " = configure one-time-password for an SSID" - }, - { "psk_passphrase", wpa_cli_cmd_psk_passphrase, - wpa_cli_complete_network_id, cli_cmd_flag_sensitive, - " = configure PSK/passphrase for an SSID" }, - { "passphrase", wpa_cli_cmd_passphrase, wpa_cli_complete_network_id, - cli_cmd_flag_sensitive, - " = configure private key passphrase\n" - " for an SSID" }, - { "sim", wpa_cli_cmd_sim, wpa_cli_complete_network_id, - cli_cmd_flag_sensitive, - " = report SIM operation result" }, - { "bssid", wpa_cli_cmd_bssid, wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = set preferred BSSID for an SSID" }, - { "bssid_ignore", wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss, - cli_cmd_flag_none, - " = add a BSSID to the list of temporarily ignored BSSs\n" - "bssid_ignore clear = clear the list of temporarily ignored BSSIDs\n" - "bssid_ignore = display the list of temporarily ignored BSSIDs" }, - { "blacklist", /* deprecated alias for bssid_ignore */ - wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss, - cli_cmd_flag_none, - "= deprecated alias for bssid_ignore" }, - { "log_level", wpa_cli_cmd_log_level, NULL, - cli_cmd_flag_none, - " [] = update the log level/timestamp\n" - "log_level = display the current log level and log options" }, - { "list_networks", wpa_cli_cmd_list_networks, NULL, - cli_cmd_flag_none, - "= list configured networks" }, - { "select_network", wpa_cli_cmd_select_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = select a network (disable others)" }, - { "enable_network", wpa_cli_cmd_enable_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = enable a network" }, - { "disable_network", wpa_cli_cmd_disable_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = disable a network" }, - { "add_network", wpa_cli_cmd_add_network, NULL, - cli_cmd_flag_none, - "= add a network" }, - { "remove_network", wpa_cli_cmd_remove_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = remove a network" }, - { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network, - cli_cmd_flag_sensitive, - " = set network variables (shows\n" - " list of variables when run without arguments)" }, - { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network, - cli_cmd_flag_none, - " = get network variables" }, - { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network, - cli_cmd_flag_none, - " = duplicate network variables" - }, - { "list_creds", wpa_cli_cmd_list_creds, NULL, - cli_cmd_flag_none, - "= list configured credentials" }, - { "add_cred", wpa_cli_cmd_add_cred, NULL, - cli_cmd_flag_none, - "= add a credential" }, - { "remove_cred", wpa_cli_cmd_remove_cred, NULL, - cli_cmd_flag_none, - " = remove a credential" }, - { "set_cred", wpa_cli_cmd_set_cred, wpa_cli_complete_cred, - cli_cmd_flag_sensitive, - " = set credential variables" }, - { "get_cred", wpa_cli_cmd_get_cred, wpa_cli_complete_cred, - cli_cmd_flag_none, - " = get credential variables" }, - { "save_config", wpa_cli_cmd_save_config, NULL, - cli_cmd_flag_none, - "= save the current configuration" }, - { "disconnect", wpa_cli_cmd_disconnect, NULL, - cli_cmd_flag_none, - "= disconnect and wait for reassociate/reconnect command before\n" - " connecting" }, - { "reconnect", wpa_cli_cmd_reconnect, NULL, - cli_cmd_flag_none, - "= like reassociate, but only takes effect if already disconnected" - }, - { "scan", wpa_cli_cmd_scan, NULL, - cli_cmd_flag_none, - "= request new BSS scan" }, - { "scan_results", wpa_cli_cmd_scan_results, NULL, - cli_cmd_flag_none, - "= get latest scan results" }, - { "abort_scan", wpa_cli_cmd_abort_scan, NULL, - cli_cmd_flag_none, - "= request ongoing scan to be aborted" }, - { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss, - cli_cmd_flag_none, - "< | > = get detailed scan result info" }, - { "get_capability", wpa_cli_cmd_get_capability, - wpa_cli_complete_get_capability, cli_cmd_flag_none, - " " - "= get capabilities" }, - { "reconfigure", wpa_cli_cmd_reconfigure, NULL, - cli_cmd_flag_none, - "= force wpa_supplicant to re-read its configuration file" }, - { "terminate", wpa_cli_cmd_terminate, NULL, - cli_cmd_flag_none, - "= terminate wpa_supplicant" }, - { "interface_add", wpa_cli_cmd_interface_add, NULL, - cli_cmd_flag_none, - " \n" - " = adds new interface, all " - "parameters but\n" - " are optional. Supported types are station ('sta') and " - "AP ('ap')" }, - { "interface_remove", wpa_cli_cmd_interface_remove, NULL, - cli_cmd_flag_none, - " = removes the interface" }, - { "interface_list", wpa_cli_cmd_interface_list, NULL, - cli_cmd_flag_none, - "= list available interfaces" }, - { "ap_scan", wpa_cli_cmd_ap_scan, NULL, - cli_cmd_flag_none, - " = set ap_scan parameter" }, - { "scan_interval", wpa_cli_cmd_scan_interval, NULL, - cli_cmd_flag_none, - " = set scan_interval parameter (in seconds)" }, - { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL, - cli_cmd_flag_none, - " = set BSS expiration age parameter" }, - { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL, - cli_cmd_flag_none, - " = set BSS expiration scan count parameter" }, - { "bss_flush", wpa_cli_cmd_bss_flush, NULL, - cli_cmd_flag_none, - " = set BSS flush age (0 by default)" }, - { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss, - cli_cmd_flag_none, - " = request over-the-DS FT with " }, - { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss, - cli_cmd_flag_none, - "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" }, - { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss, - cli_cmd_flag_sensitive, - " [PIN] = start WPS PIN method (returns PIN, if not " - "hardcoded)" }, - { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL, - cli_cmd_flag_sensitive, - " = verify PIN checksum" }, - { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none, - "Cancels the pending WPS operation" }, -#ifdef CONFIG_WPS_NFC - { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss, - cli_cmd_flag_none, - "[BSSID] = start Wi-Fi Protected Setup: NFC" }, - { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL, - cli_cmd_flag_none, - " = build configuration token" }, - { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL, - cli_cmd_flag_none, - " = create password token" }, - { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL, - cli_cmd_flag_sensitive, - " = report read NFC tag with WPS data" }, - { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL, - cli_cmd_flag_none, - " = create NFC handover request" }, - { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL, - cli_cmd_flag_none, - " = create NFC handover select" }, - { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL, - cli_cmd_flag_none, - " = report completed " - "NFC handover" }, -#endif /* CONFIG_WPS_NFC */ - { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss, - cli_cmd_flag_sensitive, - " = start WPS Registrar to configure an AP" }, - { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL, - cli_cmd_flag_sensitive, - "[params..] = enable/disable AP PIN" }, - { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL, - cli_cmd_flag_none, - "[IP address] = start Wi-Fi Protected Setup External Registrar" }, - { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL, - cli_cmd_flag_none, - "= stop Wi-Fi Protected Setup External Registrar" }, - { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL, - cli_cmd_flag_sensitive, - " = add an Enrollee PIN to External Registrar" }, - { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL, - cli_cmd_flag_none, - " = accept an Enrollee PBC using External Registrar" }, - { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL, - cli_cmd_flag_sensitive, - " = learn AP configuration" }, - { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL, - cli_cmd_flag_none, - " = set AP configuration for enrolling" }, - { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL, - cli_cmd_flag_sensitive, - " = configure AP" }, -#ifdef CONFIG_WPS_NFC - { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL, - cli_cmd_flag_none, - " = build NFC configuration token" }, -#endif /* CONFIG_WPS_NFC */ - { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL, - cli_cmd_flag_none, - " = request RSN authentication with in IBSS" }, -#ifdef CONFIG_AP - { "sta", wpa_cli_cmd_sta, wpa_cli_complete_sta, - cli_cmd_flag_none, - " = get information about an associated station (AP)" }, - { "all_sta", wpa_cli_cmd_all_sta, NULL, - cli_cmd_flag_none, - "= get information about all associated stations (AP)" }, - { "list_sta", wpa_cli_cmd_list_sta, NULL, - cli_cmd_flag_none, - "= list all stations (AP)" }, - { "deauthenticate", wpa_cli_cmd_deauthenticate, - wpa_cli_complete_deauthenticate, cli_cmd_flag_none, - " = deauthenticate a station" }, - { "disassociate", wpa_cli_cmd_disassociate, - wpa_cli_complete_disassociate, cli_cmd_flag_none, - " = disassociate a station" }, - { "chan_switch", wpa_cli_cmd_chanswitch, NULL, - cli_cmd_flag_none, - " [sec_channel_offset=] [center_freq1=]" - " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]" - " = CSA parameters" }, - { "update_beacon", wpa_cli_cmd_update_beacon, NULL, - cli_cmd_flag_none, - "= update Beacon frame contents"}, -#endif /* CONFIG_AP */ - { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none, - "= notification of suspend/hibernate" }, - { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none, - "= notification of resume/thaw" }, -#ifdef CONFIG_TESTING_OPTIONS - { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none, - "= drop SA without deauth/disassoc (test command)" }, -#endif /* CONFIG_TESTING_OPTIONS */ - { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss, - cli_cmd_flag_none, - " = roam to the specified BSS" }, -#ifdef CONFIG_MESH - { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL, - cli_cmd_flag_none, - "[ifname] = Create a new mesh interface" }, - { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL, - cli_cmd_flag_none, - " = join a mesh network (disable others)" }, - { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL, - cli_cmd_flag_none, - " = Remove mesh group interface" }, - { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL, - cli_cmd_flag_none, - " = Remove a mesh peer" }, - { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL, - cli_cmd_flag_none, - " [duration=] = Add a mesh peer" }, - { "mesh_link_probe", wpa_cli_cmd_mesh_link_probe, NULL, - cli_cmd_flag_none, - " [payload=] = Probe a mesh link for a given peer by injecting a frame." }, -#endif /* CONFIG_MESH */ -#ifdef CONFIG_P2P - { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find, - cli_cmd_flag_none, - "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" }, - { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none, - "= stop P2P Devices search" }, - { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL, - cli_cmd_flag_none, - " adv_id= conncap= [info=] = provision with a P2P ASP Device" }, - { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL, - cli_cmd_flag_none, - " adv_id= [role] [info=] = provision with a P2P ASP Device" }, - { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect, - cli_cmd_flag_none, - " <\"pbc\"|PIN> [ht40] = connect to a P2P Device" }, - { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none, - "[timeout] = listen for P2P Devices for up-to timeout seconds" }, - { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, - wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none, - " = remove P2P group interface (terminate group if GO)" }, - { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none, - "[ht40] = add a new P2P group (local end as GO)" }, - { "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL, - cli_cmd_flag_none, - " = Get peer interface address on local GO using peer Device Address" }, - { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, - wpa_cli_complete_p2p_peer, cli_cmd_flag_none, - " = request provisioning discovery" }, - { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL, - cli_cmd_flag_none, - "= get the passphrase for a group (GO only)" }, - { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req, - wpa_cli_complete_p2p_peer, cli_cmd_flag_none, - " = schedule service discovery request" }, - { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req, - NULL, cli_cmd_flag_none, - " = cancel pending service discovery request" }, - { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL, - cli_cmd_flag_none, - " = service discovery response" }, - { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL, - cli_cmd_flag_none, - "= indicate change in local services" }, - { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL, - cli_cmd_flag_none, - " = set external processing of service discovery" }, - { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL, - cli_cmd_flag_none, - "= remove all stored service entries" }, - { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL, - cli_cmd_flag_none, - " = add a local " - "service" }, - { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL, - cli_cmd_flag_none, - "asp [] = replace " - "local ASP service" }, - { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL, - cli_cmd_flag_none, - " [|service] = remove a local " - "service" }, - { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer, - cli_cmd_flag_none, - " = reject connection attempts from a specific peer" }, - { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL, - cli_cmd_flag_none, - " [peer=addr] = invite peer" }, - { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none, - "[discovered] = list known (optionally, only fully discovered) P2P " - "peers" }, - { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer, - cli_cmd_flag_none, - "
= show information about known P2P peer" }, - { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set, - cli_cmd_flag_none, - " = set a P2P parameter" }, - { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none, - "= flush P2P state" }, - { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none, - "= cancel P2P group formation" }, - { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, - wpa_cli_complete_p2p_peer, cli_cmd_flag_none, - "
= unauthorize a peer" }, - { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL, - cli_cmd_flag_none, - "[ ] [ ] = request GO " - "presence" }, - { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL, - cli_cmd_flag_none, - "[ ] = set extended listen timing" }, - { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client, - wpa_cli_complete_p2p_peer, cli_cmd_flag_none, - " = remove a peer from all groups" }, -#endif /* CONFIG_P2P */ - { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL, - cli_cmd_flag_none, - " = add vendor specific IEs to frame(s)\n" - VENDOR_ELEM_FRAME_ID }, - { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL, - cli_cmd_flag_none, - " = get vendor specific IE(s) to frame(s)\n" - VENDOR_ELEM_FRAME_ID }, - { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL, - cli_cmd_flag_none, - " = remove vendor specific IE(s) in frame(s)\n" - VENDOR_ELEM_FRAME_ID }, -#ifdef CONFIG_WIFI_DISPLAY - { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL, - cli_cmd_flag_none, - " [contents] = set Wi-Fi Display subelement" }, - { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL, - cli_cmd_flag_none, - " = get Wi-Fi Display subelement" }, -#endif /* CONFIG_WIFI_DISPLAY */ -#ifdef CONFIG_INTERWORKING - { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none, - "= fetch ANQP information for all APs" }, - { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL, - cli_cmd_flag_none, - "= stop fetch_anqp operation" }, - { "interworking_select", wpa_cli_cmd_interworking_select, NULL, - cli_cmd_flag_none, - "[auto] = perform Interworking network selection" }, - { "interworking_connect", wpa_cli_cmd_interworking_connect, - wpa_cli_complete_bss, cli_cmd_flag_none, - " = connect using Interworking credentials" }, - { "interworking_add_network", wpa_cli_cmd_interworking_add_network, - wpa_cli_complete_bss, cli_cmd_flag_none, - " = connect using Interworking credentials" }, - { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss, - cli_cmd_flag_none, - " [,]... = request ANQP information" }, - { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss, - cli_cmd_flag_none, - " [QueryReq] = GAS request" }, - { "gas_response_get", wpa_cli_cmd_gas_response_get, - wpa_cli_complete_bss, cli_cmd_flag_none, - " [start,len] = Fetch last GAS response" }, -#endif /* CONFIG_INTERWORKING */ -#ifdef CONFIG_HS20 - { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss, - cli_cmd_flag_none, - " [,]... = request HS 2.0 ANQP information" - }, - { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list, - wpa_cli_complete_bss, cli_cmd_flag_none, - " = get HS20 nai home realm list" }, - { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request, - wpa_cli_complete_bss, cli_cmd_flag_none, - " = get Hotspot 2.0 OSU icon" }, - { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none, - "= fetch OSU provider information from all APs" }, - { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL, - cli_cmd_flag_none, - "= cancel fetch_osu command" }, -#endif /* CONFIG_HS20 */ - { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL, - cli_cmd_flag_none, - "<0/1> = disable/enable automatic reconnection" }, - { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL, - cli_cmd_flag_none, - " = request TDLS discovery with " }, - { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL, - cli_cmd_flag_none, - " = request TDLS setup with " }, - { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL, - cli_cmd_flag_none, - " = tear down TDLS with " }, - { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL, - cli_cmd_flag_none, - " = TDLS link status with " }, - { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL, - cli_cmd_flag_none, - " [nominal_msdu_size=#] " - "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] " - "= add WMM-AC traffic stream" }, - { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL, - cli_cmd_flag_none, - " = delete WMM-AC traffic stream" }, - { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL, - cli_cmd_flag_none, - "= show status for Wireless Multi-Media Admission-Control" }, - { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL, - cli_cmd_flag_none, - " [sec_channel_offset=] [center_freq1=] " - "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching " - "with TDLS peer" }, - { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL, - cli_cmd_flag_none, - " = disable channel switching with TDLS peer " }, - { "signal_poll", wpa_cli_cmd_signal_poll, NULL, - cli_cmd_flag_none, - "= get signal parameters" }, - { "signal_monitor", wpa_cli_cmd_signal_monitor, NULL, - cli_cmd_flag_none, - "= set signal monitor parameters" }, - { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL, - cli_cmd_flag_none, - "= get TX/RX packet counters" }, - { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL, - cli_cmd_flag_none, - "= trigger IEEE 802.1X/EAPOL reauthentication" }, -#ifdef CONFIG_AUTOSCAN - { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none, - "[params] = Set or unset (if none) autoscan parameters" }, -#endif /* CONFIG_AUTOSCAN */ -#ifdef CONFIG_WNM - { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none, - " [interval=#] = enter/exit WNM-Sleep mode" }, - { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none, - " [list]" - " [neighbor=,,,,[,]" - " = Send BSS Transition Management Query" }, -#endif /* CONFIG_WNM */ - { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive, - " = Sent unprocessed command" }, - { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none, - "= flush wpa_supplicant state" }, -#ifdef ANDROID - { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none, - " = driver private commands" }, -#endif /* ANDROID */ - { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none, - "= radio_work " }, - { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none, - " [] = Send vendor command" - }, - { "neighbor_rep_request", - wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none, - "[ssid=] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)" - }, - { "twt_setup", - wpa_cli_cmd_twt_setup, NULL, cli_cmd_flag_none, - "[dialog=] [exponent=] [mantissa=] [min_twt=] [setup_cmd=] [twt=] [requestor=0|1] [trigger=0|1] [implicit=0|1] [flow_type=0|1] [flow_id=<3-bit-id>] [protection=0|1] [twt_channel=] [control=] = Send TWT Setup frame" - }, - { "twt_teardown", - wpa_cli_cmd_twt_teardown, NULL, cli_cmd_flag_none, - "[flags=] = Send TWT Teardown frame" - }, - { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none, - "= flush ERP keys" }, - { "mac_rand_scan", - wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none, - " enable=<0/1> [addr=mac-address " - "mask=mac-address-mask] = scan MAC randomization" - }, - { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL, - cli_cmd_flag_none, - " = retrieve preferred freq list for the specified interface type" }, - { "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL, - cli_cmd_flag_none, - " = start P2P listen offload" }, - { "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL, - cli_cmd_flag_none, - "= stop P2P listen offload" }, -#ifdef CONFIG_DPP - { "dpp_qr_code", wpa_cli_cmd_dpp_qr_code, NULL, cli_cmd_flag_none, - "report a scanned DPP URI from a QR Code" }, - { "dpp_bootstrap_gen", wpa_cli_cmd_dpp_bootstrap_gen, NULL, - cli_cmd_flag_sensitive, - "type= [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" }, - { "dpp_bootstrap_remove", wpa_cli_cmd_dpp_bootstrap_remove, NULL, - cli_cmd_flag_none, - "*| = remove DPP bootstrap information" }, - { "dpp_bootstrap_get_uri", wpa_cli_cmd_dpp_bootstrap_get_uri, NULL, - cli_cmd_flag_none, - " = get DPP bootstrap URI" }, - { "dpp_bootstrap_info", wpa_cli_cmd_dpp_bootstrap_info, NULL, - cli_cmd_flag_none, - " = show DPP bootstrap information" }, - { "dpp_bootstrap_set", wpa_cli_cmd_dpp_bootstrap_set, NULL, - cli_cmd_flag_none, - " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, - { "dpp_auth_init", wpa_cli_cmd_dpp_auth_init, NULL, cli_cmd_flag_none, - "peer= [own=] = initiate DPP bootstrapping" }, - { "dpp_listen", wpa_cli_cmd_dpp_listen, NULL, cli_cmd_flag_none, - " = start DPP listen" }, - { "dpp_stop_listen", wpa_cli_cmd_dpp_stop_listen, NULL, - cli_cmd_flag_none, - "= stop DPP listen" }, - { "dpp_configurator_add", wpa_cli_cmd_dpp_configurator_add, NULL, - cli_cmd_flag_sensitive, - "[curve=..] [key=..] = add DPP configurator" }, - { "dpp_configurator_remove", wpa_cli_cmd_dpp_configurator_remove, NULL, - cli_cmd_flag_none, - "*| = remove DPP configurator" }, - { "dpp_configurator_get_key", wpa_cli_cmd_dpp_configurator_get_key, - NULL, cli_cmd_flag_none, - " = Get DPP configurator's private key" }, - { "dpp_configurator_sign", wpa_cli_cmd_dpp_configurator_sign, NULL, - cli_cmd_flag_none, - "conf= configurator= = generate self DPP configuration" }, - { "dpp_pkex_add", wpa_cli_cmd_dpp_pkex_add, NULL, - cli_cmd_flag_sensitive, - "add PKEX code" }, - { "dpp_pkex_remove", wpa_cli_cmd_dpp_pkex_remove, NULL, - cli_cmd_flag_none, - "*| = remove DPP pkex information" }, -#ifdef CONFIG_DPP2 - { "dpp_controller_start", wpa_cli_cmd_dpp_controller_start, NULL, - cli_cmd_flag_none, - "[tcp_port=] [role=..] = start DPP controller" }, - { "dpp_controller_stop", wpa_cli_cmd_dpp_controller_stop, NULL, - cli_cmd_flag_none, - "= stop DPP controller" }, - { "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL, - cli_cmd_flag_none, - "own= iter= = start DPP chirp" }, - { "dpp_stop_chirp", wpa_cli_cmd_dpp_stop_chirp, NULL, - cli_cmd_flag_none, - "= stop DPP chirp" }, -#endif /* CONFIG_DPP2 */ -#endif /* CONFIG_DPP */ - { "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none, - "= list all BSS entries (scan results)" }, -#ifdef CONFIG_PASN - { "pasn_auth_start", wpa_cli_cmd_pasn_auth_start, NULL, - cli_cmd_flag_none, - "bssid= akmp= cipher= group= nid= = Start PASN authentication" }, - { "pasn_auth_stop", wpa_cli_cmd_pasn_auth_stop, NULL, - cli_cmd_flag_none, - "= Stop PASN authentication" }, - { "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL, - cli_cmd_flag_none, - "= Get the PTKSA Cache" }, - { "pasn_deauth", wpa_cli_cmd_pasn_deauth, NULL, - cli_cmd_flag_none, - "bssid= = Remove PASN PTKSA state" }, -#endif /* CONFIG_PASN */ - { "mscs", wpa_cli_cmd_mscs, NULL, - cli_cmd_flag_none, - " [up_bitmap=] [up_limit=] [stream_timeout=] [frame_classifier=] = Configure MSCS request" }, - { "scs", wpa_cli_cmd_scs, NULL, - cli_cmd_flag_none, - "[scs_id=] [scs_up=<0-7>] [classifier_type=<4|10>] [classifier params based on classifier type] [tclas_processing=<0|1>] [scs_id=] ... = Send SCS request" }, - { "dscp_resp", wpa_cli_cmd_dscp_resp, NULL, - cli_cmd_flag_none, - "<[reset]>/<[solicited] [policy_id=1 status=0...]> [more] = Send DSCP response" }, - { "dscp_query", wpa_cli_cmd_dscp_query, NULL, - cli_cmd_flag_none, - "wildcard/domain_name= = Send DSCP Query" }, - { NULL, NULL, NULL, cli_cmd_flag_none, NULL } -}; - - /* * Prints command usage, lines are padded with the specified string. */ @@ -4075,7 +295,7 @@ static void print_help(const char *cmd) } } -#ifdef notyet + static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd) { const char *c, *delim; @@ -4096,6 +316,7 @@ static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd) return 0; } + static char ** wpa_list_cmd_list(void) { char **res; @@ -4133,9 +354,8 @@ static char ** wpa_list_cmd_list(void) return res; } -#endif /* notyet */ -#ifdef INTERACTIVE + static char ** wpa_cli_cmd_completion(const char *cmd, const char *str, int pos) { @@ -4184,7 +404,7 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos) os_free(cmd); return res; } -#endif /* INTERACTIVE */ + static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -4234,14 +454,13 @@ static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) printf("Unknown command '%s'\n", argv[0]); ret = 1; } else { - - ret = match->handler(ctrl, argc, &argv[1]); + ret = match->handler(ctrl, argc - 1, &argv[1]); } return ret; } -#ifdef INTERACTIVE + static int wpa_cli_exec(const char *program, const char *arg1, const char *arg2) { @@ -4264,6 +483,7 @@ static int wpa_cli_exec(const char *program, const char *arg1, return res; } + static void wpa_cli_action_process(const char *msg) { const char *pos; @@ -4449,9 +669,11 @@ static int wpa_cli_open_global_ctrl(void) } update_stations(ctrl_conn); } + return 0; } + static void wpa_cli_reconnect(void) { wpa_cli_close_connection(); @@ -4626,7 +848,6 @@ static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx) } - static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx) { wpa_cli_recv_pending(mon_conn, 0); @@ -4686,7 +907,6 @@ static void start_edit(void) } - static void update_bssid_list(struct wpa_ctrl *ctrl) { char buf[4096]; @@ -4748,7 +968,7 @@ static void update_ifnames(struct wpa_ctrl *ctrl) pos = end + 1; } } -#endif /* INTERACTIVE */ + static void update_creds(struct wpa_ctrl *ctrl) { @@ -4813,7 +1033,7 @@ static void update_networks(struct wpa_ctrl *ctrl) } } -#ifdef INTERACTIVE + static void update_stations(struct wpa_ctrl *ctrl) { #ifdef CONFIG_AP @@ -4835,8 +1055,6 @@ static void update_stations(struct wpa_ctrl *ctrl) } - - static void try_connection(void *eloop_ctx, void *timeout_ctx) { if (ctrl_conn) @@ -5021,9 +1239,9 @@ static char * wpa_cli_get_default_ifname(void) return ifname; } -#endif /* INTERACTIVE */ -int cli_main(int argc, char *argv[]) + +int main(int argc, char *argv[]) { int c; int daemonize = 0; @@ -5043,11 +1261,9 @@ int cli_main(int argc, char *argv[]) case 'B': daemonize = 1; break; -#ifndef CONFIG_ZEPHYR case 'g': global = optarg; break; -#endif case 'G': ping_interval = atoi(optarg); break; @@ -5079,7 +1295,6 @@ int cli_main(int argc, char *argv[]) } } -#ifdef INTERACTIVE interactive = (argc == optind) && (action_file == NULL); if (interactive) @@ -5091,6 +1306,8 @@ int cli_main(int argc, char *argv[]) if (global && wpa_cli_open_global_ctrl() < 0) return -1; + eloop_register_signal_terminate(wpa_cli_terminate, NULL); + if (ctrl_ifname == NULL) ctrl_ifname = wpa_cli_get_default_ifname(); @@ -5109,12 +1326,9 @@ int cli_main(int argc, char *argv[]) wpa_cli_attached = 1; } } - } - - else if (interactive) { + } else if (interactive) { wpa_cli_interactive(); - } - else { + } else { if (!global && wpa_cli_open_connection(ctrl_ifname, 0) < 0) { fprintf(stderr, "Failed to connect to non-global " @@ -5140,24 +1354,19 @@ int cli_main(int argc, char *argv[]) if (action_file) wpa_cli_action(ctrl_conn); else -#endif /* INTERACTIVE */ - ret = wpa_request(ctrl_conn, argc, - argv); -#ifdef INTERACTIVE + ret = wpa_request(ctrl_conn, argc - optind, + &argv[optind]); } -#endif /* INTERACTIVE */ os_free(ctrl_ifname); -#ifdef INTERACTIVE -// eloop_destroy(); + eloop_destroy(); wpa_cli_cleanup(); -#endif /* INTERACTIVE */ return ret; } #else /* CONFIG_CTRL_IFACE */ -int cli_main(int argc, char *argv[]) +int main(int argc, char *argv[]) { printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); return -1; diff --git a/wpa_supplicant/wpa_cli_cmds.c b/wpa_supplicant/wpa_cli_cmds.c new file mode 100644 index 0000000000..4c9ddd660f --- /dev/null +++ b/wpa_supplicant/wpa_cli_cmds.c @@ -0,0 +1,3692 @@ +/* + * WPA CLI commands + * Copyright (c) 2004-2022, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "includes.h" + +#include "common/cli.h" +#include "common/wpa_ctrl.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/edit.h" +#include "utils/list.h" +#include "wpa_supplicant_i.h" +#include "ctrl_iface.h" +#include "common/version.h" +#include "common/ieee802_11_defs.h" + +#define CMD_BUF_LEN 1024 + +#define VENDOR_ELEM_FRAME_ID \ + " 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \ + "3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \ + "7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \ + "11: Assoc Req (P2P), 12: Assoc Resp (P2P)" + +static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(creds); /* struct cli_txt_entry */ +#ifdef CONFIG_AP +static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */ +#endif /* CONFIG_AP */ + +static void wpa_cli_msg_cb(char *msg, size_t len) +{ + wpa_printf(MSG_INFO, "%s\n", msg); +} + +static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, + int argc, char *argv[]) +{ + char * buf = NULL; + int ret = 0; + if (argc < min_args) { + wpa_printf(MSG_INFO, "Invalid %s command - at least %d argument%s " + "required.\n", cmd, min_args, + min_args > 1 ? "s are" : " is"); + return -1; + } + buf = os_zalloc(sizeof(char) * CMD_BUF_LEN); + if (!buf){ + printf ("Failed to allocate mem for command buf\n"); + return -1; + } + memset(buf, '\0', CMD_BUF_LEN); + if (write_cmd(buf, CMD_BUF_LEN, cmd, argc-1, argv) < 0){ + ret = -1; + goto out; + } + ret = wpa_ctrl_command(ctrl, buf); + +out: + if (buf) + os_free(buf); + + return ret; +} + + +static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "IFNAME"); +} + + +static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc > 0 && os_strcmp(argv[0], "verbose") == 0) + return wpa_ctrl_command(ctrl, "STATUS-VERBOSE"); + if (argc > 0 && os_strcmp(argv[0], "wps") == 0) + return wpa_ctrl_command(ctrl, "STATUS-WPS"); + if (argc > 0 && os_strcmp(argv[0], "driver") == 0) + return wpa_ctrl_command(ctrl, "STATUS-DRIVER"); + return wpa_ctrl_command(ctrl, "STATUS"); +} + + +static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PING"); +} + + +static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RELOG"); +} + + +static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv); +} + + +static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "MIB"); +} + + +static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PMKSA"); +} + + +static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PMKSA_FLUSH"); +} + + +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + +static int wpa_cli_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PMKSA_GET", 1, argc, argv); +} + + +static int wpa_cli_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PMKSA_ADD", 8, argc, argv); +} + + +#ifdef CONFIG_MESH + +static int wpa_cli_mesh_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_PMKSA_GET", 1, argc, argv); +} + + +static int wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_PMKSA_ADD", 4, argc, argv); +} + +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + +static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256]; + int res; + + if (argc == 1) { + res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]); + if (os_snprintf_error(sizeof(cmd), res)) { + wpa_printf(MSG_INFO, "Too long SET command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); + } + + return wpa_cli_cmd(ctrl, "SET", 2, argc, argv); +} + + +static char ** wpa_cli_complete_set(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + const char *fields[] = { + /* runtime values */ + "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod", + "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime", + "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout", + "wps_fragment_size", "wps_version_number", "ampdu", + "tdls_testing", "tdls_disabled", "pno", "radio_disabled", + "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps", + "no_keep_alive", + /* global configuration parameters */ + "ctrl_interface", "no_ctrl_interface", "ctrl_interface_group", + "eapol_version", "ap_scan", "bgscan", +#ifdef CONFIG_MESH + "user_mpm", "max_peer_links", "mesh_max_inactivity", + "dot11RSNASAERetransPeriod", +#endif /* CONFIG_MESH */ + "disable_scan_offload", "fast_reauth", "opensc_engine_path", + "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers", + "pcsc_reader", "pcsc_pin", "external_sim", "driver_param", + "dot11RSNAConfigPMKLifetime", + "dot11RSNAConfigPMKReauthThreshold", + "dot11RSNAConfigSATimeout", +#ifndef CONFIG_NO_CONFIG_WRITE + "update_config", +#endif /* CONFIG_NO_CONFIG_WRITE */ + "load_dynamic_eap", +#ifdef CONFIG_WPS + "uuid", "device_name", "manufacturer", "model_name", + "model_number", "serial_number", "device_type", "os_version", + "config_methods", "wps_cred_processing", "wps_vendor_ext_m1", +#endif /* CONFIG_WPS */ +#ifdef CONFIG_P2P + "sec_device_type", + "p2p_listen_reg_class", "p2p_listen_channel", + "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent", + "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss", + "p2p_group_idle", "p2p_passphrase_len", "p2p_pref_chan", + "p2p_no_go_freq", "p2p_add_cli_chan", + "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht", + "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface", + "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask", + "ip_addr_start", "ip_addr_end", "p2p_go_edmg", +#endif /* CONFIG_P2P */ + "country", "bss_max_count", "bss_expiration_age", + "bss_expiration_scan_count", "filter_ssids", "filter_rssi", + "max_num_sta", "disassoc_low_ack", "ap_isolate", +#ifdef CONFIG_HS20 + "hs20", +#endif /* CONFIG_HS20 */ + "interworking", "hessid", "access_network_type", "pbc_in_m1", + "go_interworking", "go_access_network_type", "go_internet", + "go_venue_group", "go_venue_type", + "autoscan", "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", + "wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend", + "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf", + "sae_groups", "dtim_period", "beacon_int", + "ap_vendor_elements", "ignore_old_scan_res", "freq_list", + "scan_cur_freq", "scan_res_valid_for_connect", + "sched_scan_interval", + "tdls_external_control", "osu_dir", "wowlan_triggers", + "p2p_search_delay", "mac_addr", "rand_addr_lifetime", + "preassoc_mac_addr", "key_mgmt_offload", "passive_scan", + "reassoc_same_bss_optim", "wps_priority", + "ap_assocresp_elements", +#ifdef CONFIG_TESTING_OPTIONS + "ignore_auth_resp", +#endif /* CONFIG_TESTING_OPTIONS */ + "relative_rssi", "relative_band_adjust", + "extended_key_id", + }; + int i, num_fields = ARRAY_SIZE(fields); + + if (arg == 1) { + char **res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(fields[i]); + if (res[i] == NULL) + return res; + } + return res; + } + + if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0) + return cli_txt_list_array(&bsses); + + return NULL; +} + +static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DUMP"); +} + + +static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); +} + + +static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "GET", 1, argc, argv); +} + + +static char ** wpa_cli_complete_get(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + const char *fields[] = { + "ctrl_interface", "ctrl_interface_group", + "eapol_version", "ap_scan", +#ifdef CONFIG_MESH + "user_mpm", "max_peer_links", "mesh_max_inactivity", +#endif /* CONFIG_MESH */ + "disable_scan_offload", "fast_reauth", "opensc_engine_path", + "pkcs11_engine_path", "pkcs11_module_path", "openssl_ciphers", + "pcsc_reader", "pcsc_pin", "external_sim", "driver_param", + "dot11RSNAConfigPMKLifetime", + "dot11RSNAConfigPMKReauthThreshold", + "dot11RSNAConfigSATimeout", +#ifndef CONFIG_NO_CONFIG_WRITE + "update_config", +#endif /* CONFIG_NO_CONFIG_WRITE */ +#ifdef CONFIG_WPS + "device_name", "manufacturer", "model_name", "model_number", + "serial_number", "config_methods", "wps_cred_processing", +#endif /* CONFIG_WPS */ +#ifdef CONFIG_P2P + "p2p_listen_reg_class", "p2p_listen_channel", + "p2p_oper_reg_class", "p2p_oper_channel", "p2p_go_intent", + "p2p_ssid_postfix", "persistent_reconnect", "p2p_intra_bss", + "p2p_group_idle", "p2p_passphrase_len", "p2p_add_cli_chan", + "p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht", + "p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface", + "p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask", + "ip_addr_start", "ip_addr_end", +#endif /* CONFIG_P2P */ + "bss_max_count", "bss_expiration_age", + "bss_expiration_scan_count", "filter_ssids", "filter_rssi", + "max_num_sta", "disassoc_low_ack", "ap_isolate", +#ifdef CONFIG_HS20 + "hs20", +#endif /* CONFIG_HS20 */ + "interworking", "access_network_type", "pbc_in_m1", "autoscan", + "go_interworking", "go_access_network_type", "go_internet", + "go_venue_group", "go_venue_type", + "wps_nfc_dev_pw_id", "ext_password_backend", + "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf", + "dtim_period", "beacon_int", "ignore_old_scan_res", + "scan_cur_freq", "scan_res_valid_for_connect", + "sched_scan_interval", + "sched_scan_start_delay", + "tdls_external_control", "osu_dir", "wowlan_triggers", + "p2p_search_delay", "mac_addr", "rand_addr_lifetime", + "preassoc_mac_addr", "key_mgmt_offload", "passive_scan", + "reassoc_same_bss_optim", "extended_key_id" + }; + int i, num_fields = ARRAY_SIZE(fields); + + if (arg == 1) { + char **res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(fields[i]); + if (res[i] == NULL) + return res; + } + return res; + } + + return NULL; +} + + +static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "LOGOFF"); +} + + +static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "LOGON"); +} + + +static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "REASSOCIATE"); +} + + +static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "REATTACH"); +} + + +static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv); +} + + +static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv); +} + + +static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv); +} + + +static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv); +} + + +static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv); +} + + +static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256]; + int res; + + if (argc < 1) + res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0"); + else + res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]); + if (os_snprintf_error(sizeof(cmd), res)) { + wpa_printf(MSG_INFO, "Too long BSS_FLUSH command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv); +} + + +static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc == 0) { + wpa_printf(MSG_INFO, "Invalid WPS_PIN command: need one or two arguments:\n" + "- BSSID: use 'any' to select any\n" + "- PIN: optional, used only with devices that have no " + "display\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "WPS_CANCEL"); +} + + +#ifdef CONFIG_WPS_NFC + +static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv); +} + + +static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + int ret; + char *buf; + size_t buflen; + + if (argc != 1) { + wpa_printf(MSG_INFO, "Invalid 'wps_nfc_tag_read' command - one argument " + "is required.\n"); + return -1; + } + + buflen = 18 + os_strlen(argv[0]); + buf = os_malloc(buflen); + if (buf == NULL) + return -1; + os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]); + + ret = wpa_ctrl_command(ctrl, buf); + os_free(buf); + + return ret; +} + + +static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv); +} + + +static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv); +} + + +static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv); +} + +#endif /* CONFIG_WPS_NFC */ + + +static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256]; + int res; + + if (argc == 2) + res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", + argv[0], argv[1]); + else if (argc == 5 || argc == 6) { + char ssid_hex[2 * SSID_MAX_LEN + 1]; + char key_hex[2 * 64 + 1]; + int i; + + ssid_hex[0] = '\0'; + for (i = 0; i < SSID_MAX_LEN; i++) { + if (argv[2][i] == '\0') + break; + os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); + } + + key_hex[0] = '\0'; + if (argc == 6) { + for (i = 0; i < 64; i++) { + if (argv[5][i] == '\0') + break; + os_snprintf(&key_hex[i * 2], 3, "%02x", + argv[5][i]); + } + } + + res = os_snprintf(cmd, sizeof(cmd), + "WPS_REG %s %s %s %s %s %s", + argv[0], argv[1], ssid_hex, argv[3], argv[4], + key_hex); + } else { + wpa_printf(MSG_INFO, "Invalid WPS_REG command: need two arguments:\n" + "- BSSID of the target AP\n" + "- AP PIN\n"); + wpa_printf(MSG_INFO, "Alternatively, six arguments can be used to " + "reconfigure the AP:\n" + "- BSSID of the target AP\n" + "- AP PIN\n" + "- new SSID\n" + "- new auth (OPEN, WPAPSK, WPA2PSK)\n" + "- new encr (NONE, WEP, TKIP, CCMP)\n" + "- new key\n"); + return -1; + } + + if (os_snprintf_error(sizeof(cmd), res)) { + wpa_printf(MSG_INFO, "Too long WPS_REG command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv); +} + + +static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "WPS_ER_STOP"); + +} + + +static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid WPS_ER_PIN command: need at least two " + "arguments:\n" + "- UUID: use 'any' to select any\n" + "- PIN: Enrollee PIN\n" + "optional: - Enrollee MAC address\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv); +} + + +static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv); +} + + +static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc != 2) { + wpa_printf(MSG_INFO, "Invalid WPS_ER_LEARN command: need two arguments:\n" + "- UUID: specify which AP to use\n" + "- PIN: AP PIN\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv); +} + + +static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc != 2) { + wpa_printf(MSG_INFO, "Invalid WPS_ER_SET_CONFIG command: need two " + "arguments:\n" + "- UUID: specify which AP to use\n" + "- Network configuration id\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv); +} + + +static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc == 5 || argc == 6) { + char ssid_hex[2 * SSID_MAX_LEN + 1]; + char key_hex[2 * 64 + 1]; + int i; + + ssid_hex[0] = '\0'; + for (i = 0; i < SSID_MAX_LEN; i++) { + if (argv[2][i] == '\0') + break; + os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); + } + + key_hex[0] = '\0'; + if (argc == 6) { + for (i = 0; i < 64; i++) { + if (argv[5][i] == '\0') + break; + os_snprintf(&key_hex[i * 2], 3, "%02x", + argv[5][i]); + } + } + + res = os_snprintf(cmd, sizeof(cmd), + "WPS_ER_CONFIG %s %s %s %s %s %s", + argv[0], argv[1], ssid_hex, argv[3], argv[4], + key_hex); + } else { + wpa_printf(MSG_INFO, "Invalid WPS_ER_CONFIG command: need six arguments:\n" + "- AP UUID\n" + "- AP PIN\n" + "- new SSID\n" + "- new auth (OPEN, WPAPSK, WPA2PSK)\n" + "- new encr (NONE, WEP, TKIP, CCMP)\n" + "- new key\n"); + return -1; + } + + if (os_snprintf_error(sizeof(cmd), res)) { + wpa_printf(MSG_INFO, "Too long WPS_ER_CONFIG command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +#ifdef CONFIG_WPS_NFC +static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc != 2) { + wpa_printf(MSG_INFO, "Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two " + "arguments:\n" + "- WPS/NDEF: token format\n" + "- UUID: specify which AP to use\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv); +} +#endif /* CONFIG_WPS_NFC */ + + +static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv); +} + +static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid IDENTITY command: needs two arguments " + "(network id and identity)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long IDENTITY command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long IDENTITY command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid PASSWORD command: needs two arguments " + "(network id and password)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PASSWORD command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PASSWORD command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid NEW_PASSWORD command: needs two arguments " + "(network id and password)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long NEW_PASSWORD command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long NEW_PASSWORD command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid PIN command: needs two arguments " + "(network id and pin)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PIN command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PIN command.\n"); + return -1; + } + pos += ret; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid OTP command: needs two arguments (network " + "id and password)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long OTP command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long OTP command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid SIM command: needs two arguments " + "(network id and SIM operation response)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long SIM command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long SIM command.\n"); + return -1; + } + pos += ret; + } + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_psk_passphrase(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid PSK_PASSPHRASE command: needs two arguments (network id and PSK/passphrase)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PSK_PASSPHRASE-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PSK_PASSPHRASE command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PSK_PASSPHRASE command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256], *pos, *end; + int i, ret; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid PASSPHRASE command: needs two arguments " + "(network id and passphrase)\n"); + return -1; + } + + end = cmd + sizeof(cmd); + pos = cmd; + ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", + argv[0], argv[1]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PASSPHRASE command.\n"); + return -1; + } + pos += ret; + for (i = 2; i < argc; i++) { + ret = os_snprintf(pos, end - pos, " %s", argv[i]); + if (os_snprintf_error(end - pos, ret)) { + wpa_printf(MSG_INFO, "Too long PASSPHRASE command.\n"); + return -1; + } + pos += ret; + } + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid BSSID command: needs two arguments (network " + "id and BSSID)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv); +} + + +static int wpa_cli_cmd_bssid_ignore(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "BSSID_IGNORE", 0, argc, argv); +} + + +static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv); +} + + +static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "LIST_NETWORKS", 0, argc, argv); +} + + +static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "ADD_NETWORK"); +} + + +static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv); +} + + +static void wpa_cli_show_network_variables(void) +{ + wpa_printf(MSG_INFO, "set_network variables:\n" + " ssid (network name, SSID)\n" + " psk (WPA passphrase or pre-shared key)\n" + " key_mgmt (key management protocol)\n" + " identity (EAP identity)\n" + " password (EAP password)\n" + " ...\n" + "\n" + "Note: Values are entered in the same format as the " + "configuration file is using,\n" + "i.e., strings values need to be inside double quotation " + "marks.\n" + "For example: set_network 1 ssid \"network name\"\n" + "\n" + "Please see wpa_supplicant.conf documentation for full list " + "of\navailable variables.\n"); +} + + +static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc == 0) { + wpa_cli_show_network_variables(); + return 0; + } + + if (argc < 3) { + wpa_printf(MSG_INFO, "Invalid SET_NETWORK command: needs three arguments\n" + "(network id, variable name, and value)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv); +} + + +static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc == 0) { + wpa_cli_show_network_variables(); + return 0; + } + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid GET_NETWORK command: needs two arguments\n" + "(network id and variable name)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv); +} + + +static const char *network_fields[] = { + "ssid", "scan_ssid", "bssid", "bssid_ignore", + "bssid_accept", "psk", "proto", "key_mgmt", + "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq", + "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1", + "vht_center_freq2", "ht", "edmg", +#ifdef IEEE8021X_EAPOL + "eap", "identity", "anonymous_identity", "password", "ca_cert", + "ca_path", "client_cert", "private_key", "private_key_passwd", + "dh_file", "subject_match", "altsubject_match", + "check_cert_subject", + "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2", + "client_cert2", "private_key2", "private_key2_passwd", + "dh_file2", "subject_match2", "altsubject_match2", + "check_cert_subject2", + "domain_suffix_match2", "domain_match2", "phase1", "phase2", + "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id", + "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id", + "engine", "engine2", "eapol_flags", "sim_num", + "openssl_ciphers", "erp", +#endif /* IEEE8021X_EAPOL */ + "wep_key0", "wep_key1", "wep_key2", "wep_key3", + "wep_tx_keyidx", "priority", +#ifdef IEEE8021X_EAPOL + "eap_workaround", "pac_file", "fragment_size", "ocsp", +#endif /* IEEE8021X_EAPOL */ + "mode", + "proactive_key_caching", "disabled", "id_str", + "ieee80211w", + "mixed_cell", "frequency", "fixed_freq", +#ifdef CONFIG_MESH + "no_auto_peer", "mesh_rssi_threshold", + "mesh_basic_rates", "dot11MeshMaxRetries", + "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout", + "dot11MeshHoldingTimeout", +#endif /* CONFIG_MESH */ + "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", + "wpa_deny_ptk0_rekey", + "enable_edmg", "edmg_channel", +#ifdef CONFIG_P2P + "go_p2p_dev_addr", "p2p_client_list", "psk_list", +#endif /* CONFIG_P2P */ +#ifdef CONFIG_HT_OVERRIDES + "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc", + "ht40_intolerant", "disable_max_amsdu", "ampdu_factor", + "ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc", +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1", + "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4", + "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7", + "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2", + "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5", + "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8", +#endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + "disable_he", +#endif /* CONFIG_HE_OVERRIDES */ + "ap_max_inactivity", "dtim_period", "beacon_int", +#ifdef CONFIG_MACSEC + "macsec_policy", + "macsec_integ_only", + "macsec_replay_protect", + "macsec_replay_window", + "macsec_port", + "mka_priority", +#endif /* CONFIG_MACSEC */ +#ifdef CONFIG_HS20 + "update_identifier", +#endif /* CONFIG_HS20 */ + "mac_addr", "pbss", "wps_disabled" +}; + + +static char ** wpa_cli_complete_network(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + int i, num_fields = ARRAY_SIZE(network_fields); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&networks); + break; + case 2: + res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(network_fields[i]); + if (res[i] == NULL) + break; + } + } + return res; +} + + +static char ** wpa_cli_complete_network_id(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + if (arg == 1) + return cli_txt_list_array(&networks); + return NULL; +} + + +static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc == 0) { + wpa_cli_show_network_variables(); + return 0; + } + + if (argc < 3) { + wpa_printf(MSG_INFO, "Invalid DUP_NETWORK command: needs three arguments\n" + "(src netid, dest netid, and variable name)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv); +} + + +static char ** wpa_cli_complete_dup_network(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + int i, num_fields = ARRAY_SIZE(network_fields); + char **res = NULL; + + switch (arg) { + case 1: + case 2: + res = cli_txt_list_array(&networks); + break; + case 3: + res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(network_fields[i]); + if (res[i] == NULL) + break; + } + } + return res; +} + + +static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "LIST_CREDS"); +} + + +static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "ADD_CRED"); +} + + +static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv); +} + + +static const char * const cred_fields[] = { + "temporary", "priority", "sp_priority", "pcsc", "eap", + "update_identifier", "min_dl_bandwidth_home", "min_ul_bandwidth_home", + "min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load", + "req_conn_capab", "ocsp", "sim_num", "realm", "username", "password", + "ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi", + "ca_cert_id", "cert_id", "key_id", "engine_id", "engine", + "milenage", "domain_suffix_match", "domain", "phase1", "phase2", + "roaming_consortium", "required_roaming_consortium", "excluded_ssid", + "roaming_partner", "provisioning_sp" +}; + + +static char ** wpa_cli_complete_cred(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + int i, num_fields = ARRAY_SIZE(cred_fields); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&creds); + break; + case 2: + res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(cred_fields[i]); + if (res[i] == NULL) + break; + } + } + return res; +} + + +static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc != 3) { + wpa_printf(MSG_INFO, "Invalid SET_CRED command: needs three arguments\n" + "(cred id, variable name, and value)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv); +} + + +static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc != 2) { + wpa_printf(MSG_INFO, "Invalid GET_CRED command: needs two arguments\n" + "(cred id, variable name)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv); +} + + +static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DISCONNECT"); +} + + +static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RECONNECT"); +} + + +static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); +} + + +static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv); +} + + +static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); +} + + +static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "ABORT_SCAN"); +} + + +static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv); +} + + +static char ** wpa_cli_complete_bss(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&bsses); + break; + } + + return res; +} + + +static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc < 1 || argc > 3) { + wpa_printf(MSG_INFO, "Invalid GET_CAPABILITY command: need at least one argument and max three arguments\n"); + return -1; + } + + if (argc > 1 && os_strcmp(argv[0], "key_mgmt") != 0 && + os_strncmp(argv[1], "iftype=", 7) == 0) { + wpa_printf(MSG_INFO, "Invalid GET_CAPABILITY command: 'iftype=' param is allowed only for 'key_mgmt'\n"); + return -1; + } + + if (argc == 2 && os_strcmp(argv[1], "strict") != 0 && + os_strncmp(argv[1], "iftype=", 7) != 0) { + wpa_printf(MSG_INFO, "Invalid GET_CAPABILITY command: the second argument, if any, must be 'strict' OR 'iftype='\n"); + return -1; + } + + if (argc == 3 && os_strcmp(argv[2], "strict") != 0) { + wpa_printf(MSG_INFO, "Invalid GET_CAPABILITY command: the third argument, if any, must be 'strict'\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv); +} + + +static char ** wpa_cli_complete_get_capability(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + const char *fields[] = { + "eap", "pairwise", "group", "group_mgmt", "key_mgmt", + "proto", "auth_alg", "modes", "channels", "freq", +#ifdef CONFIG_TDLS + "tdls", +#endif /* CONFIG_TDLS */ +#ifdef CONFIG_ERP + "erp", +#endif /* CONFIG_ERP */ +#ifdef CONFIG_FIPS + "fips", +#endif /* CONFIG_FIPS */ +#ifdef CONFIG_ACS + "acs", +#endif /* CONFIG_ACS */ + }; + const char *iftypes[] = { + "iftype=STATION", "iftype=AP", "iftype=P2P_CLIENT", + "iftype=P2P_GO", "iftype=AP_VLAN", "iftype=IBSS", "iftype=NAN", + "iftype=P2P_DEVICE", "iftype=MESH", + }; + int i, num_fields = ARRAY_SIZE(fields); + int num_iftypes = ARRAY_SIZE(iftypes); + char **res = NULL; + + if (arg == 1) { + res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(fields[i]); + if (res[i] == NULL) + return res; + } + } + if (arg == 2) { + /* the second argument can be "iftype=" OR + * "strict" */ + res = os_calloc(num_iftypes + 2, sizeof(char *)); + if (!res) + return NULL; + res[0] = os_strdup("strict"); + if (!res[0]) + return res; + for (i = 0; i < num_iftypes; i++) { + res[i + 1] = os_strdup(iftypes[i]); + if (!res[i + 1]) + return res; + } + } + if (arg == 3) { + res = os_calloc(1 + 1, sizeof(char *)); + if (res == NULL) + return NULL; + res[0] = os_strdup("strict"); + } + return res; +} + +static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RECONFIGURE"); +} + + +static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "TERMINATE"); +} + + +static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc < 1) { + wpa_printf(MSG_INFO, "Invalid INTERFACE_ADD command: needs at least one " + "argument (interface name)\n" + "All arguments: ifname confname driver ctrl_interface " + "driver_param bridge_name [create]\n"); + return -1; + } + + /* + * INTERFACE_ADD TABTABTABTAB + * TAB[TAB[TAB]] + */ + res = os_snprintf(cmd, sizeof(cmd), + "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", + argv[0], + argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", + argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", + argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "", + argc > 7 ? argv[7] : ""); + if (os_snprintf_error(sizeof(cmd), res)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv); +} + + +static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); +} + + +#ifdef CONFIG_AP +static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "STA", 1, argc, argv); +} + + +static char ** wpa_cli_complete_sta(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&stations); + break; + } + + return res; +} + + +static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd, + char *addr, size_t addr_len, int print) +{ + char buf[CMD_BUF_LEN], *pos; + size_t len; + int ret; + + if (ctrl_conn == NULL) { + wpa_printf(MSG_INFO, "Not connected to hostapd - command dropped.\n"); + return -1; + } + if (ifname_prefix) { + os_snprintf(buf, sizeof(buf), "IFNAME=%s %s", + ifname_prefix, cmd); + buf[sizeof(buf) - 1] = '\0'; + cmd = buf; + } + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + wpa_printf(MSG_INFO, "'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + wpa_printf(MSG_INFO, "'%s' command failed.\n", cmd); + return -1; + } + + buf[len] = '\0'; + if (os_memcmp(buf, "FAIL", 4) == 0 || + os_memcmp(buf, "UNKNOWN COMMAND", 15) == 0) + return -1; + if (print) + wpa_printf(MSG_INFO, "%s", buf); + + pos = buf; + while (*pos != '\0' && *pos != '\n') + pos++; + *pos = '\0'; + os_strlcpy(addr, buf, addr_len); + return 0; +} + + +static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char addr[32], cmd[64]; + + if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1)) + return 0; + do { + os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); + } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0); + + return -1; +} + + +static int wpa_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char addr[32], cmd[64]; + + if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0)) + return 0; + do { + if (os_strcmp(addr, "") != 0) + wpa_printf(MSG_INFO, "%s\n", addr); + os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); + } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0); + + return 0; +} + + +static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv); +} + + +static char ** wpa_cli_complete_deauthenticate(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&stations); + break; + } + + return res; +} + + +static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv); +} + + +static char ** wpa_cli_complete_disassociate(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&stations); + break; + } + + return res; +} + + +static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv); +} + + +static int wpa_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "UPDATE_BEACON"); +} + +#endif /* CONFIG_AP */ + + +static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "SUSPEND"); +} + + +static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RESUME"); +} + + +#ifdef CONFIG_TESTING_OPTIONS +static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DROP_SA"); +} +#endif /* CONFIG_TESTING_OPTIONS */ + + +static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv); +} + + +#ifdef CONFIG_MESH + +static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv); +} + + +static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv); +} + + +static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv); +} + + +static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv); +} + + +static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv); +} + + +static int wpa_cli_cmd_mesh_link_probe(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_LINK_PROBE", 1, argc, argv); +} + +#endif /* CONFIG_MESH */ + + +#ifdef CONFIG_P2P + +static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv); +} + + +static char ** wpa_cli_complete_p2p_find(const char *str, int pos) +{ + char **res = NULL; + int arg = get_cmd_arg_num(str, pos); + + res = os_calloc(6, sizeof(char *)); + if (res == NULL) + return NULL; + res[0] = os_strdup("type=social"); + if (res[0] == NULL) { + os_free(res); + return NULL; + } + res[1] = os_strdup("type=progressive"); + if (res[1] == NULL) + return res; + res[2] = os_strdup("delay="); + if (res[2] == NULL) + return res; + res[3] = os_strdup("dev_id="); + if (res[3] == NULL) + return res; + if (arg == 1) + res[4] = os_strdup("[timeout]"); + + return res; +} + + +static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_STOP_FIND"); +} + + +static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv); +} + + +static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv); +} + + +static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv); +} + + +static char ** wpa_cli_complete_p2p_connect(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&p2p_peers); + break; + } + + return res; +} + + +static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv); +} + + +static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv); +} + + +static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&p2p_groups); + break; + } + + return res; +} + + +static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv); +} + + +static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc != 2 && argc != 3) { + wpa_printf(MSG_INFO, "Invalid P2P_PROV_DISC command: needs at least " + "two arguments, address and config method\n" + "(display, keypad, or pbc) and an optional join\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv); +} + + +static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE"); +} + + +static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[CMD_BUF_LEN]; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid P2P_SERV_DISC_REQ command: needs two " + "or more arguments (address and TLVs)\n"); + return -1; + } + + if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0) + return -1; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[CMD_BUF_LEN]; + int res; + + if (argc != 4) { + wpa_printf(MSG_INFO, "Invalid P2P_SERV_DISC_RESP command: needs four " + "arguments (freq, address, dialog token, and TLVs)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + if (os_snprintf_error(sizeof(cmd), res)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE"); +} + + +static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH"); +} + + +static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc < 3) { + wpa_printf(MSG_INFO, "Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv); +} + + +static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc < 5 || argc > 6) { + wpa_printf(MSG_INFO, "Invalid P2P_SERVICE_REP command: needs 5-6 " + "arguments\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv); +} + + +static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[CMD_BUF_LEN]; + int res; + + if (argc != 2 && argc != 3) { + wpa_printf(MSG_INFO, "Invalid P2P_SERVICE_DEL command: needs two or three " + "arguments\n"); + return -1; + } + + if (argc == 3) + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERVICE_DEL %s %s %s", + argv[0], argv[1], argv[2]); + else + res = os_snprintf(cmd, sizeof(cmd), + "P2P_SERVICE_DEL %s %s", + argv[0], argv[1]); + if (os_snprintf_error(sizeof(cmd), res)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl, + int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv); +} + + +static char ** wpa_cli_complete_p2p_peer(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&p2p_peers); + break; + } + + return res; +} + + +static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, const char *cmd, + char *addr, size_t addr_len, + int discovered) +{ + char buf[CMD_BUF_LEN], *pos; + size_t len; + int ret; + + if (ctrl_conn == NULL) + return -1; + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + wpa_printf(MSG_INFO, "'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + wpa_printf(MSG_INFO, "'%s' command failed.\n", cmd); + return -1; + } + + buf[len] = '\0'; + if (os_memcmp(buf, "FAIL", 4) == 0) + return -1; + + pos = buf; + while (*pos != '\0' && *pos != '\n') + pos++; + *pos++ = '\0'; + os_strlcpy(addr, buf, addr_len); + if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL) + wpa_printf(MSG_INFO, "%s\n", addr); + return 0; +} + + +static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char addr[32], cmd[64]; + int discovered; + + discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0; + + if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST", + addr, sizeof(addr), discovered)) + return -1; + do { + os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr); + } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr), + discovered) == 0); + + return 0; +} + + +static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv); +} + + +static char ** wpa_cli_complete_p2p_set(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + const char *fields[] = { + "discoverability", + "managed", + "listen_channel", + "ssid_postfix", + "noa", + "ps", + "oppps", + "ctwindow", + "disabled", + "conc_pref", + "force_long_sd", + "peer_filter", + "cross_connect", + "go_apsd", + "client_apsd", + "disallow_freq", + "disc_int", + "per_sta_psk", + }; + int i, num_fields = ARRAY_SIZE(fields); + + if (arg == 1) { + char **res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(fields[i]); + if (res[i] == NULL) + return res; + } + return res; + } + + if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0) + return cli_txt_list_array(&p2p_peers); + + return NULL; +} + + +static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_FLUSH"); +} + + +static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "P2P_CANCEL"); +} + + +static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc != 0 && argc != 2 && argc != 4) { + wpa_printf(MSG_INFO, "Invalid P2P_PRESENCE_REQ command: needs two arguments " + "(preferred duration, interval; in microsecods).\n" + "Optional second pair can be used to provide " + "acceptable values.\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv); +} + + +static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc != 0 && argc != 2) { + wpa_printf(MSG_INFO, "Invalid P2P_EXT_LISTEN command: needs two arguments " + "(availability period, availability interval; in " + "millisecods).\n" + "Extended Listen Timing can be cancelled with this " + "command when used without parameters.\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv); +} + + +static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv); +} + +#endif /* CONFIG_P2P */ + + +static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv); +} + + +static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv); +} + + +static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv); +} + + +#ifdef CONFIG_WIFI_DISPLAY + +static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[100]; + int res; + + if (argc != 1 && argc != 2) { + wpa_printf(MSG_INFO, "Invalid WFD_SUBELEM_SET command: needs one or two " + "arguments (subelem, hexdump)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s", + argv[0], argc > 1 ? argv[1] : ""); + if (os_snprintf_error(sizeof(cmd), res)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[100]; + int res; + + if (argc != 1) { + wpa_printf(MSG_INFO, "Invalid WFD_SUBELEM_GET command: needs one " + "argument (subelem)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s", + argv[0]); + if (os_snprintf_error(sizeof(cmd), res)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} +#endif /* CONFIG_WIFI_DISPLAY */ + + +#ifdef CONFIG_INTERWORKING +static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "FETCH_ANQP"); +} + + +static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP"); +} + + +static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv); +} + + +static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv); +} + + +static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv); +} + + +static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv); +} + + +static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv); +} +#endif /* CONFIG_INTERWORKING */ + + +#ifdef CONFIG_HS20 + +static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv); +} + + +static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[512]; + + if (argc == 0) { + wpa_printf(MSG_INFO, "Command needs one or two arguments (dst mac addr and " + "optional home realm)\n"); + return -1; + } + + if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST", + argc, argv) < 0) + return -1; + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[512]; + + if (argc < 2) { + wpa_printf(MSG_INFO, "Command needs two arguments (dst mac addr and " + "icon name)\n"); + return -1; + } + + if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0) + return -1; + + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "FETCH_OSU"); +} + + +static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU"); +} + +#endif /* CONFIG_HS20 */ + + +static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv); +} + + +static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv); +} + + +static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv); +} + + +static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv); +} + + +static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv); +} + + +static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv); +} + + +static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv); +} + + +static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "WMM_AC_STATUS"); +} + + +static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv); +} + + +static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv); +} + + +static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "SIGNAL_POLL"); +} + + +static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv); +} + + +static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PKTCNT_POLL"); +} + + +static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "REAUTHENTICATE"); +} + + +#ifdef CONFIG_AUTOSCAN + +static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc == 0) + return wpa_ctrl_command(ctrl, "AUTOSCAN "); + + return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv); +} + +#endif /* CONFIG_AUTOSCAN */ + + +#ifdef CONFIG_WNM + +static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv); +} + + +static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv); +} + +#endif /* CONFIG_WNM */ + + +static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + if (argc == 0) + return -1; + return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]); +} + +static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv); +} + + +static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "FLUSH"); +} + + +static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv); +} + + +static int wpa_cli_cmd_twt_setup(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TWT_SETUP", 0, argc, argv); +} + + +static int wpa_cli_cmd_twt_teardown(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "TWT_TEARDOWN", 0, argc, argv); +} + + +static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "ERP_FLUSH"); +} + + +static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv); +} + + +static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv); +} + + +static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv); +} + + +static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv); +} + + +#ifdef CONFIG_DPP + +static int wpa_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN"); +} + + +static int wpa_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv); +} + + +static int wpa_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); +} + + +#ifdef CONFIG_DPP2 + +static int wpa_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); +} + + +static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); +} + +#endif /* CONFIG_DPP2 */ +#endif /* CONFIG_DPP */ + + +static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) +{ + char buf[512], *pos, *bssid = NULL, *freq = NULL, *level = NULL, + *flags = NULL, *ssid = NULL; + size_t len; + int ret, id = -1; + + if (!ctrl_conn) + return -1; + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + wpa_printf(MSG_INFO, "'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + wpa_printf(MSG_INFO, "'%s' command failed.\n", cmd); + return -1; + } + + buf[len] = '\0'; + if (os_memcmp(buf, "FAIL", 4) == 0) + return -1; + + pos = buf; + while (*pos != '\0') { + if (str_starts(pos, "id=")) + id = atoi(pos + 3); + if (str_starts(pos, "bssid=")) + bssid = pos + 6; + if (str_starts(pos, "freq=")) + freq = pos + 5; + if (str_starts(pos, "level=")) + level = pos + 6; + if (str_starts(pos, "flags=")) + flags = pos + 6; + if (str_starts(pos, "ssid=")) + ssid = pos + 5; + + while (*pos != '\0' && *pos != '\n') + pos++; + *pos++ = '\0'; + } + if (id != -1) + wpa_printf(MSG_INFO, "%s\t%s\t%s\t%s\t%s\n", bssid ? bssid : "N/A", + freq ? freq : "N/A", level ? level : "N/A", + flags ? flags : "N/A", ssid ? ssid : "N/A"); + return id; +} + + +static int wpa_cli_cmd_all_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[64]; + int id = -1; + unsigned int mask; + + wpa_printf(MSG_INFO, "bssid / frequency / signal level / flags / ssid\n"); + + mask = WPA_BSS_MASK_ID | WPA_BSS_MASK_BSSID | WPA_BSS_MASK_FREQ | + WPA_BSS_MASK_LEVEL | WPA_BSS_MASK_FLAGS | WPA_BSS_MASK_SSID; + do { + if (id < 0) + os_snprintf(cmd, sizeof(cmd), "BSS FIRST MASK=0x%x", + mask); + else + os_snprintf(cmd, sizeof(cmd), "BSS NEXT-%d MASK=0x%x", + id, mask); + id = wpa_ctrl_command_bss(ctrl, cmd); + } while (id >= 0); + + return 0; +} + + +#ifdef CONFIG_PASN + +static int wpa_cli_cmd_pasn_auth_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PASN_AUTH_START", 4, argc, argv); +} + + +static int wpa_cli_cmd_pasn_auth_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PASN_AUTH_STOP", 0, argc, argv); +} + +static int wpa_cli_cmd_ptksa_cache_list(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv); +} + + +static int wpa_cli_cmd_pasn_deauth(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PASN_DEAUTH", 1, argc, argv); +} + +#endif /* CONFIG_PASN */ + + +static int wpa_cli_cmd_mscs(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MSCS", 1, argc, argv); +} + + +static int wpa_cli_cmd_scs(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "SCS", 2, argc, argv); +} + + +static int wpa_cli_cmd_dscp_resp(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DSCP_RESP", 1, argc, argv); +} + + +static int wpa_cli_cmd_dscp_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DSCP_QUERY", 1, argc, argv); +} + + +enum wpa_cli_cmd_flags { + cli_cmd_flag_none = 0x00, + cli_cmd_flag_sensitive = 0x01 +}; + +struct wpa_cli_cmd { + const char *cmd; + int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); + char ** (*completion)(const char *str, int pos); + enum wpa_cli_cmd_flags flags; + const char *usage; +}; + +static const struct wpa_cli_cmd wpa_cli_commands[] = { + { "status", wpa_cli_cmd_status, NULL, + cli_cmd_flag_none, + "[verbose] = get current WPA/EAPOL/EAP status" }, + { "ifname", wpa_cli_cmd_ifname, NULL, + cli_cmd_flag_none, + "= get current interface name" }, + { "ping", wpa_cli_cmd_ping, NULL, + cli_cmd_flag_none, + "= pings wpa_supplicant" }, + { "relog", wpa_cli_cmd_relog, NULL, + cli_cmd_flag_none, + "= re-open log-file (allow rolling logs)" }, + { "note", wpa_cli_cmd_note, NULL, + cli_cmd_flag_none, + " = add a note to wpa_supplicant debug log" }, + { "mib", wpa_cli_cmd_mib, NULL, + cli_cmd_flag_none, + "= get MIB variables (dot1x, dot11)" }, + { "set", wpa_cli_cmd_set, wpa_cli_complete_set, + cli_cmd_flag_none, + "= set variables (shows list of variables when run without " + "arguments)" }, + { "dump", wpa_cli_cmd_dump, NULL, + cli_cmd_flag_none, + "= dump config variables" }, + { "get", wpa_cli_cmd_get, wpa_cli_complete_get, + cli_cmd_flag_none, + " = get information" }, + { "driver_flags", wpa_cli_cmd_driver_flags, NULL, + cli_cmd_flag_none, + "= list driver flags" }, + { "logon", wpa_cli_cmd_logon, NULL, + cli_cmd_flag_none, + "= IEEE 802.1X EAPOL state machine logon" }, + { "logoff", wpa_cli_cmd_logoff, NULL, + cli_cmd_flag_none, + "= IEEE 802.1X EAPOL state machine logoff" }, + { "pmksa", wpa_cli_cmd_pmksa, NULL, + cli_cmd_flag_none, + "= show PMKSA cache" }, + { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL, + cli_cmd_flag_none, + "= flush PMKSA cache entries" }, +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + { "pmksa_get", wpa_cli_cmd_pmksa_get, NULL, + cli_cmd_flag_none, + " = fetch all stored PMKSA cache entries" }, + { "pmksa_add", wpa_cli_cmd_pmksa_add, NULL, + cli_cmd_flag_sensitive, + " = store PMKSA cache entry from external storage" }, +#ifdef CONFIG_MESH + { "mesh_pmksa_get", wpa_cli_mesh_cmd_pmksa_get, NULL, + cli_cmd_flag_none, + " = fetch all stored mesh PMKSA cache entries" }, + { "mesh_pmksa_add", wpa_cli_mesh_cmd_pmksa_add, NULL, + cli_cmd_flag_sensitive, + " = store mesh PMKSA cache entry from external storage" }, +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + { "reassociate", wpa_cli_cmd_reassociate, NULL, + cli_cmd_flag_none, + "= force reassociation" }, + { "reattach", wpa_cli_cmd_reattach, NULL, + cli_cmd_flag_none, + "= force reassociation back to the same BSS" }, + { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss, + cli_cmd_flag_none, + " = force preauthentication" }, + { "identity", wpa_cli_cmd_identity, wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = configure identity for an SSID" }, + { "password", wpa_cli_cmd_password, wpa_cli_complete_network_id, + cli_cmd_flag_sensitive, + " = configure password for an SSID" }, + { "new_password", wpa_cli_cmd_new_password, + wpa_cli_complete_network_id, cli_cmd_flag_sensitive, + " = change password for an SSID" }, + { "pin", wpa_cli_cmd_pin, wpa_cli_complete_network_id, + cli_cmd_flag_sensitive, + " = configure pin for an SSID" }, + { "otp", wpa_cli_cmd_otp, wpa_cli_complete_network_id, + cli_cmd_flag_sensitive, + " = configure one-time-password for an SSID" + }, + { "psk_passphrase", wpa_cli_cmd_psk_passphrase, + wpa_cli_complete_network_id, cli_cmd_flag_sensitive, + " = configure PSK/passphrase for an SSID" }, + { "passphrase", wpa_cli_cmd_passphrase, wpa_cli_complete_network_id, + cli_cmd_flag_sensitive, + " = configure private key passphrase\n" + " for an SSID" }, + { "sim", wpa_cli_cmd_sim, wpa_cli_complete_network_id, + cli_cmd_flag_sensitive, + " = report SIM operation result" }, + { "bssid", wpa_cli_cmd_bssid, wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = set preferred BSSID for an SSID" }, + { "bssid_ignore", wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss, + cli_cmd_flag_none, + " = add a BSSID to the list of temporarily ignored BSSs\n" + "bssid_ignore clear = clear the list of temporarily ignored BSSIDs\n" + "bssid_ignore = display the list of temporarily ignored BSSIDs" }, + { "blacklist", /* deprecated alias for bssid_ignore */ + wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss, + cli_cmd_flag_none, + "= deprecated alias for bssid_ignore" }, + { "log_level", wpa_cli_cmd_log_level, NULL, + cli_cmd_flag_none, + " [] = update the log level/timestamp\n" + "log_level = display the current log level and log options" }, + { "list_networks", wpa_cli_cmd_list_networks, NULL, + cli_cmd_flag_none, + "= list configured networks" }, + { "select_network", wpa_cli_cmd_select_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = select a network (disable others)" }, + { "enable_network", wpa_cli_cmd_enable_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = enable a network" }, + { "disable_network", wpa_cli_cmd_disable_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = disable a network" }, + { "add_network", wpa_cli_cmd_add_network, NULL, + cli_cmd_flag_none, + "= add a network" }, + { "remove_network", wpa_cli_cmd_remove_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = remove a network" }, + { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network, + cli_cmd_flag_sensitive, + " = set network variables (shows\n" + " list of variables when run without arguments)" }, + { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network, + cli_cmd_flag_none, + " = get network variables" }, + { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network, + cli_cmd_flag_none, + " = duplicate network variables" + }, + { "list_creds", wpa_cli_cmd_list_creds, NULL, + cli_cmd_flag_none, + "= list configured credentials" }, + { "add_cred", wpa_cli_cmd_add_cred, NULL, + cli_cmd_flag_none, + "= add a credential" }, + { "remove_cred", wpa_cli_cmd_remove_cred, NULL, + cli_cmd_flag_none, + " = remove a credential" }, + { "set_cred", wpa_cli_cmd_set_cred, wpa_cli_complete_cred, + cli_cmd_flag_sensitive, + " = set credential variables" }, + { "get_cred", wpa_cli_cmd_get_cred, wpa_cli_complete_cred, + cli_cmd_flag_none, + " = get credential variables" }, + { "save_config", wpa_cli_cmd_save_config, NULL, + cli_cmd_flag_none, + "= save the current configuration" }, + { "disconnect", wpa_cli_cmd_disconnect, NULL, + cli_cmd_flag_none, + "= disconnect and wait for reassociate/reconnect command before\n" + " connecting" }, + { "reconnect", wpa_cli_cmd_reconnect, NULL, + cli_cmd_flag_none, + "= like reassociate, but only takes effect if already disconnected" + }, + { "scan", wpa_cli_cmd_scan, NULL, + cli_cmd_flag_none, + "= request new BSS scan" }, + { "scan_results", wpa_cli_cmd_scan_results, NULL, + cli_cmd_flag_none, + "= get latest scan results" }, + { "abort_scan", wpa_cli_cmd_abort_scan, NULL, + cli_cmd_flag_none, + "= request ongoing scan to be aborted" }, + { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss, + cli_cmd_flag_none, + "< | > = get detailed scan result info" }, + { "get_capability", wpa_cli_cmd_get_capability, + wpa_cli_complete_get_capability, cli_cmd_flag_none, + " " + "= get capabilities" }, + { "reconfigure", wpa_cli_cmd_reconfigure, NULL, + cli_cmd_flag_none, + "= force wpa_supplicant to re-read its configuration file" }, + { "terminate", wpa_cli_cmd_terminate, NULL, + cli_cmd_flag_none, + "= terminate wpa_supplicant" }, + { "interface_add", wpa_cli_cmd_interface_add, NULL, + cli_cmd_flag_none, + " \n" + " = adds new interface, all " + "parameters but\n" + " are optional. Supported types are station ('sta') and " + "AP ('ap')" }, + { "interface_remove", wpa_cli_cmd_interface_remove, NULL, + cli_cmd_flag_none, + " = removes the interface" }, + { "interface_list", wpa_cli_cmd_interface_list, NULL, + cli_cmd_flag_none, + "= list available interfaces" }, + { "ap_scan", wpa_cli_cmd_ap_scan, NULL, + cli_cmd_flag_none, + " = set ap_scan parameter" }, + { "scan_interval", wpa_cli_cmd_scan_interval, NULL, + cli_cmd_flag_none, + " = set scan_interval parameter (in seconds)" }, + { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL, + cli_cmd_flag_none, + " = set BSS expiration age parameter" }, + { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL, + cli_cmd_flag_none, + " = set BSS expiration scan count parameter" }, + { "bss_flush", wpa_cli_cmd_bss_flush, NULL, + cli_cmd_flag_none, + " = set BSS flush age (0 by default)" }, + { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss, + cli_cmd_flag_none, + " = request over-the-DS FT with " }, + { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss, + cli_cmd_flag_none, + "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" }, + { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss, + cli_cmd_flag_sensitive, + " [PIN] = start WPS PIN method (returns PIN, if not " + "hardcoded)" }, + { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL, + cli_cmd_flag_sensitive, + " = verify PIN checksum" }, + { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none, + "Cancels the pending WPS operation" }, +#ifdef CONFIG_WPS_NFC + { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss, + cli_cmd_flag_none, + "[BSSID] = start Wi-Fi Protected Setup: NFC" }, + { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL, + cli_cmd_flag_none, + " = build configuration token" }, + { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL, + cli_cmd_flag_none, + " = create password token" }, + { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL, + cli_cmd_flag_sensitive, + " = report read NFC tag with WPS data" }, + { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL, + cli_cmd_flag_none, + " = create NFC handover request" }, + { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL, + cli_cmd_flag_none, + " = create NFC handover select" }, + { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL, + cli_cmd_flag_none, + " = report completed " + "NFC handover" }, +#endif /* CONFIG_WPS_NFC */ + { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss, + cli_cmd_flag_sensitive, + " = start WPS Registrar to configure an AP" }, + { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL, + cli_cmd_flag_sensitive, + "[params..] = enable/disable AP PIN" }, + { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL, + cli_cmd_flag_none, + "[IP address] = start Wi-Fi Protected Setup External Registrar" }, + { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL, + cli_cmd_flag_none, + "= stop Wi-Fi Protected Setup External Registrar" }, + { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL, + cli_cmd_flag_sensitive, + " = add an Enrollee PIN to External Registrar" }, + { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL, + cli_cmd_flag_none, + " = accept an Enrollee PBC using External Registrar" }, + { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL, + cli_cmd_flag_sensitive, + " = learn AP configuration" }, + { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL, + cli_cmd_flag_none, + " = set AP configuration for enrolling" }, + { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL, + cli_cmd_flag_sensitive, + " = configure AP" }, +#ifdef CONFIG_WPS_NFC + { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL, + cli_cmd_flag_none, + " = build NFC configuration token" }, +#endif /* CONFIG_WPS_NFC */ + { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL, + cli_cmd_flag_none, + " = request RSN authentication with in IBSS" }, +#ifdef CONFIG_AP + { "sta", wpa_cli_cmd_sta, wpa_cli_complete_sta, + cli_cmd_flag_none, + " = get information about an associated station (AP)" }, + { "all_sta", wpa_cli_cmd_all_sta, NULL, + cli_cmd_flag_none, + "= get information about all associated stations (AP)" }, + { "list_sta", wpa_cli_cmd_list_sta, NULL, + cli_cmd_flag_none, + "= list all stations (AP)" }, + { "deauthenticate", wpa_cli_cmd_deauthenticate, + wpa_cli_complete_deauthenticate, cli_cmd_flag_none, + " = deauthenticate a station" }, + { "disassociate", wpa_cli_cmd_disassociate, + wpa_cli_complete_disassociate, cli_cmd_flag_none, + " = disassociate a station" }, + { "chan_switch", wpa_cli_cmd_chanswitch, NULL, + cli_cmd_flag_none, + " [sec_channel_offset=] [center_freq1=]" + " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]" + " = CSA parameters" }, + { "update_beacon", wpa_cli_cmd_update_beacon, NULL, + cli_cmd_flag_none, + "= update Beacon frame contents"}, +#endif /* CONFIG_AP */ + { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none, + "= notification of suspend/hibernate" }, + { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none, + "= notification of resume/thaw" }, +#ifdef CONFIG_TESTING_OPTIONS + { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none, + "= drop SA without deauth/disassoc (test command)" }, +#endif /* CONFIG_TESTING_OPTIONS */ + { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss, + cli_cmd_flag_none, + " = roam to the specified BSS" }, +#ifdef CONFIG_MESH + { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL, + cli_cmd_flag_none, + "[ifname] = Create a new mesh interface" }, + { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL, + cli_cmd_flag_none, + " = join a mesh network (disable others)" }, + { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL, + cli_cmd_flag_none, + " = Remove mesh group interface" }, + { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL, + cli_cmd_flag_none, + " = Remove a mesh peer" }, + { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL, + cli_cmd_flag_none, + " [duration=] = Add a mesh peer" }, + { "mesh_link_probe", wpa_cli_cmd_mesh_link_probe, NULL, + cli_cmd_flag_none, + " [payload=] = Probe a mesh link for a given peer by injecting a frame." }, +#endif /* CONFIG_MESH */ +#ifdef CONFIG_P2P + { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find, + cli_cmd_flag_none, + "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" }, + { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none, + "= stop P2P Devices search" }, + { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL, + cli_cmd_flag_none, + " adv_id= conncap= [info=] = provision with a P2P ASP Device" }, + { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL, + cli_cmd_flag_none, + " adv_id= [role] [info=] = provision with a P2P ASP Device" }, + { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect, + cli_cmd_flag_none, + " <\"pbc\"|PIN> [ht40] = connect to a P2P Device" }, + { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none, + "[timeout] = listen for P2P Devices for up-to timeout seconds" }, + { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, + wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none, + " = remove P2P group interface (terminate group if GO)" }, + { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none, + "[ht40] = add a new P2P group (local end as GO)" }, + { "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL, + cli_cmd_flag_none, + " = Get peer interface address on local GO using peer Device Address" }, + { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, + wpa_cli_complete_p2p_peer, cli_cmd_flag_none, + " = request provisioning discovery" }, + { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL, + cli_cmd_flag_none, + "= get the passphrase for a group (GO only)" }, + { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req, + wpa_cli_complete_p2p_peer, cli_cmd_flag_none, + " = schedule service discovery request" }, + { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req, + NULL, cli_cmd_flag_none, + " = cancel pending service discovery request" }, + { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL, + cli_cmd_flag_none, + " = service discovery response" }, + { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL, + cli_cmd_flag_none, + "= indicate change in local services" }, + { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL, + cli_cmd_flag_none, + " = set external processing of service discovery" }, + { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL, + cli_cmd_flag_none, + "= remove all stored service entries" }, + { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL, + cli_cmd_flag_none, + " = add a local " + "service" }, + { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL, + cli_cmd_flag_none, + "asp [] = replace " + "local ASP service" }, + { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL, + cli_cmd_flag_none, + " [|service] = remove a local " + "service" }, + { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer, + cli_cmd_flag_none, + " = reject connection attempts from a specific peer" }, + { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL, + cli_cmd_flag_none, + " [peer=addr] = invite peer" }, + { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none, + "[discovered] = list known (optionally, only fully discovered) P2P " + "peers" }, + { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer, + cli_cmd_flag_none, + "
= show information about known P2P peer" }, + { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set, + cli_cmd_flag_none, + " = set a P2P parameter" }, + { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none, + "= flush P2P state" }, + { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none, + "= cancel P2P group formation" }, + { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, + wpa_cli_complete_p2p_peer, cli_cmd_flag_none, + "
= unauthorize a peer" }, + { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL, + cli_cmd_flag_none, + "[ ] [ ] = request GO " + "presence" }, + { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL, + cli_cmd_flag_none, + "[ ] = set extended listen timing" }, + { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client, + wpa_cli_complete_p2p_peer, cli_cmd_flag_none, + " = remove a peer from all groups" }, +#endif /* CONFIG_P2P */ + { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL, + cli_cmd_flag_none, + " = add vendor specific IEs to frame(s)\n" + VENDOR_ELEM_FRAME_ID }, + { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL, + cli_cmd_flag_none, + " = get vendor specific IE(s) to frame(s)\n" + VENDOR_ELEM_FRAME_ID }, + { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL, + cli_cmd_flag_none, + " = remove vendor specific IE(s) in frame(s)\n" + VENDOR_ELEM_FRAME_ID }, +#ifdef CONFIG_WIFI_DISPLAY + { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL, + cli_cmd_flag_none, + " [contents] = set Wi-Fi Display subelement" }, + { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL, + cli_cmd_flag_none, + " = get Wi-Fi Display subelement" }, +#endif /* CONFIG_WIFI_DISPLAY */ +#ifdef CONFIG_INTERWORKING + { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none, + "= fetch ANQP information for all APs" }, + { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL, + cli_cmd_flag_none, + "= stop fetch_anqp operation" }, + { "interworking_select", wpa_cli_cmd_interworking_select, NULL, + cli_cmd_flag_none, + "[auto] = perform Interworking network selection" }, + { "interworking_connect", wpa_cli_cmd_interworking_connect, + wpa_cli_complete_bss, cli_cmd_flag_none, + " = connect using Interworking credentials" }, + { "interworking_add_network", wpa_cli_cmd_interworking_add_network, + wpa_cli_complete_bss, cli_cmd_flag_none, + " = connect using Interworking credentials" }, + { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss, + cli_cmd_flag_none, + " [,]... = request ANQP information" }, + { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss, + cli_cmd_flag_none, + " [QueryReq] = GAS request" }, + { "gas_response_get", wpa_cli_cmd_gas_response_get, + wpa_cli_complete_bss, cli_cmd_flag_none, + " [start,len] = Fetch last GAS response" }, +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_HS20 + { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss, + cli_cmd_flag_none, + " [,]... = request HS 2.0 ANQP information" + }, + { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list, + wpa_cli_complete_bss, cli_cmd_flag_none, + " = get HS20 nai home realm list" }, + { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request, + wpa_cli_complete_bss, cli_cmd_flag_none, + " = get Hotspot 2.0 OSU icon" }, + { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none, + "= fetch OSU provider information from all APs" }, + { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL, + cli_cmd_flag_none, + "= cancel fetch_osu command" }, +#endif /* CONFIG_HS20 */ + { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL, + cli_cmd_flag_none, + "<0/1> = disable/enable automatic reconnection" }, + { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL, + cli_cmd_flag_none, + " = request TDLS discovery with " }, + { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL, + cli_cmd_flag_none, + " = request TDLS setup with " }, + { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL, + cli_cmd_flag_none, + " = tear down TDLS with " }, + { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL, + cli_cmd_flag_none, + " = TDLS link status with " }, + { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL, + cli_cmd_flag_none, + " [nominal_msdu_size=#] " + "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] " + "= add WMM-AC traffic stream" }, + { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL, + cli_cmd_flag_none, + " = delete WMM-AC traffic stream" }, + { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL, + cli_cmd_flag_none, + "= show status for Wireless Multi-Media Admission-Control" }, + { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL, + cli_cmd_flag_none, + " [sec_channel_offset=] [center_freq1=] " + "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching " + "with TDLS peer" }, + { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL, + cli_cmd_flag_none, + " = disable channel switching with TDLS peer " }, + { "signal_poll", wpa_cli_cmd_signal_poll, NULL, + cli_cmd_flag_none, + "= get signal parameters" }, + { "signal_monitor", wpa_cli_cmd_signal_monitor, NULL, + cli_cmd_flag_none, + "= set signal monitor parameters" }, + { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL, + cli_cmd_flag_none, + "= get TX/RX packet counters" }, + { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL, + cli_cmd_flag_none, + "= trigger IEEE 802.1X/EAPOL reauthentication" }, +#ifdef CONFIG_AUTOSCAN + { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none, + "[params] = Set or unset (if none) autoscan parameters" }, +#endif /* CONFIG_AUTOSCAN */ +#ifdef CONFIG_WNM + { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none, + " [interval=#] = enter/exit WNM-Sleep mode" }, + { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none, + " [list]" + " [neighbor=,,,,[,]" + " = Send BSS Transition Management Query" }, +#endif /* CONFIG_WNM */ + { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive, + " = Sent unprocessed command" }, + { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none, + "= flush wpa_supplicant state" }, + { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none, + "= radio_work " }, + { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none, + " [] = Send vendor command" + }, + { "neighbor_rep_request", + wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none, + "[ssid=] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)" + }, + { "twt_setup", + wpa_cli_cmd_twt_setup, NULL, cli_cmd_flag_none, + "[dialog=] [exponent=] [mantissa=] [min_twt=] [setup_cmd=] [twt=] [requestor=0|1] [trigger=0|1] [implicit=0|1] [flow_type=0|1] [flow_id=<3-bit-id>] [protection=0|1] [twt_channel=] [control=] = Send TWT Setup frame" + }, + { "twt_teardown", + wpa_cli_cmd_twt_teardown, NULL, cli_cmd_flag_none, + "[flags=] = Send TWT Teardown frame" + }, + { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none, + "= flush ERP keys" }, + { "mac_rand_scan", + wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none, + " enable=<0/1> [addr=mac-address " + "mask=mac-address-mask] = scan MAC randomization" + }, + { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL, + cli_cmd_flag_none, + " = retrieve preferred freq list for the specified interface type" }, + { "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL, + cli_cmd_flag_none, + " = start P2P listen offload" }, + { "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL, + cli_cmd_flag_none, + "= stop P2P listen offload" }, +#ifdef CONFIG_DPP + { "dpp_qr_code", wpa_cli_cmd_dpp_qr_code, NULL, cli_cmd_flag_none, + "report a scanned DPP URI from a QR Code" }, + { "dpp_bootstrap_gen", wpa_cli_cmd_dpp_bootstrap_gen, NULL, + cli_cmd_flag_sensitive, + "type= [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" }, + { "dpp_bootstrap_remove", wpa_cli_cmd_dpp_bootstrap_remove, NULL, + cli_cmd_flag_none, + "*| = remove DPP bootstrap information" }, + { "dpp_bootstrap_get_uri", wpa_cli_cmd_dpp_bootstrap_get_uri, NULL, + cli_cmd_flag_none, + " = get DPP bootstrap URI" }, + { "dpp_bootstrap_info", wpa_cli_cmd_dpp_bootstrap_info, NULL, + cli_cmd_flag_none, + " = show DPP bootstrap information" }, + { "dpp_bootstrap_set", wpa_cli_cmd_dpp_bootstrap_set, NULL, + cli_cmd_flag_none, + " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, + { "dpp_auth_init", wpa_cli_cmd_dpp_auth_init, NULL, cli_cmd_flag_none, + "peer= [own=] = initiate DPP bootstrapping" }, + { "dpp_listen", wpa_cli_cmd_dpp_listen, NULL, cli_cmd_flag_none, + " = start DPP listen" }, + { "dpp_stop_listen", wpa_cli_cmd_dpp_stop_listen, NULL, + cli_cmd_flag_none, + "= stop DPP listen" }, + { "dpp_configurator_add", wpa_cli_cmd_dpp_configurator_add, NULL, + cli_cmd_flag_sensitive, + "[curve=..] [key=..] = add DPP configurator" }, + { "dpp_configurator_remove", wpa_cli_cmd_dpp_configurator_remove, NULL, + cli_cmd_flag_none, + "*| = remove DPP configurator" }, + { "dpp_configurator_get_key", wpa_cli_cmd_dpp_configurator_get_key, + NULL, cli_cmd_flag_none, + " = Get DPP configurator's private key" }, + { "dpp_configurator_sign", wpa_cli_cmd_dpp_configurator_sign, NULL, + cli_cmd_flag_none, + "conf= configurator= = generate self DPP configuration" }, + { "dpp_pkex_add", wpa_cli_cmd_dpp_pkex_add, NULL, + cli_cmd_flag_sensitive, + "add PKEX code" }, + { "dpp_pkex_remove", wpa_cli_cmd_dpp_pkex_remove, NULL, + cli_cmd_flag_none, + "*| = remove DPP pkex information" }, +#ifdef CONFIG_DPP2 + { "dpp_controller_start", wpa_cli_cmd_dpp_controller_start, NULL, + cli_cmd_flag_none, + "[tcp_port=] [role=..] = start DPP controller" }, + { "dpp_controller_stop", wpa_cli_cmd_dpp_controller_stop, NULL, + cli_cmd_flag_none, + "= stop DPP controller" }, + { "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL, + cli_cmd_flag_none, + "own= iter= = start DPP chirp" }, + { "dpp_stop_chirp", wpa_cli_cmd_dpp_stop_chirp, NULL, + cli_cmd_flag_none, + "= stop DPP chirp" }, +#endif /* CONFIG_DPP2 */ +#endif /* CONFIG_DPP */ + { "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none, + "= list all BSS entries (scan results)" }, +#ifdef CONFIG_PASN + { "pasn_auth_start", wpa_cli_cmd_pasn_auth_start, NULL, + cli_cmd_flag_none, + "bssid= akmp= cipher= group= nid= = Start PASN authentication" }, + { "pasn_auth_stop", wpa_cli_cmd_pasn_auth_stop, NULL, + cli_cmd_flag_none, + "= Stop PASN authentication" }, + { "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL, + cli_cmd_flag_none, + "= Get the PTKSA Cache" }, + { "pasn_deauth", wpa_cli_cmd_pasn_deauth, NULL, + cli_cmd_flag_none, + "bssid= = Remove PASN PTKSA state" }, +#endif /* CONFIG_PASN */ + { "mscs", wpa_cli_cmd_mscs, NULL, + cli_cmd_flag_none, + " [up_bitmap=] [up_limit=] [stream_timeout=] [frame_classifier=] = Configure MSCS request" }, + { "scs", wpa_cli_cmd_scs, NULL, + cli_cmd_flag_none, + "[scs_id=] [scs_up=<0-7>] [classifier_type=<4|10>] [classifier params based on classifier type] [tclas_processing=<0|1>] [scs_id=] ... = Send SCS request" }, + { "dscp_resp", wpa_cli_cmd_dscp_resp, NULL, + cli_cmd_flag_none, + "<[reset]>/<[solicited] [policy_id=1 status=0...]> [more] = Send DSCP response" }, + { "dscp_query", wpa_cli_cmd_dscp_query, NULL, + cli_cmd_flag_none, + "wildcard/domain_name= = Send DSCP Query" }, + { NULL, NULL, NULL, cli_cmd_flag_none, NULL } +}; + +int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + const struct wpa_cli_cmd *cmd, *match = NULL; + int count; + int ret = 0; + + if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) { + ifname_prefix = argv[0] + 7; + argv = &argv[1]; + argc--; + } else + ifname_prefix = NULL; + + if (argc == 0) + return -1; + + count = 0; + cmd = wpa_cli_commands; + while (cmd->cmd) { + if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0) + { + match = cmd; + if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { + /* we have an exact match */ + count = 1; + break; + } + count++; + } + cmd++; + } + + if (count > 1) { + wpa_printf(MSG_INFO, "Ambiguous command '%s'; possible commands:", argv[0]); + cmd = wpa_cli_commands; + while (cmd->cmd) { + if (os_strncasecmp(cmd->cmd, argv[0], + os_strlen(argv[0])) == 0) { + wpa_printf(MSG_INFO, " %s", cmd->cmd); + } + cmd++; + } + wpa_printf(MSG_INFO, "\n"); + ret = 1; + } else if (count == 0) { + wpa_printf(MSG_INFO, "Unknown command '%s'\n", argv[0]); + ret = 1; + } else { + ret = match->handler(ctrl, argc, &argv[1]); + } + + return ret; +} \ No newline at end of file diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c new file mode 100644 index 0000000000..6131e18d94 --- /dev/null +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -0,0 +1,340 @@ +/* + * WPA Supplicant - command line interface for wpa_supplicant daemon + * for Zephyr (based on wpa_cli.c) + * Copyright (c) 2004-2022, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "includes.h" + +#include "common/cli.h" +#include "common/wpa_ctrl.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/edit.h" +#include "utils/list.h" +#include "wpa_supplicant_i.h" +#include "ctrl_iface.h" +#include "common/version.h" +#include "common/ieee802_11_defs.h" + +#include "supp_main.h" +#include "wpa_cli_zephyr.h" +#include "ctrl_iface_zephyr.h" + +#define CMD_BUF_LEN 1024 +#define MAX_CMD_SIZE 512 +#define MAX_RESPONSE_SIZE 512 +#define DEFAULT_IFNAME "wlan0" +#define MAX_ARGS 32 + +struct wpa_ctrl *ctrl_conn; +char *ifname_prefix = NULL; + +static void wpa_cli_msg_cb(char *msg, size_t len) +{ + wpa_printf(MSG_INFO, "%s\n", msg); +} + +static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print, char *resp) +{ + char buf[CMD_BUF_LEN] = { 0 }; + size_t len; + int ret; + + if (ctrl_conn == NULL) { + printf("Not connected to wpa_supplicant - command dropped.\n"); + return -1; + } + if (ifname_prefix) { + os_snprintf(buf, sizeof(buf), "IFNAME=%s %s", + ifname_prefix, cmd); + buf[sizeof(buf) - 1] = '\0'; + cmd = buf; + } + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + printf("'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + printf("'%s' command failed.\n", cmd); + return -1; + } + + if (resp) { + /* Remove the LF */ + os_memcpy(resp, buf, len - 1); + } + + if (print) { + buf[len] = '\0'; + printf("%s", buf); + } + return 0; +} + +static int wpa_ctrl_command_resp(struct wpa_ctrl *ctrl, const char *cmd, char *resp) +{ + return _wpa_ctrl_command(ctrl, cmd, 0, resp); +} + +static int wpa_cli_open_connection(struct wpa_supplicant *wpa_s) +{ + ctrl_conn = wpa_ctrl_open(wpa_s->ctrl_iface->sock_pair[0]); + if (ctrl_conn == NULL) { + wpa_printf(MSG_ERROR, "Failed to open control connection to " + "%d - %s", wpa_s->ctrl_iface->sock_pair[0], + strerror(errno)); + return -1; + } + + return 0; +} + +static void wpa_cli_close_connection(void) +{ + if (ctrl_conn == NULL) + return; + + wpa_ctrl_close(ctrl_conn); + ctrl_conn = NULL; +} + +/* Lifted from zephyr shell_utils.c to handle escapes */ +static inline uint16_t supp_strlen(const char *str) +{ + return str == NULL ? 0U : (uint16_t)strlen(str); +} + +static char make_argv(char **ppcmd, uint8_t c) +{ + char *cmd = *ppcmd; + char quote = 0; + + while (1) { + c = *cmd; + + if (c == '\0') { + break; + } + + if (quote == c) { + memmove(cmd, cmd + 1, supp_strlen(cmd)); + quote = 0; + continue; + } + + if (quote && c == '\\') { + char t = *(cmd + 1); + + if (t == quote) { + memmove(cmd, cmd + 1, + supp_strlen(cmd)); + cmd += 1; + continue; + } + + if (t == '0') { + uint8_t i; + uint8_t v = 0U; + + for (i = 2U; i < (2 + 3); i++) { + t = *(cmd + i); + + if (t >= '0' && t <= '7') { + v = (v << 3) | (t - '0'); + } else { + break; + } + } + + if (i > 2) { + memmove(cmd, cmd + (i - 1), + supp_strlen(cmd) - (i - 2)); + *cmd++ = v; + continue; + } + } + + if (t == 'x') { + uint8_t i; + uint8_t v = 0U; + + for (i = 2U; i < (2 + 2); i++) { + t = *(cmd + i); + + if (t >= '0' && t <= '9') { + v = (v << 4) | (t - '0'); + } else if ((t >= 'a') && + (t <= 'f')) { + v = (v << 4) | (t - 'a' + 10); + } else if ((t >= 'A') && (t <= 'F')) { + v = (v << 4) | (t - 'A' + 10); + } else { + break; + } + } + + if (i > 2) { + memmove(cmd, cmd + (i - 1), + supp_strlen(cmd) - (i - 2)); + *cmd++ = v; + continue; + } + } + } + + if (!quote && isspace((int) c)) { + break; + } + + cmd += 1; + } + *ppcmd = cmd; + + return quote; +} + + +char supp_make_argv(size_t *argc, const char **argv, char *cmd, + uint8_t max_argc) +{ + char quote = 0; + char c; + + *argc = 0; + do { + c = *cmd; + if (c == '\0') { + break; + } + + if (isspace((int) c)) { + *cmd++ = '\0'; + continue; + } + + argv[(*argc)++] = cmd; + if (*argc == max_argc) { + break; + } + quote = make_argv(&cmd, c); + } while (true); + + return quote; +} + +int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) +{ + return _wpa_ctrl_command(ctrl, cmd, 1, NULL); +} + +/* Public APIs */ + +int z_wpa_ctrl_init(void *wpa_s) +{ + int ret; + struct wpa_supplicant *supp = wpa_s; + + ret = wpa_cli_open_connection(supp); + if (ret < 0) { + wpa_printf(MSG_INFO, "Failed to initialize control interface: %s: %d", supp->ifname, ret); + return ret; + } + + return ret; +} + +void z_wpa_ctrl_deinit(void) +{ + wpa_cli_close_connection(); +} + +int z_wpa_ctrl_zephyr_cmd(int argc, const char *argv[]) +{ + return wpa_request(ctrl_conn, argc , (char **) argv); +} + +int z_wpa_cli_cmd_v(const char *fmt, ...) +{ + va_list cmd_args; + int argc; + const char *argv[MAX_ARGS]; + char cmd[MAX_CMD_SIZE]; + + va_start(cmd_args, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, cmd_args); + va_end(cmd_args); + + (void)supp_make_argv(&argc, &argv[0], cmd, MAX_ARGS); + + wpa_printf(MSG_DEBUG, "Calling wpa_cli: %s, argc: %d\n", cmd, argc); + for (int i = 0; i < argc; i++) + wpa_printf(MSG_DEBUG, "argv[%d]: %s\n", i, argv[i]); + + return z_wpa_ctrl_zephyr_cmd(argc, argv); +} + +int z_wpa_ctrl_add_network(struct add_network_resp *resp) +{ + int ret; + char buf[MAX_RESPONSE_SIZE] = {0}; + + ret = wpa_ctrl_command_resp(ctrl_conn, "ADD_NETWORK", buf); + if (ret) { + return ret; + } + + ret = sscanf((const char *)buf, "%d", &resp->network_id); + if (ret < 0) { + wpa_printf(MSG_INFO, "Failed to parse ADD_NETWORK response: %s", + strerror(errno)); + return -1; + } + + return 0; +} + +int z_wpa_ctrl_signal_poll(struct signal_poll_resp *resp) +{ + int ret; + char buf[MAX_RESPONSE_SIZE] = {0}; + + ret = wpa_ctrl_command_resp(ctrl_conn, "SIGNAL_POLL", buf); + if (ret) { + return ret; + } + + ret = sscanf((const char *)buf, "RSSI=%d", &resp->rssi); + if (ret < 0) { + wpa_printf(MSG_INFO, "Failed to parse SIGNAL_POLL response: %s", + strerror(errno)); + return -1; + } + + return 0; +} + +int z_wpa_ctrl_status(struct status_resp *resp) +{ + int ret; + char buf[MAX_RESPONSE_SIZE] = {0}; + + ret = wpa_ctrl_command_resp(ctrl_conn, "STATUS", buf); + if (ret) { + return ret; + } + + ret = sscanf((const char *)buf, "bssid=%%*\nfreq=%%*\nssid=%s", resp->ssid); + if (ret < 0) { + wpa_printf(MSG_INFO, "Failed to parse STATUS response: %s", + strerror(errno)); + return -1; + } + resp->ssid_len = strlen(resp->ssid); + + return 0; +} diff --git a/wpa_supplicant/wpa_cli_zephyr.h b/wpa_supplicant/wpa_cli_zephyr.h new file mode 100644 index 0000000000..b16e772d8e --- /dev/null +++ b/wpa_supplicant/wpa_cli_zephyr.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef __WPA_CLI_ZEPHYR_H_ +#define __WPA_CLI_ZEPHYR_H_ + +#include + +#define SSID_MAX_LEN 32 + +/* Public data structures - no serialization done, so, non-nested only */ +struct add_network_resp { + int network_id; +}; + +struct signal_poll_resp { + int rssi; +}; + +struct status_resp { + char ssid_len; + char ssid[SSID_MAX_LEN + 1]; +}; + +/* Public APIs */ +int z_wpa_ctrl_init(void *wpa_s); +void z_wpa_ctrl_deinit(void); +int z_wpa_ctrl_zephyr_cmd(int argc, const char *argv[]); +int z_wpa_cli_cmd_v(const char *fmt, ...); + +int z_wpa_ctrl_add_network(struct add_network_resp *resp); +int z_wpa_ctrl_signal_poll(struct signal_poll_resp *resp); +int z_wpa_ctrl_status(struct status_resp *resp); + +#endif /* __WPA_CLI_ZEPHYR_H_ */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 46f73c987f..72c0b5918c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6836,7 +6836,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); -#ifndef CONFIG_ZEPHYR wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); if (wpa_s->ctrl_iface == NULL) { wpa_printf(MSG_ERROR, @@ -6850,7 +6849,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->conf->ctrl_interface); return -1; } -#endif wpa_s->gas = gas_query_init(wpa_s); if (wpa_s->gas == NULL) { diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index c95c16fec0..80b7e47832 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -35,7 +35,7 @@ zephyr_library_compile_definitions( CONFIG_WPA_S_ZEPHYR_L2_WIFI_MGMT #CONFIG_NO_STDOUT_DEBUG CONFIG_CTRL_IFACE - CONFIG_CTRL_IFACE_UDP + CONFIG_CTRL_IFACE_ZEPHYR CONFIG_NO_RANDOM_POOL CONFIG_MBO CONFIG_WNM @@ -69,7 +69,7 @@ zephyr_library_sources( ${COMMON_SRC_BASE}/utils/eloop.c ${COMMON_SRC_BASE}/utils/os_zephyr.c ${COMMON_SRC_BASE}/utils/radiotap.c - #${COMMON_SRC_BASE}/utils/edit_simple.c + ${COMMON_SRC_BASE}/utils/edit_simple.c ${WPA_SUPPLICANT_BASE}/config.c ${WPA_SUPPLICANT_BASE}/notify.c ${WPA_SUPPLICANT_BASE}/bss.c @@ -86,10 +86,11 @@ zephyr_library_sources( ${WPA_SUPPLICANT_BASE}/scan.c ${WPA_SUPPLICANT_BASE}/robust_av.c ${WPA_SUPPLICANT_BASE}/ctrl_iface.c - ${WPA_SUPPLICANT_BASE}/ctrl_iface_udp.c - ${WPA_SUPPLICANT_BASE}/wpa_cli.c ${WPA_SUPPLICANT_BASE}/mbo.c ${WPA_SUPPLICANT_BASE}/wnm_sta.c + ${WPA_SUPPLICANT_BASE}/wpa_cli_cmds.c + ${WPA_SUPPLICANT_BASE}/ctrl_iface_zephyr.c + ${WPA_SUPPLICANT_BASE}/wpa_cli_zephyr.c # Zephyr main src/supp_main.c src/utils/wpa_debug.c From 044ed05fe11cc2e59e1e915dc6fadcdde6bf0820 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 23 Jan 2023 00:42:16 +0530 Subject: [PATCH 084/150] Make WPA CLI as passthrough Instead of exposing limited commands using wrappers add a generic pass through WPA CLI that can take any command supported by WPA CLI. Only downside is we lose the help for each command in shell, but as this is only for internal use (WFA certification) this is not a constraint. Signed-off-by: Krishna T --- zephyr/Kconfig | 3 + zephyr/src/wpa_cli.c | 138 +++++-------------------------------------- 2 files changed, 17 insertions(+), 124 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 7499a2dc55..8ca908ceb5 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -72,6 +72,9 @@ config WPA_CLI bool "CLI support for wpa_supplicant" default n +config NET_SOCKETPAIR_BUFFER_SIZE + default 4096 if WPA_CLI + module = WPA_SUPP module-str = WPA supplicant source "subsys/logging/Kconfig.template.log_config" diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index 997aa04966..daafba1735 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -5,156 +5,46 @@ */ /* @file - * @brief Wi-Fi shell sample + * @brief wpa_cli implementation for Zephyr OS */ -#include -#include -#include - #include #include #include -#include -#include -#include - -#include -#include -#include - -static struct { - const struct shell *shell; - - union { - struct { - uint8_t connecting : 1; - uint8_t disconnecting : 1; - uint8_t _unused : 6; - }; - uint8_t all; - }; -} context; - - -int cli_main(int argc, const char **argv); +#include "wpa_cli_zephyr.h" -extern struct wpa_global *global; - -/* TODO: Take this an input from shell */ -const char if_name[] = "wlan0"; - - -static int cmd_supplicant(const struct shell *shell, +static int cmd_wpa_cli(const struct shell *sh, size_t argc, const char *argv[]) { - struct wpa_supplicant *wpa_s = wpa_supplicant_get_iface(global, if_name); + ARG_UNUSED(sh); - if (!wpa_s) { - shell_fprintf(shell, - SHELL_ERROR, - "%s: wpa_supplicant is not initialized, dropping connect\n", - __func__); - return -1; + if (argc == 1) { + shell_error(sh, "Missing argument"); + return -EINVAL; } - return cli_main(argc, - argv); + /* Remove wpa_cli from the argument list */ + return z_wpa_ctrl_zephyr_cmd(argc - 1, &argv[1]); } -SHELL_STATIC_SUBCMD_SET_CREATE( - wpa_cli_cmds, - SHELL_CMD(add_network, - NULL, - "\"Add Network network id/number\"", - cmd_supplicant), - SHELL_CMD(set_network, - NULL, - "\"Set Network params\"", - cmd_supplicant), - SHELL_CMD(set, - NULL, - "\"Set Global params\"", - cmd_supplicant), - SHELL_CMD(get, - NULL, "\"Get Global params\"", - cmd_supplicant), - SHELL_CMD(enable_network, - NULL, - "\"Enable Network\"", - cmd_supplicant), - SHELL_CMD(remove_network, - NULL, - "\"Remove Network\"", - cmd_supplicant), - SHELL_CMD(get_network, - NULL, - "\"Get Network\"", - cmd_supplicant), - SHELL_CMD(select_network, - NULL, - "\"Select Network which will be enabled; rest of the networks will be disabled\"", - cmd_supplicant), - SHELL_CMD(disable_network, - NULL, - "\"\"", - cmd_supplicant), - SHELL_CMD(disconnect, - NULL, - "\"\"", - cmd_supplicant), - SHELL_CMD(reassociate, - NULL, - "\"\"", - cmd_supplicant), - SHELL_CMD(status, - NULL, - "\"Get client status\"", - cmd_supplicant), - SHELL_CMD(bssid, - NULL, - "\"Associate with this BSSID\"", - cmd_supplicant), - SHELL_CMD(sta_autoconnect, - NULL, - "\"\"", - cmd_supplicant), - SHELL_CMD(signal_poll, - NULL, - "\"\"", - cmd_supplicant), - SHELL_CMD(wnm_bss_query, - NULL, - "\"\"", - cmd_supplicant), - SHELL_CMD(list_networks, - NULL, - "\"\"", - cmd_supplicant), - SHELL_SUBCMD_SET_END); - /* Persisting with "wpa_cli" naming for compatibility with Wi-Fi * certification applications and scripts. */ SHELL_CMD_REGISTER(wpa_cli, - &wpa_cli_cmds, - "wpa_supplicant commands (only for internal use)", - NULL); + NULL, + "wpa_cli commands (only for internal use)", + cmd_wpa_cli); -static int wifi_shell_init(const struct device *unused) +static int wpa_cli_init(const struct device *unused) { ARG_UNUSED(unused); - context.shell = NULL; - context.all = 0U; - return 0; } - -SYS_INIT(wifi_shell_init, +SYS_INIT(wpa_cli_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From 0ab6939fa0866a46ec6028e83f88d8b9b5cceca5 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 23 Jan 2023 00:44:48 +0530 Subject: [PATCH 085/150] Use WPA CLI to interact with supplicant Directly calling WPA supplicant APIs is error prone as it introduces concurrency, so, use WPA CLI interface to serialize them using control interface and Eloop. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 164 +++++++++++------------------------------ zephyr/src/supp_main.c | 30 +++++++- zephyr/src/supp_main.h | 3 + 3 files changed, 75 insertions(+), 122 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index f9b3cfbf55..e0fb3353e1 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#include #include #include @@ -16,6 +17,7 @@ #include "supp_main.h" #include "supp_api.h" +#include "wpa_cli_zephyr.h" int cli_main(int, const char **); extern struct k_sem wpa_supplicant_ready_sem; @@ -56,36 +58,9 @@ static void supp_shell_connect_status(struct k_work *work); static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work, supp_shell_connect_status); -static int send_wpa_supplicant_dummy_event(void) -{ - struct wpa_supplicant_event_msg msg = { 0 }; - - msg.ignore_msg = true; - - return send_wpa_supplicant_event(&msg); -} - - static inline struct wpa_supplicant * get_wpa_s_handle(const struct device *dev) { - struct wpa_supplicant *wpa_s = NULL; - int ret = k_sem_take(&wpa_supplicant_ready_sem, K_SECONDS(2)); - - if (ret) { - wpa_printf(MSG_ERROR, "%s: WPA supplicant not ready: %d", __func__, ret); - return NULL; - } - - k_sem_give(&wpa_supplicant_ready_sem); - - wpa_s = wpa_supplicant_get_iface(global, dev->name); - if (!wpa_s) { - wpa_printf(MSG_ERROR, - "%s: Unable to get wpa_s handle for %s\n", __func__, dev->name); - return NULL; - } - - return wpa_s; + return get_wpa_s_handle_ifname(dev->name); } static void supp_shell_connect_status(struct k_work *work) @@ -110,7 +85,7 @@ static void supp_shell_connect_status(struct k_work *work) if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) { if (ctrl->connection_timeout > 0 && seconds_counter++ > ctrl->connection_timeout) { - wpas_request_disconnection(wpa_s); + z_wpa_cli_cmd_v("disconnect"); status = CONNECTION_FAILURE; goto out; } @@ -144,10 +119,9 @@ static inline void wpa_supp_restart_status_work(void) int z_wpa_supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params) { - struct wpa_ssid *ssid = NULL; - bool pmf = true; struct wpa_supplicant *wpa_s; int ret = 0; + struct add_network_resp resp = {0}; if (!net_if_is_up(net_if_lookup_by_dev(dev))) { wpa_printf(MSG_ERROR, @@ -163,100 +137,51 @@ int z_wpa_supplicant_connect(const struct device *dev, goto out; } - wpa_supplicant_remove_all_networks(wpa_s); - - ssid = wpa_supplicant_add_network(wpa_s); - ssid->ssid = os_zalloc(sizeof(u8) * MAX_SSID_LEN); - - memcpy(ssid->ssid, params->ssid, params->ssid_length); - ssid->ssid_len = params->ssid_length; - ssid->disabled = 1; - ssid->key_mgmt = WPA_KEY_MGMT_NONE; - - if (params->channel != WIFI_CHANNEL_ANY) { - /* We use global channel list here and also use the widest - * op_class for 5GHz channels as there is no user input - * for these. - */ - int freq = ieee80211_chan_to_freq(NULL, 81, params->channel); - - if (freq <= 0) { - freq = ieee80211_chan_to_freq(NULL, 128, params->channel); - } - - if (freq <= 0) { - wpa_printf(MSG_ERROR, "Invalid channel %d", params->channel); - ret = -EINVAL; - goto out; - } - - ssid->scan_freq = os_zalloc(2 * sizeof(int)); - if (!ssid->scan_freq) { - ret = -ENOMEM; - goto out; - } - ssid->scan_freq[0] = freq; - ssid->scan_freq[1] = 0; - - ssid->freq_list = os_zalloc(2 * sizeof(int)); - if (!ssid->freq_list) { - os_free(ssid->scan_freq); - ret = -ENOMEM; - goto out; - } - ssid->freq_list[0] = freq; - ssid->freq_list[1] = 0; + z_wpa_cli_cmd_v("remove_network all"); + ret = z_wpa_ctrl_add_network(&resp); + if (ret) { + goto out; } - wpa_s->conf->filter_ssids = 1; - wpa_s->conf->ap_scan = 1; + wpa_printf(MSG_DEBUG, "NET added: %d\n", resp.network_id); + z_wpa_cli_cmd_v("set_network %d ssid \"%s\"", resp.network_id, params->ssid); + z_wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id); + z_wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id); if (params->psk) { - // TODO: Extend enum wifi_security_type + /* WPA3 */ if (params->security == 3) { - ssid->key_mgmt = WPA_KEY_MGMT_SAE; - str_clear_free(ssid->sae_password); - ssid->sae_password = dup_binstr(params->psk, params->psk_length); - - if (ssid->sae_password == NULL) { - wpa_printf(MSG_ERROR, "%s:Failed to copy sae_password\n", - __func__); - ret = -ENOMEM; - goto out; + if (params->sae_password) { + z_wpa_cli_cmd_v("set_network %d sae_password \"%s\"", + resp.network_id, params->sae_password); + } else { + z_wpa_cli_cmd_v("set_network %d sae_password \"%s\"", + resp.network_id, params->psk); } + z_wpa_cli_cmd_v("set_network %d key_mgmt SAE", + resp.network_id); + } else if (params->security == 2) { + z_wpa_cli_cmd_v("set_network %d psk \"%s\"", + resp.network_id, params->psk); + z_wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-256", + resp.network_id); } else { - if (params->security == 2) - ssid->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; - else - ssid->key_mgmt = WPA_KEY_MGMT_PSK; - - str_clear_free(ssid->passphrase); - ssid->passphrase = dup_binstr(params->psk, params->psk_length); - - if (ssid->passphrase == NULL) { - wpa_printf(MSG_ERROR, "%s:Failed to copy passphrase\n", - __func__); - ret = -ENOMEM; - goto out; - } + z_wpa_cli_cmd_v( "set_network %d psk \"%s\"", + resp.network_id, params->psk); + z_wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK", + resp.network_id); } - wpa_config_update_psk(ssid); - - if (pmf) { - /* 1-1 Mapping */ - ssid->ieee80211w = params->mfp; + if (params->mfp) { + z_wpa_cli_cmd_v("set_network %d ieee80211w %d", + resp.network_id, params->mfp); } - } - wpa_supplicant_enable_network(wpa_s, - ssid); - - wpa_supplicant_select_network(wpa_s, - ssid); + /* enable and select network */ + z_wpa_cli_cmd_v("enable_network %d", resp.network_id); - send_wpa_supplicant_dummy_event(); + z_wpa_cli_cmd_v("select_network %d", resp.network_id); wpa_supp_api_ctrl.dev = dev; wpa_supp_api_ctrl.requested_op = CONNECT; @@ -286,7 +211,7 @@ int z_wpa_supplicant_disconnect(const struct device *dev) } wpa_supp_api_ctrl.dev = dev; wpa_supp_api_ctrl.requested_op = DISCONNECT; - wpas_request_disconnection(wpa_s); + z_wpa_cli_cmd_v("disconnect"); out: k_mutex_unlock(&wpa_supplicant_mutex); @@ -352,6 +277,7 @@ int z_wpa_supplicant_status(const struct device *dev, if (wpa_s->wpa_state >= WPA_ASSOCIATED) { struct wpa_ssid *ssid = wpa_s->current_ssid; u8 channel; + struct signal_poll_resp signal_poll; os_memcpy(status->bssid, wpa_s->bssid, WIFI_MAC_ADDR_LEN); status->band = wpas_band_to_zephyr(wpas_freq_to_band(wpa_s->assoc_freq)); @@ -363,16 +289,16 @@ int z_wpa_supplicant_status(const struct device *dev, if (ssid) { u8 *_ssid = ssid->ssid; size_t ssid_len = ssid->ssid_len; - u8 ssid_buf[SSID_MAX_LEN] = {0}; + struct status_resp cli_status; if (ssid_len == 0) { - int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); + int _res = z_wpa_ctrl_status(&cli_status); if (_res < 0) ssid_len = 0; else - ssid_len = _res; - _ssid = ssid_buf; + ssid_len = cli_status.ssid_len; + _ssid = cli_status.ssid; } os_memcpy(status->ssid, _ssid, ssid_len); status->ssid_len = ssid_len; @@ -388,9 +314,9 @@ int z_wpa_supplicant_status(const struct device *dev, status->link_mode = WIFI_LINK_MODE_UNKNOWN; } } - ret = wpa_drv_signal_poll(wpa_s, si); + ret = z_wpa_ctrl_signal_poll(&signal_poll); if (!ret) { - status->rssi = si->current_signal; + status->rssi = signal_poll.rssi; } else { wpa_printf(MSG_ERROR, "%s:Failed to read RSSI\n", __func__); diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index b84b7463e7..443db3101a 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -25,10 +25,10 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "fst/fst.h" #include "includes.h" #include "p2p_supplicant.h" -#include "wpa_supplicant_i.h" #include "driver_i.h" #include "supp_main.h" +#include "wpa_cli_zephyr.h" K_SEM_DEFINE(wpa_supplicant_ready_sem, 0, 1); @@ -69,6 +69,28 @@ static int wpa_supplicant_init_match(struct wpa_global *global) } #endif /* CONFIG_MATCH_IFACE */ +struct wpa_supplicant *get_wpa_s_handle_ifname(const char* ifname) +{ + struct wpa_supplicant *wpa_s = NULL; + int ret = k_sem_take(&wpa_supplicant_ready_sem, K_SECONDS(2)); + + if (ret) { + wpa_printf(MSG_ERROR, "%s: WPA supplicant not ready: %d", __func__, ret); + return NULL; + } + + k_sem_give(&wpa_supplicant_ready_sem); + + wpa_s = wpa_supplicant_get_iface(global, ifname); + if (!wpa_s) { + wpa_printf(MSG_ERROR, + "%s: Unable to get wpa_s handle for %s\n", __func__, ifname); + return NULL; + } + + return wpa_s; +} + #include "config.h" static void iface_cb(struct net_if *iface, void *user_data) { @@ -223,8 +245,8 @@ static void start_wpa_supplicant(void) net_if_foreach(iface_cb, ifaces); - ifaces[0].ctrl_interface = "test_ctrl"; - params.ctrl_interface = "test_ctrl"; + ifaces[0].ctrl_interface = "zephyr"; + params.ctrl_interface = "zephyr"; wpa_printf(MSG_INFO, "Using interface %s\n", ifaces[0].ifname); for (i = 0; exitcode == 0 && i < iface_count; i++) { @@ -251,6 +273,7 @@ static void start_wpa_supplicant(void) exitcode = -1; break; } + z_wpa_ctrl_init(wpa_s); wpa_s->conf->filter_ssids = 1; wpa_s->conf->ap_scan= 1; } @@ -270,6 +293,7 @@ static void start_wpa_supplicant(void) eloop_unregister_read_sock(wpa_event_sockpair[0]); + z_wpa_ctrl_deinit(); wpa_supplicant_deinit(global); fst_global_deinit(); diff --git a/zephyr/src/supp_main.h b/zephyr/src/supp_main.h index d87ee253dc..4a7a0c7c44 100644 --- a/zephyr/src/supp_main.h +++ b/zephyr/src/supp_main.h @@ -6,6 +6,9 @@ #ifndef __SUPP_MAIN_H_ #define __SUPP_MAIN_H_ +#include "wpa_supplicant_i.h" + +struct wpa_supplicant *get_wpa_s_handle_ifname(const char* ifname); struct wpa_supplicant_event_msg { /* Dummy messages to unblock select */ bool ignore_msg; From 4bf4967a83e8c3a00c58dca4bcb967c18b182e86 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 24 Jan 2023 21:28:07 +0530 Subject: [PATCH 086/150] Disable non-zephyr-wifi commands by default For basic Wi-Fi operation in Zephyr we only need few commands, so, to save flash space disable other commands by default. This also involves reordering them to group. CONFIG_WPA_CLI is used for developer access that enables all commands at the cost of Flash. Signed-off-by: Krishna T --- wpa_supplicant/wpa_cli_cmds.c | 510 +++++++++++++++++----------------- 1 file changed, 256 insertions(+), 254 deletions(-) diff --git a/wpa_supplicant/wpa_cli_cmds.c b/wpa_supplicant/wpa_cli_cmds.c index 4c9ddd660f..582fdcfae7 100644 --- a/wpa_supplicant/wpa_cli_cmds.c +++ b/wpa_supplicant/wpa_cli_cmds.c @@ -36,11 +36,6 @@ static DEFINE_DL_LIST(creds); /* struct cli_txt_entry */ static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */ #endif /* CONFIG_AP */ -static void wpa_cli_msg_cb(char *msg, size_t len) -{ - wpa_printf(MSG_INFO, "%s\n", msg); -} - static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, int argc, char *argv[]) { @@ -72,9 +67,213 @@ static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, } -static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[]) +static const char *network_fields[] = { + "ssid", "scan_ssid", "bssid", "bssid_ignore", + "bssid_accept", "psk", "proto", "key_mgmt", + "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq", + "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1", + "vht_center_freq2", "ht", "edmg", +#ifdef IEEE8021X_EAPOL + "eap", "identity", "anonymous_identity", "password", "ca_cert", + "ca_path", "client_cert", "private_key", "private_key_passwd", + "dh_file", "subject_match", "altsubject_match", + "check_cert_subject", + "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2", + "client_cert2", "private_key2", "private_key2_passwd", + "dh_file2", "subject_match2", "altsubject_match2", + "check_cert_subject2", + "domain_suffix_match2", "domain_match2", "phase1", "phase2", + "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id", + "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id", + "engine", "engine2", "eapol_flags", "sim_num", + "openssl_ciphers", "erp", +#endif /* IEEE8021X_EAPOL */ + "wep_key0", "wep_key1", "wep_key2", "wep_key3", + "wep_tx_keyidx", "priority", +#ifdef IEEE8021X_EAPOL + "eap_workaround", "pac_file", "fragment_size", "ocsp", +#endif /* IEEE8021X_EAPOL */ + "mode", + "proactive_key_caching", "disabled", "id_str", + "ieee80211w", + "mixed_cell", "frequency", "fixed_freq", +#ifdef CONFIG_MESH + "no_auto_peer", "mesh_rssi_threshold", + "mesh_basic_rates", "dot11MeshMaxRetries", + "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout", + "dot11MeshHoldingTimeout", +#endif /* CONFIG_MESH */ + "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", + "wpa_deny_ptk0_rekey", + "enable_edmg", "edmg_channel", +#ifdef CONFIG_P2P + "go_p2p_dev_addr", "p2p_client_list", "psk_list", +#endif /* CONFIG_P2P */ +#ifdef CONFIG_HT_OVERRIDES + "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc", + "ht40_intolerant", "disable_max_amsdu", "ampdu_factor", + "ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc", +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1", + "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4", + "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7", + "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2", + "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5", + "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8", +#endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + "disable_he", +#endif /* CONFIG_HE_OVERRIDES */ + "ap_max_inactivity", "dtim_period", "beacon_int", +#ifdef CONFIG_MACSEC + "macsec_policy", + "macsec_integ_only", + "macsec_replay_protect", + "macsec_replay_window", + "macsec_port", + "mka_priority", +#endif /* CONFIG_MACSEC */ +#ifdef CONFIG_HS20 + "update_identifier", +#endif /* CONFIG_HS20 */ + "mac_addr", "pbss", "wps_disabled" +}; + + +static char ** wpa_cli_complete_network(const char *str, int pos) { - return wpa_ctrl_command(ctrl, "IFNAME"); + int arg = get_cmd_arg_num(str, pos); + int i, num_fields = ARRAY_SIZE(network_fields); + char **res = NULL; + + switch (arg) { + case 1: + res = cli_txt_list_array(&networks); + break; + case 2: + res = os_calloc(num_fields + 1, sizeof(char *)); + if (res == NULL) + return NULL; + for (i = 0; i < num_fields; i++) { + res[i] = os_strdup(network_fields[i]); + if (res[i] == NULL) + break; + } + } + return res; +} + +static char ** wpa_cli_complete_network_id(const char *str, int pos) +{ + int arg = get_cmd_arg_num(str, pos); + if (arg == 1) + return cli_txt_list_array(&networks); + return NULL; +} + +static void wpa_cli_show_network_variables(void) +{ + wpa_printf(MSG_INFO, "set_network variables:\n" + " ssid (network name, SSID)\n" + " psk (WPA passphrase or pre-shared key)\n" + " key_mgmt (key management protocol)\n" + " identity (EAP identity)\n" + " password (EAP password)\n" + " ...\n" + "\n" + "Note: Values are entered in the same format as the " + "configuration file is using,\n" + "i.e., strings values need to be inside double quotation " + "marks.\n" + "For example: set_network 1 ssid \"network name\"\n" + "\n" + "Please see wpa_supplicant.conf documentation for full list " + "of\navailable variables.\n"); +} + + +static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc == 0) { + wpa_cli_show_network_variables(); + return 0; + } + + if (argc < 3) { + wpa_printf(MSG_INFO, "Invalid SET_NETWORK command: needs three arguments\n" + "(network id, variable name, and value)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv); +} + + +static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + if (argc == 0) { + wpa_cli_show_network_variables(); + return 0; + } + + if (argc < 2) { + wpa_printf(MSG_INFO, "Invalid GET_NETWORK command: needs two arguments\n" + "(network id and variable name)\n"); + return -1; + } + + return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv); +} + +static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "LIST_NETWORKS", 0, argc, argv); +} + + +static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "ADD_NETWORK"); +} + + +static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv); +} + + +static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DISCONNECT"); } @@ -90,6 +289,18 @@ static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +#if !defined(CONFIG_ZEPHYR) || (defined(CONFIG_ZEPHYR) && defined(CONFIG_WPA_CLI)) +static void wpa_cli_msg_cb(char *msg, size_t len) +{ + wpa_printf(MSG_INFO, "%s\n", msg); +} + +static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "IFNAME"); +} + + static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "PING"); @@ -1039,212 +1250,6 @@ static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) } -static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "LIST_NETWORKS", 0, argc, argv); -} - - -static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv); -} - - -static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "ADD_NETWORK"); -} - - -static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv); -} - - -static void wpa_cli_show_network_variables(void) -{ - wpa_printf(MSG_INFO, "set_network variables:\n" - " ssid (network name, SSID)\n" - " psk (WPA passphrase or pre-shared key)\n" - " key_mgmt (key management protocol)\n" - " identity (EAP identity)\n" - " password (EAP password)\n" - " ...\n" - "\n" - "Note: Values are entered in the same format as the " - "configuration file is using,\n" - "i.e., strings values need to be inside double quotation " - "marks.\n" - "For example: set_network 1 ssid \"network name\"\n" - "\n" - "Please see wpa_supplicant.conf documentation for full list " - "of\navailable variables.\n"); -} - - -static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc < 3) { - wpa_printf(MSG_INFO, "Invalid SET_NETWORK command: needs three arguments\n" - "(network id, variable name, and value)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv); -} - - -static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc < 2) { - wpa_printf(MSG_INFO, "Invalid GET_NETWORK command: needs two arguments\n" - "(network id and variable name)\n"); - return -1; - } - - return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv); -} - - -static const char *network_fields[] = { - "ssid", "scan_ssid", "bssid", "bssid_ignore", - "bssid_accept", "psk", "proto", "key_mgmt", - "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq", - "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1", - "vht_center_freq2", "ht", "edmg", -#ifdef IEEE8021X_EAPOL - "eap", "identity", "anonymous_identity", "password", "ca_cert", - "ca_path", "client_cert", "private_key", "private_key_passwd", - "dh_file", "subject_match", "altsubject_match", - "check_cert_subject", - "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2", - "client_cert2", "private_key2", "private_key2_passwd", - "dh_file2", "subject_match2", "altsubject_match2", - "check_cert_subject2", - "domain_suffix_match2", "domain_match2", "phase1", "phase2", - "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id", - "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id", - "engine", "engine2", "eapol_flags", "sim_num", - "openssl_ciphers", "erp", -#endif /* IEEE8021X_EAPOL */ - "wep_key0", "wep_key1", "wep_key2", "wep_key3", - "wep_tx_keyidx", "priority", -#ifdef IEEE8021X_EAPOL - "eap_workaround", "pac_file", "fragment_size", "ocsp", -#endif /* IEEE8021X_EAPOL */ - "mode", - "proactive_key_caching", "disabled", "id_str", - "ieee80211w", - "mixed_cell", "frequency", "fixed_freq", -#ifdef CONFIG_MESH - "no_auto_peer", "mesh_rssi_threshold", - "mesh_basic_rates", "dot11MeshMaxRetries", - "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout", - "dot11MeshHoldingTimeout", -#endif /* CONFIG_MESH */ - "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", - "wpa_deny_ptk0_rekey", - "enable_edmg", "edmg_channel", -#ifdef CONFIG_P2P - "go_p2p_dev_addr", "p2p_client_list", "psk_list", -#endif /* CONFIG_P2P */ -#ifdef CONFIG_HT_OVERRIDES - "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc", - "ht40_intolerant", "disable_max_amsdu", "ampdu_factor", - "ampdu_density", "ht_mcs", "rx_stbc", "tx_stbc", -#endif /* CONFIG_HT_OVERRIDES */ -#ifdef CONFIG_VHT_OVERRIDES - "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1", - "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4", - "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7", - "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2", - "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5", - "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8", -#endif /* CONFIG_VHT_OVERRIDES */ -#ifdef CONFIG_HE_OVERRIDES - "disable_he", -#endif /* CONFIG_HE_OVERRIDES */ - "ap_max_inactivity", "dtim_period", "beacon_int", -#ifdef CONFIG_MACSEC - "macsec_policy", - "macsec_integ_only", - "macsec_replay_protect", - "macsec_replay_window", - "macsec_port", - "mka_priority", -#endif /* CONFIG_MACSEC */ -#ifdef CONFIG_HS20 - "update_identifier", -#endif /* CONFIG_HS20 */ - "mac_addr", "pbss", "wps_disabled" -}; - - -static char ** wpa_cli_complete_network(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - int i, num_fields = ARRAY_SIZE(network_fields); - char **res = NULL; - - switch (arg) { - case 1: - res = cli_txt_list_array(&networks); - break; - case 2: - res = os_calloc(num_fields + 1, sizeof(char *)); - if (res == NULL) - return NULL; - for (i = 0; i < num_fields; i++) { - res[i] = os_strdup(network_fields[i]); - if (res[i] == NULL) - break; - } - } - return res; -} - - -static char ** wpa_cli_complete_network_id(const char *str, int pos) -{ - int arg = get_cmd_arg_num(str, pos); - if (arg == 1) - return cli_txt_list_array(&networks); - return NULL; -} - - static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1369,13 +1374,6 @@ static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) } -static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "DISCONNECT"); -} - - static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -2933,6 +2931,8 @@ static int wpa_cli_cmd_dscp_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) return wpa_cli_cmd(ctrl, "DSCP_QUERY", 1, argc, argv); } +#endif /* !CONFIG_ZEPHYR || (CONFIG_ZEPHYR && CONFIG_WPA_CLI)*/ + enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, @@ -2950,7 +2950,41 @@ struct wpa_cli_cmd { static const struct wpa_cli_cmd wpa_cli_commands[] = { { "status", wpa_cli_cmd_status, NULL, cli_cmd_flag_none, - "[verbose] = get current WPA/EAPOL/EAP status" }, + "[verbose] = get current WPA/EAPOL/EAP status" }, + { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network, + cli_cmd_flag_sensitive, + " = set network variables (shows\n" + " list of variables when run without arguments)" }, + { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network, + cli_cmd_flag_none, + " = get network variables" }, + { "list_networks", wpa_cli_cmd_list_networks, NULL, + cli_cmd_flag_none, + "= list configured networks" }, + { "select_network", wpa_cli_cmd_select_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = select a network (disable others)" }, + { "enable_network", wpa_cli_cmd_enable_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = enable a network" }, + { "disable_network", wpa_cli_cmd_disable_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = disable a network" }, + { "add_network", wpa_cli_cmd_add_network, NULL, + cli_cmd_flag_none, + "= add a network" }, + { "remove_network", wpa_cli_cmd_remove_network, + wpa_cli_complete_network_id, + cli_cmd_flag_none, + " = remove a network" }, + { "disconnect", wpa_cli_cmd_disconnect, NULL, + cli_cmd_flag_none, + "= disconnect and wait for reassociate/reconnect command before\n" + " connecting" }, +#if !defined(CONFIG_ZEPHYR) || (defined(CONFIG_ZEPHYR) && defined(CONFIG_WPA_CLI)) { "ifname", wpa_cli_cmd_ifname, NULL, cli_cmd_flag_none, "= get current interface name" }, @@ -3058,35 +3092,6 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { cli_cmd_flag_none, " [] = update the log level/timestamp\n" "log_level = display the current log level and log options" }, - { "list_networks", wpa_cli_cmd_list_networks, NULL, - cli_cmd_flag_none, - "= list configured networks" }, - { "select_network", wpa_cli_cmd_select_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = select a network (disable others)" }, - { "enable_network", wpa_cli_cmd_enable_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = enable a network" }, - { "disable_network", wpa_cli_cmd_disable_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = disable a network" }, - { "add_network", wpa_cli_cmd_add_network, NULL, - cli_cmd_flag_none, - "= add a network" }, - { "remove_network", wpa_cli_cmd_remove_network, - wpa_cli_complete_network_id, - cli_cmd_flag_none, - " = remove a network" }, - { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network, - cli_cmd_flag_sensitive, - " = set network variables (shows\n" - " list of variables when run without arguments)" }, - { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network, - cli_cmd_flag_none, - " = get network variables" }, { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network, cli_cmd_flag_none, " = duplicate network variables" @@ -3109,10 +3114,6 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "save_config", wpa_cli_cmd_save_config, NULL, cli_cmd_flag_none, "= save the current configuration" }, - { "disconnect", wpa_cli_cmd_disconnect, NULL, - cli_cmd_flag_none, - "= disconnect and wait for reassociate/reconnect command before\n" - " connecting" }, { "reconnect", wpa_cli_cmd_reconnect, NULL, cli_cmd_flag_none, "= like reassociate, but only takes effect if already disconnected" @@ -3634,6 +3635,7 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "dscp_query", wpa_cli_cmd_dscp_query, NULL, cli_cmd_flag_none, "wildcard/domain_name= = Send DSCP Query" }, +#endif /* !CONFIG_ZEPHYR || (CONFIG_ZEPHYR && CONFIG_WPA_CLI)*/ { NULL, NULL, NULL, cli_cmd_flag_none, NULL } }; From a913c4500cdef366f37ae8c17167bfe0f8f1c9ca Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 19 Jan 2023 18:31:55 +0530 Subject: [PATCH 087/150] Fix unnecessary delay in getting wiphy info Fetching wiphy info is quicker but due to sleeping 1 sec between each attempt we end up waiting full second. Use semaphores instead of sleep to immediately quit waiting once information is available. Make the semaphore generic, so that it can be reused for others too. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 20 ++++++++++++-------- src/drivers/driver_zephyr.h | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 7b9d37c1b4..60192064a6 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -15,6 +15,7 @@ #include "common/ieee802_11_common.h" #define SCAN_TIMEOUT 30 +#define GET_WIPHY_TIMEOUT 10 void wpa_supplicant_event_wrapper(void *ctx, enum wpa_event_type event, @@ -470,7 +471,8 @@ static int phy_info_band_cfg(struct phy_info_arg *phy_info, static void wpa_drv_zep_event_get_wiphy(struct zep_drv_if_ctx *if_ctx, void *band_info) { if (!band_info) { - if_ctx->get_wiphy_in_progress = false; + /* Done with all bands */ + k_sem_give(&if_ctx->drv_resp_sem); return; } @@ -642,7 +644,6 @@ struct hostapd_hw_modes *wpa_drv_get_hw_feature_data(void *priv, struct zep_drv_if_ctx *if_ctx = NULL; const struct zep_wpa_supp_dev_ops *dev_ops = NULL; int ret = -1; - int i=0; if_ctx = priv; @@ -662,14 +663,15 @@ struct hostapd_hw_modes *wpa_drv_get_hw_feature_data(void *priv, if_ctx->phy_info_arg = &result; - if_ctx->get_wiphy_in_progress = true; - ret = dev_ops->get_wiphy(if_ctx->dev_priv); + if (ret < 0) { + return NULL; + } - while ((if_ctx->get_wiphy_in_progress) && (i < SCAN_TIMEOUT)) { - k_yield(); - os_sleep(1, 0); - i++; + k_sem_take(&if_ctx->drv_resp_sem, K_SECONDS(GET_WIPHY_TIMEOUT)); + + if (!result.modes) { + return NULL; } struct hostapd_hw_modes *modes; @@ -788,6 +790,8 @@ static void *wpa_drv_zep_init(void *ctx, goto out; } + k_sem_init(&if_ctx->drv_resp_sem, 0, 1); + wpa_drv_mgmt_subscribe_non_ap(if_ctx); out: diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index 8ef2a73f62..ba80237c71 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -112,6 +112,7 @@ struct zep_drv_if_ctx { void *supp_if_ctx; const struct device *dev_ctx; void *dev_priv; + struct k_sem drv_resp_sem; struct wpa_scan_results *scan_res2; bool scan_res2_get_in_prog; @@ -123,7 +124,6 @@ struct zep_drv_if_ctx { bool associated; void *phy_info_arg; - bool get_wiphy_in_progress; }; From ca396ab4472f9c6a6a2c3fe7f253911f63b7140b Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 19 Jan 2023 19:40:24 +0530 Subject: [PATCH 088/150] Use semaphore for scan instead of sleep This slightly improves the scan done time as we don't wait an extra second. Add resets before re-using the semaphore. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 60192064a6..966a5fc79e 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -107,6 +107,7 @@ void wpa_drv_zep_event_proc_scan_done(struct zep_drv_if_ctx *if_ctx, if_ctx->supp_if_ctx); if_ctx->scan_res2_get_in_prog = false; + k_sem_give(&if_ctx->drv_resp_sem); wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_SCAN_RESULTS, @@ -145,13 +146,10 @@ void wpa_drv_zep_event_proc_scan_res(struct zep_drv_if_ctx *if_ctx, if_ctx->scan_res2->res = tmp; - if_ctx->scan_res2_get_in_prog = more_res; - - return; err: - /* Ignore failures except the last */ if (!more_res) { if_ctx->scan_res2_get_in_prog = false; + k_sem_give(&if_ctx->drv_resp_sem); } } @@ -668,6 +666,7 @@ struct hostapd_hw_modes *wpa_drv_get_hw_feature_data(void *priv, return NULL; } + k_sem_reset(&if_ctx->drv_resp_sem); k_sem_take(&if_ctx->drv_resp_sem, K_SECONDS(GET_WIPHY_TIMEOUT)); if (!result.modes) { @@ -889,7 +888,6 @@ struct wpa_scan_results *wpa_drv_zep_get_scan_results2(void *priv) { struct zep_drv_if_ctx *if_ctx = NULL; const struct zep_wpa_supp_dev_ops *dev_ops = NULL; - unsigned int i = 0; int ret = -1; if (!priv) { @@ -924,14 +922,10 @@ struct wpa_scan_results *wpa_drv_zep_get_scan_results2(void *priv) if_ctx->scan_res2_get_in_prog = true; - /* Wait for the device to populate the scan results */ - while ((if_ctx->scan_res2_get_in_prog) && (i < SCAN_TIMEOUT)) { - k_yield(); - os_sleep(1, 0); - i++; - } + k_sem_reset(&if_ctx->drv_resp_sem); + k_sem_take(&if_ctx->drv_resp_sem, K_SECONDS(SCAN_TIMEOUT)); - if (i == SCAN_TIMEOUT) { + if (if_ctx->scan_res2_get_in_prog) { wpa_printf(MSG_ERROR, "%s: Timed out waiting for scan results\n", __func__); ret = -1; goto out; From 207e0508be39a4896ec584037888b747b9ace558 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 6 Feb 2023 13:06:08 +0530 Subject: [PATCH 089/150] Fix WPA2-PSK-SHA256 security This was a typo but as its in the string for WPA CLI, went undetected. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index e0fb3353e1..420704cd87 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -163,7 +163,7 @@ int z_wpa_supplicant_connect(const struct device *dev, } else if (params->security == 2) { z_wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id, params->psk); - z_wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-256", + z_wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256", resp.network_id); } else { z_wpa_cli_cmd_v( "set_network %d psk \"%s\"", From f65559c5d5e2692ae62e5f74f36ea47850a0d6c3 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 7 Feb 2023 02:17:13 +0530 Subject: [PATCH 090/150] Fix data access violation If a sample doesn't use POSIX_API then the default POSIX_MAX_FDS are 4, but Zephyr's WPA supplicant needs at least 7, so, fix this by explicitly defining it. Signed-off-by: Krishna T --- zephyr/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 8ca908ceb5..e1ee08f18b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -75,6 +75,12 @@ config WPA_CLI config NET_SOCKETPAIR_BUFFER_SIZE default 4096 if WPA_CLI +config POSIX_MAX_FDS + # l2_packet - 1 + # ctrl_iface - 2 * socketpairs = 4(local and global) + # z_wpa_event_sock - 1 socketpair = 2 + default 7 if !POSIX_API + module = WPA_SUPP module-str = WPA supplicant source "subsys/logging/Kconfig.template.log_config" From 05584835c5828fae94e856116579d078d27dac58 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 7 Feb 2023 13:43:21 +0530 Subject: [PATCH 091/150] Remove editing support This needs CONFIG_POSIX_API and now that we have moved to use wpa_cli_zephyr this is no longer required. Signed-off-by: Krishna T --- zephyr/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 80b7e47832..7056ff2483 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -69,7 +69,6 @@ zephyr_library_sources( ${COMMON_SRC_BASE}/utils/eloop.c ${COMMON_SRC_BASE}/utils/os_zephyr.c ${COMMON_SRC_BASE}/utils/radiotap.c - ${COMMON_SRC_BASE}/utils/edit_simple.c ${WPA_SUPPLICANT_BASE}/config.c ${WPA_SUPPLICANT_BASE}/notify.c ${WPA_SUPPLICANT_BASE}/bss.c From ccda6879cfd92a8081dd0ca6876865f492837a27 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Wed, 8 Feb 2023 00:24:51 +0530 Subject: [PATCH 092/150] Send connect success after authorizing port If we send too early and if data starts immediately then it might be dropped as the port might still be unauthorized. Signed-off-by: Krishna T --- wpa_supplicant/wpa_supplicant.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 72c0b5918c..133d9da131 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1027,9 +1027,6 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, ssid && ssid->id_str ? ssid->id_str : "", fils_hlp_sent ? " FILS_HLP_SENT" : ""); #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#ifdef CONFIG_ZEPHYR - send_wifi_mgmt_event(wpa_s->ifname, NET_EVENT_WIFI_CMD_CONNECT_RESULT, 0); -#endif /* CONFIG_ZEPHYR */ wpas_clear_temp_disabled(wpa_s, ssid, 1); wpa_s->consecutive_conn_failures = 0; wpa_s->new_connection = 0; @@ -1044,6 +1041,9 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, sme_sched_obss_scan(wpa_s, 1); +#ifdef CONFIG_ZEPHYR + send_wifi_mgmt_event(wpa_s->ifname, NET_EVENT_WIFI_CMD_CONNECT_RESULT, 0); +#endif /* CONFIG_ZEPHYR */ #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) if (!fils_hlp_sent && ssid && ssid->eap.erp) update_fils_connect_params = true; From ea5cbfe247c1383309b37b307a9e5e9c26e0b3e7 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sat, 4 Feb 2023 20:30:22 +0530 Subject: [PATCH 093/150] Initialize the argv array to zeroes In some commands argv is accessed fully and relies on NULL value to exit. This causes hard to debug crash. Signed-off-by: Krishna T --- wpa_supplicant/wpa_cli_zephyr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c index 6131e18d94..2a549a4fc4 100644 --- a/wpa_supplicant/wpa_cli_zephyr.c +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -262,8 +262,8 @@ int z_wpa_cli_cmd_v(const char *fmt, ...) { va_list cmd_args; int argc; - const char *argv[MAX_ARGS]; - char cmd[MAX_CMD_SIZE]; + const char *argv[MAX_ARGS] = {0}; + char cmd[MAX_CMD_SIZE] = {0}; va_start(cmd_args, fmt); vsnprintf(cmd, sizeof(cmd), fmt, cmd_args); From 7dd5323ba9041f8ec68ce0ffd906cfbf076c5fea Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sat, 4 Feb 2023 20:33:22 +0530 Subject: [PATCH 094/150] Add support for global control interface This is needed to manage interfaces using control interface for the upcoming hotplugging support. Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface_zephyr.c | 97 ++++++++++++++++++++++- wpa_supplicant/wpa_cli_cmds.c | 119 +++++++++++++++-------------- wpa_supplicant/wpa_cli_zephyr.c | 79 +++++++++++++++++-- wpa_supplicant/wpa_cli_zephyr.h | 6 ++ 4 files changed, 235 insertions(+), 66 deletions(-) diff --git a/wpa_supplicant/ctrl_iface_zephyr.c b/wpa_supplicant/ctrl_iface_zephyr.c index 4b3bca27c3..6b902a3dce 100644 --- a/wpa_supplicant/ctrl_iface_zephyr.c +++ b/wpa_supplicant/ctrl_iface_zephyr.c @@ -121,13 +121,106 @@ wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) { } +/* Global control interface */ + +static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, + void *sock_ctx) +{ + struct wpa_global *global = eloop_ctx; + char *buf, *pos; + int res; + char *reply = NULL; + size_t reply_len = 0; + + buf = os_zalloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recv(sock, buf, CTRL_IFACE_MAX_LEN, 0); + if (res < 0) { + wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", + strerror(errno)); + os_free(buf); + return; + } + + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } + buf[res] = '\0'; + + pos = buf; + while (*pos == ' ') + pos++; + + reply = wpa_supplicant_global_ctrl_iface_process(global, pos, + &reply_len); + + if (reply) { + send(sock, reply, reply_len, 0); + os_free(reply); + } else if (reply_len == 1) { + send(sock, "FAIL\n", 5, 0); + } else if (reply_len == 2) { + send(sock, "OK\n", 3, 0); + } + + os_free(buf); +} struct ctrl_iface_global_priv * wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) { - return (void *) 1; + struct ctrl_iface_global_priv *priv; + int ret; + + priv = os_zalloc(sizeof(*priv)); + if (priv == NULL) + return NULL; + priv->global = global; + memset(priv->sock_pair, -1, sizeof(priv->sock_pair)); + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, priv->sock_pair); + if (ret != 0) { + wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); + goto fail; + } + + os_free(global->params.ctrl_interface); + global->params.ctrl_interface = os_strdup("g_zephyr:"); + if (!global->params.ctrl_interface) { + wpa_printf(MSG_ERROR, "Failed to malloc global ctrl_interface\n"); + goto fail; + } + + eloop_register_read_sock(priv->sock_pair[1], wpa_supplicant_global_ctrl_iface_receive, + global, priv); + + return priv; + +fail: + if (priv->sock_pair[0] >= 0) + close(priv->sock_pair[0]); + if (priv->sock_pair[1] >= 0) + close(priv->sock_pair[1]); + os_free(priv); + return NULL; } void wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) { -} \ No newline at end of file + if (!priv) + return; + + if (priv->sock_pair[0] > -1) { + eloop_unregister_read_sock(priv->sock_pair[0]); + close(priv->sock_pair[0]); + priv->sock_pair[0] = -1; + } + + if (priv->sock_pair[1] >= 0) + close(priv->sock_pair[1]); + + os_free(priv); +} diff --git a/wpa_supplicant/wpa_cli_cmds.c b/wpa_supplicant/wpa_cli_cmds.c index 582fdcfae7..117461b46f 100644 --- a/wpa_supplicant/wpa_cli_cmds.c +++ b/wpa_supplicant/wpa_cli_cmds.c @@ -289,6 +289,53 @@ static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) } + +static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc < 1) { + wpa_printf(MSG_INFO, "Invalid INTERFACE_ADD command: needs at least one " + "argument (interface name)\n" + "All arguments: ifname confname driver ctrl_interface " + "driver_param bridge_name [create]\n"); + return -1; + } + + /* + * INTERFACE_ADD TABTABTABTAB + * TAB[TAB[TAB]] + */ + res = os_snprintf(cmd, sizeof(cmd), + "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", + argv[0], + argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", + argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", + argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "", + argc > 7 ? argv[7] : ""); + if (os_snprintf_error(sizeof(cmd), res)) + return -1; + cmd[sizeof(cmd) - 1] = '\0'; + return wpa_ctrl_command(ctrl, cmd); +} + + +static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv); +} + + +static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); +} + + #if !defined(CONFIG_ZEPHYR) || (defined(CONFIG_ZEPHYR) && defined(CONFIG_WPA_CLI)) static void wpa_cli_msg_cb(char *msg, size_t len) { @@ -1534,52 +1581,6 @@ static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, } -static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc < 1) { - wpa_printf(MSG_INFO, "Invalid INTERFACE_ADD command: needs at least one " - "argument (interface name)\n" - "All arguments: ifname confname driver ctrl_interface " - "driver_param bridge_name [create]\n"); - return -1; - } - - /* - * INTERFACE_ADD TABTABTABTAB - * TAB[TAB[TAB]] - */ - res = os_snprintf(cmd, sizeof(cmd), - "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", - argv[0], - argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", - argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", - argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "", - argc > 7 ? argv[7] : ""); - if (os_snprintf_error(sizeof(cmd), res)) - return -1; - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv); -} - - -static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); -} - - #ifdef CONFIG_AP static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -2984,6 +2985,19 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { cli_cmd_flag_none, "= disconnect and wait for reassociate/reconnect command before\n" " connecting" }, + { "interface_add", wpa_cli_cmd_interface_add, NULL, + cli_cmd_flag_none, + " \n" + " = adds new interface, all " + "parameters but\n" + " are optional. Supported types are station ('sta') and " + "AP ('ap')" }, + { "interface_remove", wpa_cli_cmd_interface_remove, NULL, + cli_cmd_flag_none, + " = removes the interface" }, + { "interface_list", wpa_cli_cmd_interface_list, NULL, + cli_cmd_flag_none, + "= list available interfaces" }, #if !defined(CONFIG_ZEPHYR) || (defined(CONFIG_ZEPHYR) && defined(CONFIG_WPA_CLI)) { "ifname", wpa_cli_cmd_ifname, NULL, cli_cmd_flag_none, @@ -3140,19 +3154,6 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "terminate", wpa_cli_cmd_terminate, NULL, cli_cmd_flag_none, "= terminate wpa_supplicant" }, - { "interface_add", wpa_cli_cmd_interface_add, NULL, - cli_cmd_flag_none, - " \n" - " = adds new interface, all " - "parameters but\n" - " are optional. Supported types are station ('sta') and " - "AP ('ap')" }, - { "interface_remove", wpa_cli_cmd_interface_remove, NULL, - cli_cmd_flag_none, - " = removes the interface" }, - { "interface_list", wpa_cli_cmd_interface_list, NULL, - cli_cmd_flag_none, - "= list available interfaces" }, { "ap_scan", wpa_cli_cmd_ap_scan, NULL, cli_cmd_flag_none, " = set ap_scan parameter" }, diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c index 2a549a4fc4..8462fd5270 100644 --- a/wpa_supplicant/wpa_cli_zephyr.c +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -30,7 +30,9 @@ #define MAX_ARGS 32 struct wpa_ctrl *ctrl_conn; +struct wpa_ctrl *global_ctrl_conn; char *ifname_prefix = NULL; +extern struct wpa_global *global; static void wpa_cli_msg_cb(char *msg, size_t len) { @@ -43,7 +45,7 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print, size_t len; int ret; - if (ctrl_conn == NULL) { + if (ctrl_conn == NULL && global_ctrl_conn == NULL) { printf("Not connected to wpa_supplicant - command dropped.\n"); return -1; } @@ -81,6 +83,15 @@ static int wpa_ctrl_command_resp(struct wpa_ctrl *ctrl, const char *cmd, char *r return _wpa_ctrl_command(ctrl, cmd, 0, resp); } +static void wpa_cli_close_connection(void) +{ + if (ctrl_conn == NULL) + return; + + wpa_ctrl_close(ctrl_conn); + ctrl_conn = NULL; +} + static int wpa_cli_open_connection(struct wpa_supplicant *wpa_s) { ctrl_conn = wpa_ctrl_open(wpa_s->ctrl_iface->sock_pair[0]); @@ -94,15 +105,29 @@ static int wpa_cli_open_connection(struct wpa_supplicant *wpa_s) return 0; } -static void wpa_cli_close_connection(void) +static int wpa_cli_open_global_ctrl(void) { - if (ctrl_conn == NULL) + global_ctrl_conn = wpa_ctrl_open(global->ctrl_iface->sock_pair[0]); + if (global_ctrl_conn == NULL) { + wpa_printf(MSG_ERROR, "Failed to open global control connection to " + "%d - %s", global->ctrl_iface->sock_pair[0], + strerror(errno)); + return -1; + } + + return 0; +} + +static void wpa_cli_close_global_ctrl(void) +{ + if (global_ctrl_conn == NULL) return; - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; + wpa_ctrl_close(global_ctrl_conn); + global_ctrl_conn = NULL; } + /* Lifted from zephyr shell_utils.c to handle escapes */ static inline uint16_t supp_strlen(const char *str) { @@ -234,6 +259,25 @@ int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) /* Public APIs */ +int z_global_wpa_ctrl_init(void) +{ + int ret; + + ret = wpa_cli_open_global_ctrl(); + if (ret < 0) { + wpa_printf(MSG_INFO, "Failed to initialize global control interface: %d", ret); + return ret; + } + + return ret; +} + + +void z_global_wpa_ctrl_deinit(void) +{ + return wpa_cli_close_global_ctrl(); +} + int z_wpa_ctrl_init(void *wpa_s) { int ret; @@ -338,3 +382,28 @@ int z_wpa_ctrl_status(struct status_resp *resp) return 0; } + +int z_wpa_global_ctrl_zephyr_cmd(int argc, const char *argv[]) +{ + return wpa_request(global_ctrl_conn, argc , (char **) argv); +} + +int z_wpa_cli_global_cmd_v(const char *fmt, ...) +{ + va_list cmd_args; + int argc; + const char *argv[MAX_ARGS] = {0}; + char cmd[MAX_CMD_SIZE]; + + va_start(cmd_args, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, cmd_args); + va_end(cmd_args); + + (void)supp_make_argv(&argc, &argv[0], cmd, MAX_ARGS); + + wpa_printf(MSG_DEBUG, "Calling wpa_cli: %s, argc: %d\n", cmd, argc); + for (int i = 0; i < argc; i++) + wpa_printf(MSG_DEBUG, "argv[%d]: %s\n", i, argv[i]); + + return z_wpa_global_ctrl_zephyr_cmd(argc, argv); +} diff --git a/wpa_supplicant/wpa_cli_zephyr.h b/wpa_supplicant/wpa_cli_zephyr.h index b16e772d8e..57e4e4feee 100644 --- a/wpa_supplicant/wpa_cli_zephyr.h +++ b/wpa_supplicant/wpa_cli_zephyr.h @@ -35,4 +35,10 @@ int z_wpa_ctrl_add_network(struct add_network_resp *resp); int z_wpa_ctrl_signal_poll(struct signal_poll_resp *resp); int z_wpa_ctrl_status(struct status_resp *resp); +/* Global control interface */ +int z_global_wpa_ctrl_init(void); +void z_global_wpa_ctrl_deinit(void); +int z_wpa_global_ctrl_zephyr_cmd(int argc, const char *argv[]); +int z_wpa_cli_global_cmd_v(const char *fmt, ...); + #endif /* __WPA_CLI_ZEPHYR_H_ */ From 128cee93318d3d2fb31cda79d98c42a07904613b Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sat, 4 Feb 2023 20:57:19 +0530 Subject: [PATCH 095/150] Fix namespaces Use "z_wpas_" as the prefix for all internal functions to disambiduate between wpa_supplicant APIs. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 2 +- zephyr/src/supp_api.c | 2 +- zephyr/src/supp_main.c | 44 ++++++++++++++++++------------------- zephyr/src/supp_main.h | 4 ++-- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 966a5fc79e..c8b35b0155 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -33,7 +33,7 @@ void wpa_supplicant_event_wrapper(void *ctx, } os_memcpy(msg.data, data, sizeof(*data)); } - send_wpa_supplicant_event(&msg); + z_wpas_send_event(&msg); } void wpa_drv_zep_event_mac_changed(struct zep_drv_if_ctx *if_ctx) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 420704cd87..54cd4588aa 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -60,7 +60,7 @@ static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work, static inline struct wpa_supplicant * get_wpa_s_handle(const struct device *dev) { - return get_wpa_s_handle_ifname(dev->name); + return z_wpas_get_handle_by_ifname(dev->name); } static void supp_shell_connect_status(struct k_work *work) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 443db3101a..0c94ba7432 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -30,17 +30,17 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "supp_main.h" #include "wpa_cli_zephyr.h" -K_SEM_DEFINE(wpa_supplicant_ready_sem, 0, 1); +K_SEM_DEFINE(z_wpas_ready_sem, 0, 1); struct wpa_global *global; -static int wpa_event_sockpair[2]; +static int z_wpas_event_sockpair[2]; -static void start_wpa_supplicant(void); +static void z_wpas_start(void); -K_THREAD_DEFINE(wpa_s_tid, +K_THREAD_DEFINE(z_wpa_s_tid, CONFIG_WPA_SUPP_THREAD_STACK_SIZE, - start_wpa_supplicant, + z_wpas_start, NULL, NULL, NULL, @@ -49,7 +49,7 @@ K_THREAD_DEFINE(wpa_s_tid, 0); #ifdef CONFIG_MATCH_IFACE -static int wpa_supplicant_init_match(struct wpa_global *global) +static int z_wpas_init_match(struct wpa_global *global) { /* * The assumption is that the first driver is the primary driver and @@ -69,17 +69,17 @@ static int wpa_supplicant_init_match(struct wpa_global *global) } #endif /* CONFIG_MATCH_IFACE */ -struct wpa_supplicant *get_wpa_s_handle_ifname(const char* ifname) +struct wpa_supplicant *z_wpas_get_handle_by_ifname(const char* ifname) { struct wpa_supplicant *wpa_s = NULL; - int ret = k_sem_take(&wpa_supplicant_ready_sem, K_SECONDS(2)); + int ret = k_sem_take(&z_wpas_ready_sem, K_SECONDS(2)); if (ret) { wpa_printf(MSG_ERROR, "%s: WPA supplicant not ready: %d", __func__, ret); return NULL; } - k_sem_give(&wpa_supplicant_ready_sem); + k_sem_give(&z_wpas_ready_sem); wpa_s = wpa_supplicant_get_iface(global, ifname); if (!wpa_s) { @@ -121,7 +121,7 @@ static void iface_cb(struct net_if *iface, void *user_data) os_free(ifname); } -static void wpa_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) +static void z_wpas_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) { int ret; ARG_UNUSED(eloop_ctx); @@ -158,29 +158,29 @@ static int register_wpa_event_sock(void) { int ret; - ret = socketpair(AF_UNIX, SOCK_STREAM, 0, wpa_event_sockpair); + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, z_wpas_event_sockpair); if (ret != 0) { wpa_printf(MSG_ERROR, "Failed to initialize socket: %s", strerror(errno)); return -1; } - eloop_register_read_sock(wpa_event_sockpair[0], wpa_event_sock_handler, NULL, NULL); + eloop_register_read_sock(z_wpas_event_sockpair[0], z_wpas_event_sock_handler, NULL, NULL); return 0; } -int send_wpa_supplicant_event(const struct wpa_supplicant_event_msg *msg) +int z_wpas_send_event(const struct wpa_supplicant_event_msg *msg) { int ret; unsigned int retry = 0; - if (wpa_event_sockpair[1] < 0) { + if (z_wpas_event_sockpair[1] < 0) { return -1; } retry_send: - ret = send(wpa_event_sockpair[1], msg, sizeof(*msg), 0); + ret = send(z_wpas_event_sockpair[1], msg, sizeof(*msg), 0); if (ret < 0) { if (errno == EINTR || errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK) { k_msleep(2); @@ -201,7 +201,7 @@ int send_wpa_supplicant_event(const struct wpa_supplicant_event_msg *msg) return 0; } -static void start_wpa_supplicant(void) +static void z_wpas_start(void) { int i; struct wpa_interface *ifaces, *iface; @@ -282,24 +282,24 @@ static void start_wpa_supplicant(void) #ifdef CONFIG_MATCH_IFACE if (exitcode == 0) { - exitcode = wpa_supplicant_init_match(global); + exitcode = z_wpas_init_match(global); } #endif /* CONFIG_MATCH_IFACE */ if (exitcode == 0) { - k_sem_give(&wpa_supplicant_ready_sem); + k_sem_give(&z_wpas_ready_sem); exitcode = wpa_supplicant_run(global); } - eloop_unregister_read_sock(wpa_event_sockpair[0]); + eloop_unregister_read_sock(z_wpas_event_sockpair[0]); z_wpa_ctrl_deinit(); wpa_supplicant_deinit(global); fst_global_deinit(); - close(wpa_event_sockpair[0]); - close(wpa_event_sockpair[1]); + close(z_wpas_event_sockpair[0]); + close(z_wpas_event_sockpair[1]); out: os_free(ifaces); @@ -308,6 +308,6 @@ static void start_wpa_supplicant(void) #endif /* CONFIG_MATCH_IFACE */ os_free(params.pid_file); - wpa_printf(MSG_INFO, "wpa_supplicant_main: exitcode %d", exitcode); + wpa_printf(MSG_INFO, "z_wpas_start: exitcode %d", exitcode); return; } diff --git a/zephyr/src/supp_main.h b/zephyr/src/supp_main.h index 4a7a0c7c44..447e41077e 100644 --- a/zephyr/src/supp_main.h +++ b/zephyr/src/supp_main.h @@ -8,7 +8,7 @@ #include "wpa_supplicant_i.h" -struct wpa_supplicant *get_wpa_s_handle_ifname(const char* ifname); +struct wpa_supplicant *z_wpas_get_handle_by_ifname(const char* ifname); struct wpa_supplicant_event_msg { /* Dummy messages to unblock select */ bool ignore_msg; @@ -16,5 +16,5 @@ struct wpa_supplicant_event_msg { unsigned int event; void *data; }; -int send_wpa_supplicant_event(const struct wpa_supplicant_event_msg *msg); +int z_wpas_send_event(const struct wpa_supplicant_event_msg *msg); #endif /* __SUPP_MAIN_H_ */ From f62b9d512a88e856cf81ce2400c5d898bed03699 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sat, 4 Feb 2023 21:00:50 +0530 Subject: [PATCH 096/150] Add interfaces hotplugging support Using the network management events from the driver dynamically add/remove interfaces to the WPA supplicant, this ensures a better integration of driver and WPA supplicant rather than WPA supplicant assuming interface is administratively up. Default behaviour now would be for the interface to be administratively up but operationally down till the WPA supplicant associates and then interface will be operationally up. Signed-off-by: Krishna T --- zephyr/Kconfig | 4 + zephyr/src/supp_api.c | 2 +- zephyr/src/supp_main.c | 212 ++++++++++++++++++++++++++++------------- 3 files changed, 152 insertions(+), 66 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e1ee08f18b..312f37015b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -22,6 +22,10 @@ config WPA_SUPP_THREAD_STACK_SIZE int "Stack size for wpa_supplicant thread" default 8192 +config WPA_SUPP_IFACE_WQ_STACK_SIZE + int "Stack size for wpa_supplicant iface workqueue" + default 4096 + config WEP bool "WEP (Legacy crypto) support" diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 54cd4588aa..24681b363c 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -123,7 +123,7 @@ int z_wpa_supplicant_connect(const struct device *dev, int ret = 0; struct add_network_resp resp = {0}; - if (!net_if_is_up(net_if_lookup_by_dev(dev))) { + if (!net_if_is_admin_up(net_if_lookup_by_dev(dev))) { wpa_printf(MSG_ERROR, "Interface %s is down, dropping connect", dev->name); diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 0c94ba7432..e07eafba1e 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -31,12 +31,20 @@ LOG_MODULE_REGISTER(wpa_supplicant, LOG_LEVEL_DBG); #include "wpa_cli_zephyr.h" K_SEM_DEFINE(z_wpas_ready_sem, 0, 1); +#include + +/* Should match with the driver name */ +#define DEFAULT_IFACE_NAME "wlan0" + +static struct net_mgmt_event_callback cb; +struct k_mutex iface_up_mutex; struct wpa_global *global; static int z_wpas_event_sockpair[2]; static void z_wpas_start(void); +static void z_wpas_iface_work_handler(struct k_work *item); K_THREAD_DEFINE(z_wpa_s_tid, CONFIG_WPA_SUPP_THREAD_STACK_SIZE, @@ -48,6 +56,17 @@ K_THREAD_DEFINE(z_wpa_s_tid, 0, 0); +static K_THREAD_STACK_DEFINE(z_wpas_iface_wq_stack, + CONFIG_WPA_SUPP_IFACE_WQ_STACK_SIZE); + +/* TODO: Debug why wsing system workqueue blocks the driver dedicated + * workqueue? + */ +static struct k_work_q z_wpas_iface_wq; +static K_WORK_DEFINE(z_wpas_iface_work, + z_wpas_iface_work_handler); + + #ifdef CONFIG_MATCH_IFACE static int z_wpas_init_match(struct wpa_global *global) { @@ -91,34 +110,130 @@ struct wpa_supplicant *z_wpas_get_handle_by_ifname(const char* ifname) return wpa_s; } +static int z_wpas_get_iface_count(void) +{ + struct wpa_supplicant *wpa_s; + unsigned count = 0; + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + count += 1; + } + return count; +} + +static int z_wpas_add_interface(const char* ifname) +{ + struct wpa_supplicant *wpa_s; + int ret; + + ret = z_wpa_cli_global_cmd_v("interface_add %s %s %s %s", + ifname, "zephyr", "zephyr", "zephyr"); + if (ret) { + wpa_printf(MSG_ERROR, "Failed to add interface: %s", ifname); + return -1; + } + + /* This cannot be through control interface as need the handle */ + wpa_s = wpa_supplicant_get_iface(global, ifname); + if (wpa_s == NULL) { + wpa_printf(MSG_ERROR, "Failed to add iface: %s", ifname); + return -1; + } + wpa_s->conf->filter_ssids = 1; + wpa_s->conf->ap_scan= 1; + + /* Default interface, kick start wpa_supplicant */ + if (z_wpas_get_iface_count() == 1) { + k_mutex_unlock(&iface_up_mutex); + } + + z_wpa_ctrl_init(wpa_s); + + return 0; +} + +static int z_wpas_remove_interface(const char* ifname) +{ + int ret; + + wpa_printf(MSG_INFO, "Remove interface %s\n", ifname); + + ret = z_wpa_cli_global_cmd_v("interface_remove %s", ifname); + if (ret) { + wpa_printf(MSG_ERROR, "Failed to add interface: %s", ifname); + return -1; + } + + return 0; +} + +static void iface_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + const char *ifname = iface->if_dev->dev->name; + + wpa_printf(MSG_INFO, "Event: %d", mgmt_event); + if (mgmt_event == NET_EVENT_IF_ADMIN_UP) { + z_wpas_add_interface(ifname); + } else if (mgmt_event == NET_EVENT_IF_ADMIN_DOWN) { + z_wpas_remove_interface(ifname); + } +} + +static void register_iface_events(void) +{ + k_mutex_init(&iface_up_mutex); + + k_mutex_lock(&iface_up_mutex, K_FOREVER); + net_mgmt_init_event_callback(&cb, iface_event_handler, + NET_EVENT_IF_ADMIN_UP | NET_EVENT_IF_ADMIN_DOWN); + net_mgmt_add_event_callback(&cb); +} + +static void wait_for_interface_up(const char* iface_name) +{ + if (z_wpas_get_iface_count() == 0) { + k_mutex_lock(&iface_up_mutex, K_FOREVER); + } +} + #include "config.h" static void iface_cb(struct net_if *iface, void *user_data) { - struct wpa_interface *ifaces = user_data; - struct net_linkaddr *link_addr = NULL; - int ifindex; - char own_addr[NET_LINK_ADDR_MAX_LENGTH]; - char *ifname; - - ifindex = net_if_get_by_iface(iface); - link_addr = &iface->if_dev->link_addr; - /* 802.15.4 interface, ignore */ - if (link_addr->len > NET_LINK_ADDR_MAX_LENGTH) { + const char *ifname = iface->if_dev->dev->name; + + if (ifname == NULL) { + return; + } + + if (strncmp(ifname, DEFAULT_IFACE_NAME, strlen(ifname)) != 0) + { return; } - os_memcpy(own_addr, link_addr->addr, link_addr->len); - ifname = os_strdup(iface->if_dev->dev->name); - wpa_printf( - MSG_INFO, - "iface_cb: iface %s ifindex %d %02x:%02x:%02x:%02x:%02x:%02x", - ifname ? ifname: "Unknown", ifindex, own_addr[0], own_addr[1], - own_addr[2], own_addr[3], own_addr[4], own_addr[5]); + /* Check default interface */ + if (net_if_is_admin_up(iface)) { + z_wpas_add_interface(ifname); + } + + register_iface_events(); +} + + +static void z_wpas_iface_work_handler(struct k_work *item) +{ + ARG_UNUSED(item); + + int ret = k_sem_take(&z_wpas_ready_sem, K_SECONDS(5)); + if (ret) { + wpa_printf(MSG_ERROR, "Timed out waiting for wpa_supplicant"); + return; + } - /* TODO : make this user configurable*/ - ifaces[0].ifname = "wlan0"; + net_if_foreach(iface_cb, NULL); + wait_for_interface_up(DEFAULT_IFACE_NAME); - os_free(ifname); + k_sem_give(&z_wpas_ready_sem); } static void z_wpas_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) @@ -203,10 +318,15 @@ int z_wpas_send_event(const struct wpa_supplicant_event_msg *msg) static void z_wpas_start(void) { - int i; - struct wpa_interface *ifaces, *iface; - int iface_count, exitcode = -1; struct wpa_params params; + int exitcode = -1; + k_work_queue_init(&z_wpas_iface_wq); + + k_work_queue_start(&z_wpas_iface_wq, + z_wpas_iface_wq_stack, + K_THREAD_STACK_SIZEOF(z_wpas_iface_wq_stack), + 7, + NULL); os_memset(¶ms, 0, sizeof(params)); params.wpa_debug_level = CONFIG_WPA_SUPP_DEBUG_LEVEL; @@ -214,12 +334,6 @@ static void z_wpas_start(void) wpa_printf(MSG_INFO, "%s: %d Starting wpa_supplicant thread with debug level: %d\n", __func__, __LINE__, params.wpa_debug_level); - iface = ifaces = os_zalloc(sizeof(struct wpa_interface)); - if (ifaces == NULL) { - return; - } - iface_count = 1; - exitcode = 0; global = wpa_supplicant_init(¶ms); if (global == NULL) { @@ -242,44 +356,12 @@ static void z_wpas_start(void) wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl"); } #endif - - net_if_foreach(iface_cb, ifaces); - - ifaces[0].ctrl_interface = "zephyr"; - params.ctrl_interface = "zephyr"; - wpa_printf(MSG_INFO, "Using interface %s\n", ifaces[0].ifname); - - for (i = 0; exitcode == 0 && i < iface_count; i++) { - struct wpa_supplicant *wpa_s; - - if ((ifaces[i].confname == NULL && - ifaces[i].ctrl_interface == NULL) || - ifaces[i].ifname == NULL) { - if (iface_count == 1 && (params.ctrl_interface || -#ifdef CONFIG_MATCH_IFACE - params.match_iface_count || -#endif /* CONFIG_MATCH_IFACE */ - params.dbus_ctrl_interface)) - break; - wpa_printf(MSG_INFO, - "Failed to initialize interface %d\n", i); - exitcode = -1; - break; - } - wpa_printf(MSG_INFO, "Initializing interface %d: %s\n", i, - ifaces[i].ifname); - wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL); - if (wpa_s == NULL) { - exitcode = -1; - break; - } - z_wpa_ctrl_init(wpa_s); - wpa_s->conf->filter_ssids = 1; - wpa_s->conf->ap_scan= 1; - } + z_global_wpa_ctrl_init(); register_wpa_event_sock(); + k_work_submit_to_queue(&z_wpas_iface_wq, &z_wpas_iface_work); + #ifdef CONFIG_MATCH_IFACE if (exitcode == 0) { exitcode = z_wpas_init_match(global); @@ -294,6 +376,7 @@ static void z_wpas_start(void) eloop_unregister_read_sock(z_wpas_event_sockpair[0]); z_wpa_ctrl_deinit(); + z_global_wpa_ctrl_deinit(); wpa_supplicant_deinit(global); fst_global_deinit(); @@ -302,7 +385,6 @@ static void z_wpas_start(void) close(z_wpas_event_sockpair[1]); out: - os_free(ifaces); #ifdef CONFIG_MATCH_IFACE os_free(params.match_ifaces); #endif /* CONFIG_MATCH_IFACE */ From 733a8874a4a8aaab1c7cbab70777bf71f89a7960 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sat, 4 Feb 2023 21:18:56 +0530 Subject: [PATCH 097/150] Fix error reporting errno is not applicable for malloc, so, remove and add missing logs for other error scenarios. Signed-off-by: Krishna T --- src/common/wpa_ctrl.c | 6 ++++-- wpa_supplicant/ctrl_iface.c | 4 ++-- wpa_supplicant/wpa_cli_zephyr.c | 10 ++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c index 5107837e82..afdd93697c 100644 --- a/src/common/wpa_ctrl.c +++ b/src/common/wpa_ctrl.c @@ -589,13 +589,15 @@ struct wpa_ctrl * wpa_ctrl_open(const int sock) struct wpa_ctrl *ctrl; if (sock < 0) { - wpa_printf(MSG_ERROR, "Invalid socket"); + wpa_printf(MSG_ERROR, "Invalid socket : %d\n", sock); return NULL; } ctrl = os_zalloc(sizeof(*ctrl)); - if (ctrl == NULL) + if (ctrl == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory: %d\n", sizeof(*ctrl)); return NULL; + } /* We use one of the socketpair opened in ctrl_iface_zephyr.c */ ctrl->s = sock; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index d6f6ad2fff..cd82b2bdb7 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11478,8 +11478,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply = os_malloc(reply_size); if (reply == NULL) { - wpa_printf(MSG_ERROR, "ctrl_iface: reply malloc of %d failed %s", - reply_size, strerror(errno)); + wpa_printf(MSG_ERROR, "ctrl_iface: reply malloc of %d failed", + reply_size); *resp_len = 1; return NULL; } diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c index 8462fd5270..550b6f0f26 100644 --- a/wpa_supplicant/wpa_cli_zephyr.c +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -96,9 +96,8 @@ static int wpa_cli_open_connection(struct wpa_supplicant *wpa_s) { ctrl_conn = wpa_ctrl_open(wpa_s->ctrl_iface->sock_pair[0]); if (ctrl_conn == NULL) { - wpa_printf(MSG_ERROR, "Failed to open control connection to " - "%d - %s", wpa_s->ctrl_iface->sock_pair[0], - strerror(errno)); + wpa_printf(MSG_ERROR, "Failed to open control connection to %d", + wpa_s->ctrl_iface->sock_pair[0]); return -1; } @@ -109,9 +108,8 @@ static int wpa_cli_open_global_ctrl(void) { global_ctrl_conn = wpa_ctrl_open(global->ctrl_iface->sock_pair[0]); if (global_ctrl_conn == NULL) { - wpa_printf(MSG_ERROR, "Failed to open global control connection to " - "%d - %s", global->ctrl_iface->sock_pair[0], - strerror(errno)); + wpa_printf(MSG_ERROR, "Failed to open global control connection to %d", + global->ctrl_iface->sock_pair[0]); return -1; } From 4e39fa3f90a0f7ae34ff48d7526d160191c474a3 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sat, 4 Feb 2023 22:23:09 +0530 Subject: [PATCH 098/150] Reduce control interface stack size With the limited messages we expose 1024 should be enough, this reduces the overall stack size. Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h index 79135db459..e0440e853d 100644 --- a/wpa_supplicant/ctrl_iface.h +++ b/wpa_supplicant/ctrl_iface.h @@ -12,7 +12,12 @@ #ifdef CONFIG_CTRL_IFACE #ifndef CTRL_IFACE_MAX_LEN +#ifdef CONFIG_ZEPHYR +#define CTRL_IFACE_MAX_LEN 1024 +#else #define CTRL_IFACE_MAX_LEN 4096 +#endif /* CONFIG_ZEPHYR */ + #endif /* CTRL_IFACE_MAX_LEN */ /* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ From eca80cce4a13e992182886fd2f98668452b5f8a5 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Sun, 5 Feb 2023 00:56:37 +0530 Subject: [PATCH 099/150] Implement channel in connect command When switching to control interface, the code to configure channel from user to WPA supplicant has been removed, use the control interface to configure the channel. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 24681b363c..1b8c1b6b9a 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -115,6 +115,26 @@ static inline void wpa_supp_restart_status_work(void) K_MSEC(10)); } +static inline int chan_to_freq(int chan) +{ + /* We use global channel list here and also use the widest + * op_class for 5GHz channels as there is no user input + * for these (yet). + */ + int freq = ieee80211_chan_to_freq(NULL, 81, chan); + + if (freq <= 0) { + freq = ieee80211_chan_to_freq(NULL, 128, chan); + } + + if (freq <= 0) { + wpa_printf(MSG_ERROR, "Invalid channel %d", chan); + return -1; + } + + return freq; +} + int z_wpa_supplicant_connect(const struct device *dev, struct wifi_connect_req_params *params) @@ -181,8 +201,17 @@ int z_wpa_supplicant_connect(const struct device *dev, /* enable and select network */ z_wpa_cli_cmd_v("enable_network %d", resp.network_id); - z_wpa_cli_cmd_v("select_network %d", resp.network_id); + if (params->channel != WIFI_CHANNEL_ANY) { + int freq = chan_to_freq(params->channel); + if (freq < 0) { + ret = -1; + goto out; + } + z_wpa_cli_cmd_v("set_network %d scan_freq %d", + resp.network_id, freq); + } + z_wpa_cli_cmd_v("select_network %d", resp.network_id); wpa_supp_api_ctrl.dev = dev; wpa_supp_api_ctrl.requested_op = CONNECT; wpa_supp_api_ctrl.connection_timeout = params->timeout; From d4d68457a5fed0e14592038c84036a9af3a7ec53 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Mon, 6 Feb 2023 23:19:16 +0530 Subject: [PATCH 100/150] Removed unused prototype This was missed in cleaning up old interface. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 1 - 1 file changed, 1 deletion(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 1b8c1b6b9a..3b6249451d 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -19,7 +19,6 @@ #include "supp_api.h" #include "wpa_cli_zephyr.h" -int cli_main(int, const char **); extern struct k_sem wpa_supplicant_ready_sem; extern struct wpa_global *global; From e0ff634793590512b88fbbc36910e24b244df16a Mon Sep 17 00:00:00 2001 From: Krishna T Date: Mon, 6 Feb 2023 23:24:41 +0530 Subject: [PATCH 101/150] Check return value All these WPA cli command invocations need to be checked for return value to catch issues early. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 3b6249451d..affff49d4f 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -38,6 +38,14 @@ enum status_thread_state { #define CONNECTION_FAILURE 1 #define CONNECTION_TERMINATED 2 +#define _wpa_cli_cmd_v(cmd, ...) \ + do { \ + if (z_wpa_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \ + wpa_printf(MSG_ERROR, "Failed to execute wpa_cli command: %s", cmd); \ + goto out; \ + } \ + } while (0) + K_MUTEX_DEFINE(wpa_supplicant_mutex); @@ -84,7 +92,7 @@ static void supp_shell_connect_status(struct k_work *work) if (ctrl->requested_op == CONNECT && wpa_s->wpa_state != WPA_COMPLETED) { if (ctrl->connection_timeout > 0 && seconds_counter++ > ctrl->connection_timeout) { - z_wpa_cli_cmd_v("disconnect"); + _wpa_cli_cmd_v("disconnect"); status = CONNECTION_FAILURE; goto out; } @@ -156,7 +164,7 @@ int z_wpa_supplicant_connect(const struct device *dev, goto out; } - z_wpa_cli_cmd_v("remove_network all"); + _wpa_cli_cmd_v("remove_network all"); ret = z_wpa_ctrl_add_network(&resp); if (ret) { goto out; @@ -164,41 +172,41 @@ int z_wpa_supplicant_connect(const struct device *dev, wpa_printf(MSG_DEBUG, "NET added: %d\n", resp.network_id); - z_wpa_cli_cmd_v("set_network %d ssid \"%s\"", resp.network_id, params->ssid); - z_wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id); - z_wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id); + _wpa_cli_cmd_v("set_network %d ssid \"%s\"", resp.network_id, params->ssid); + _wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id); + _wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id); if (params->psk) { /* WPA3 */ if (params->security == 3) { if (params->sae_password) { - z_wpa_cli_cmd_v("set_network %d sae_password \"%s\"", + _wpa_cli_cmd_v("set_network %d sae_password \"%s\"", resp.network_id, params->sae_password); } else { - z_wpa_cli_cmd_v("set_network %d sae_password \"%s\"", + _wpa_cli_cmd_v("set_network %d sae_password \"%s\"", resp.network_id, params->psk); } - z_wpa_cli_cmd_v("set_network %d key_mgmt SAE", + _wpa_cli_cmd_v("set_network %d key_mgmt SAE", resp.network_id); } else if (params->security == 2) { - z_wpa_cli_cmd_v("set_network %d psk \"%s\"", + _wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id, params->psk); - z_wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256", + _wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256", resp.network_id); } else { - z_wpa_cli_cmd_v( "set_network %d psk \"%s\"", + _wpa_cli_cmd_v( "set_network %d psk \"%s\"", resp.network_id, params->psk); - z_wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK", + _wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK", resp.network_id); } if (params->mfp) { - z_wpa_cli_cmd_v("set_network %d ieee80211w %d", + _wpa_cli_cmd_v("set_network %d ieee80211w %d", resp.network_id, params->mfp); } } /* enable and select network */ - z_wpa_cli_cmd_v("enable_network %d", resp.network_id); + _wpa_cli_cmd_v("enable_network %d", resp.network_id); if (params->channel != WIFI_CHANNEL_ANY) { int freq = chan_to_freq(params->channel); @@ -209,6 +217,7 @@ int z_wpa_supplicant_connect(const struct device *dev, z_wpa_cli_cmd_v("set_network %d scan_freq %d", resp.network_id, freq); } + _wpa_cli_cmd_v("select_network %d", resp.network_id); z_wpa_cli_cmd_v("select_network %d", resp.network_id); wpa_supp_api_ctrl.dev = dev; @@ -239,7 +248,7 @@ int z_wpa_supplicant_disconnect(const struct device *dev) } wpa_supp_api_ctrl.dev = dev; wpa_supp_api_ctrl.requested_op = DISCONNECT; - z_wpa_cli_cmd_v("disconnect"); + _wpa_cli_cmd_v("disconnect"); out: k_mutex_unlock(&wpa_supplicant_mutex); From d02ac2f1f0c449c94d881079a3cfd4b4c6e5a4ba Mon Sep 17 00:00:00 2001 From: Krishna T Date: Mon, 6 Feb 2023 23:27:52 +0530 Subject: [PATCH 102/150] Fix the printf Use proper API to print it out. Signed-off-by: Krishna T --- wpa_supplicant/wpa_cli_cmds.c | 3 ++- wpa_supplicant/wpa_cli_zephyr.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/wpa_cli_cmds.c b/wpa_supplicant/wpa_cli_cmds.c index 117461b46f..abecced0fc 100644 --- a/wpa_supplicant/wpa_cli_cmds.c +++ b/wpa_supplicant/wpa_cli_cmds.c @@ -49,7 +49,8 @@ static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, } buf = os_zalloc(sizeof(char) * CMD_BUF_LEN); if (!buf){ - printf ("Failed to allocate mem for command buf\n"); + wpa_printf(MSG_ERROR, "Failed to allocate mem for command buf - %d\n", + CMD_BUF_LEN); return -1; } memset(buf, '\0', CMD_BUF_LEN); diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c index 550b6f0f26..aa32076531 100644 --- a/wpa_supplicant/wpa_cli_zephyr.c +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -46,7 +46,7 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print, int ret; if (ctrl_conn == NULL && global_ctrl_conn == NULL) { - printf("Not connected to wpa_supplicant - command dropped.\n"); + wpa_printf(MSG_ERROR, "Not connected to wpa_supplicant - command dropped.\n"); return -1; } if (ifname_prefix) { @@ -59,10 +59,10 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print, ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, wpa_cli_msg_cb); if (ret == -2) { - printf("'%s' command timed out.\n", cmd); + wpa_printf(MSG_ERROR, "'%s' command timed out.\n", cmd); return -2; } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); + wpa_printf(MSG_ERROR, "'%s' command failed.\n", cmd); return -1; } From aa41230ec27d6255f27016c4068288d44c47e55f Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 7 Feb 2023 02:42:00 +0530 Subject: [PATCH 103/150] Improve the security check * Check for security instead of assuming psk means security (Handy in test for switching b/w PSK and None). * Use Enums and remove comments. * Specifically check for PSK. * Throw error if not matching any. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index affff49d4f..2fe1e86f6b 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -175,9 +175,8 @@ int z_wpa_supplicant_connect(const struct device *dev, _wpa_cli_cmd_v("set_network %d ssid \"%s\"", resp.network_id, params->ssid); _wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id); _wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id); - if (params->psk) { - /* WPA3 */ - if (params->security == 3) { + if (params->security != WIFI_SECURITY_TYPE_NONE) { + if (params->security == WIFI_SECURITY_TYPE_SAE) { if (params->sae_password) { _wpa_cli_cmd_v("set_network %d sae_password \"%s\"", resp.network_id, params->sae_password); @@ -187,16 +186,21 @@ int z_wpa_supplicant_connect(const struct device *dev, } _wpa_cli_cmd_v("set_network %d key_mgmt SAE", resp.network_id); - } else if (params->security == 2) { + } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) { _wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id, params->psk); _wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK-SHA256", resp.network_id); - } else { + } else if (params->security == WIFI_SECURITY_TYPE_PSK) { _wpa_cli_cmd_v( "set_network %d psk \"%s\"", resp.network_id, params->psk); _wpa_cli_cmd_v("set_network %d key_mgmt WPA-PSK", resp.network_id); + } else { + ret = -1; + wpa_printf(MSG_ERROR, "Unsupported security type: %d", + params->security); + goto out; } if (params->mfp) { From af0d09d205949c89401c6e471e1bbd944e64fe8b Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 7 Feb 2023 13:46:21 +0530 Subject: [PATCH 104/150] Fix socketpair size for control interface Now that we are using control interface as the primary communications this is applicable for all. Signed-off-by: Krishna T --- zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 312f37015b..56a1e9e5fd 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -77,7 +77,7 @@ config WPA_CLI default n config NET_SOCKETPAIR_BUFFER_SIZE - default 4096 if WPA_CLI + default 4096 config POSIX_MAX_FDS # l2_packet - 1 From bb6dbb3ef33f723685ed8be6c85c69c3db7fcc8f Mon Sep 17 00:00:00 2001 From: Krishna T Date: Wed, 8 Feb 2023 20:52:23 +0530 Subject: [PATCH 105/150] Indent using tabs Signed-off-by: Krishna T --- zephyr/src/supp_events.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/zephyr/src/supp_events.c b/zephyr/src/supp_events.c index d2bddd50f4..36af436146 100644 --- a/zephyr/src/supp_events.c +++ b/zephyr/src/supp_events.c @@ -5,25 +5,25 @@ int send_wifi_mgmt_event(const char *ifname, enum net_event_wifi_cmd event, int status) { - const struct device *dev = device_get_binding(ifname); - struct net_if *iface = net_if_lookup_by_dev(dev); + const struct device *dev = device_get_binding(ifname); + struct net_if *iface = net_if_lookup_by_dev(dev); - if (!iface) { - wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname); - return -ENODEV; - } + if (!iface) { + wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname); + return -ENODEV; + } - switch (event) { - case NET_EVENT_WIFI_CMD_CONNECT_RESULT: - wifi_mgmt_raise_connect_result_event(iface, status); - break; - case NET_EVENT_WIFI_CMD_DISCONNECT_RESULT: - wifi_mgmt_raise_disconnect_result_event(iface, status); - break; - default: - wpa_printf(MSG_ERROR, "Unsupported event %d", event); - return -EINVAL; - } + switch (event) { + case NET_EVENT_WIFI_CMD_CONNECT_RESULT: + wifi_mgmt_raise_connect_result_event(iface, status); + break; + case NET_EVENT_WIFI_CMD_DISCONNECT_RESULT: + wifi_mgmt_raise_disconnect_result_event(iface, status); + break; + default: + wpa_printf(MSG_ERROR, "Unsupported event %d", event); + return -EINVAL; + } - return 0; + return 0; } From 20ebeeffbdc617a3447c28e62754e3a882f7eb55 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Wed, 8 Feb 2023 21:40:56 +0530 Subject: [PATCH 106/150] Increase network management stack size This is needed esp. for "wifi status" as that makes a call all the way to Driver, and if its called from network management thread then more stack is needed. Signed-off-by: Krishna T --- zephyr/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 56a1e9e5fd..469938f5e5 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -85,6 +85,11 @@ config POSIX_MAX_FDS # z_wpa_event_sock - 1 socketpair = 2 default 7 if !POSIX_API +# Control interface is stack heavy (buffers + snprintfs) +# Making calls to RPU from net_mgmt callbacks (status - RSSI) +config NET_MGMT_EVENT_STACK_SIZE + default 4096 + module = WPA_SUPP module-str = WPA supplicant source "subsys/logging/Kconfig.template.log_config" From fa53e2c5aa660199fc306eaffc5374e276139079 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Wed, 8 Feb 2023 00:50:18 +0530 Subject: [PATCH 107/150] Mark Wi-Fi supported for nRF7002DK EK support is still experimental. Signed-off-by: Krishna T --- zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 469938f5e5..f1818c5251 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -12,7 +12,7 @@ config WPA_SUPP select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT - select EXPERIMENTAL + select EXPERIMENTAL if !SOC_NRF5340_CPUAPP_QKAA help WPA supplicant implements 802.1X related functions. From 4240dc1f37c2af7f83aedf77ab909df2476c5b37 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Mon, 13 Feb 2023 19:14:59 +0530 Subject: [PATCH 108/150] Configure maximum polling sockets The minimum requirement for WPA supplicant is 4. Signed-off-by: Krishna T --- zephyr/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index f1818c5251..b064ee8ad4 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -90,6 +90,9 @@ config POSIX_MAX_FDS config NET_MGMT_EVENT_STACK_SIZE default 4096 +config NET_SOCKETS_POLL_MAX + default 4 + module = WPA_SUPP module-str = WPA supplicant source "subsys/logging/Kconfig.template.log_config" From dd71da381783bd7451e41277b11b7120362491fe Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Tue, 14 Feb 2023 10:46:06 +0530 Subject: [PATCH 109/150] Get extended capabilities from driver SHEL-1269: Multiple BSSID bit is not set in Association request Implement get_ext_capab op to get MBSSID support cap. info Signed-off-by: Sridhar Nuvusetty --- src/drivers/driver_nl80211.h | 4 ++-- src/drivers/driver_zephyr.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 80d4564721..597a926ea4 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -105,10 +105,10 @@ struct wpa_driver_nl80211_data { u8 *extended_capa, *extended_capa_mask; unsigned int extended_capa_len; struct drv_nl80211_ext_capa { - enum nl80211_iftype iftype; + enum nrf_wifi_iftype iftype; u8 *ext_capa, *ext_capa_mask; unsigned int ext_capa_len; - } iface_ext_capa[NL80211_IFTYPE_MAX]; + } iface_ext_capa[NRF_WIFI_IFTYPE_MAX]; unsigned int num_iface_ext_capa; int has_capability; diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index c8b35b0155..1b9a5582da 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -1296,7 +1296,21 @@ static int wpa_drv_zep_send_action(void *priv, unsigned int freq, wait_time, 0); } +static int nl80211_get_ext_capab(void *priv, enum wpa_driver_if_type type, + const u8 **ext_capa, const u8 **ext_capa_mask, + unsigned int *ext_capa_len) +{ + struct wpa_driver_capa capa; + + wpa_drv_zep_get_capa(priv, &capa); + + /* By default, use the per-radio values */ + *ext_capa = capa.extended_capa; + *ext_capa_mask = capa.extended_capa_mask; + *ext_capa_len = capa.extended_capa_len; + return 0; +} const struct wpa_driver_ops wpa_driver_zep_ops = { .name = "zephyr", @@ -1319,4 +1333,5 @@ const struct wpa_driver_ops wpa_driver_zep_ops = { .signal_poll = wpa_drv_zep_signal_poll, .send_action = wpa_drv_zep_send_action, .get_hw_feature_data = wpa_drv_get_hw_feature_data, + .get_ext_capab = nl80211_get_ext_capab, }; From 3dc8b0e1b93e419b48bce89f3838235e44edf300 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 14 Feb 2023 00:22:27 +0530 Subject: [PATCH 110/150] Don't print non-output statuses Skip printing OK/FAIL. Signed-off-by: Krishna T --- wpa_supplicant/wpa_cli_zephyr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c index aa32076531..f397994cd4 100644 --- a/wpa_supplicant/wpa_cli_zephyr.c +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -71,6 +71,15 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print, os_memcpy(resp, buf, len - 1); } +#ifndef CONFIG_WPA_CLI + /* This is not interactive */ + if (os_strncmp(buf, "OK\n", len) == 0 || + os_strncmp(buf, "FAIL\n", len) == 0) + { + print = 0; + } +#endif + if (print) { buf[len] = '\0'; printf("%s", buf); From 8d3f26d7da1b49815fbd0fe8335189cfac4ded85 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 14 Feb 2023 00:27:30 +0530 Subject: [PATCH 111/150] Fix the indent Signed-off-by: Krishna T --- wpa_supplicant/wpa_cli_zephyr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_cli_zephyr.c b/wpa_supplicant/wpa_cli_zephyr.c index f397994cd4..9b42170237 100644 --- a/wpa_supplicant/wpa_cli_zephyr.c +++ b/wpa_supplicant/wpa_cli_zephyr.c @@ -81,8 +81,8 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print, #endif if (print) { - buf[len] = '\0'; - printf("%s", buf); + buf[len] = '\0'; + printf("%s", buf); } return 0; } From 4ccdf0537669e861d97b157bc8c73c2d234c02f6 Mon Sep 17 00:00:00 2001 From: krishna T Date: Wed, 15 Feb 2023 02:21:48 +0530 Subject: [PATCH 112/150] Add assert for minimum libc HEAP This is to catch any RAM limitations early. Signed-off-by: Krishna T --- zephyr/Kconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index b064ee8ad4..e202444336 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -12,12 +12,26 @@ config WPA_SUPP select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT + # For newlib min HEAP check, NCS_SAMPLE_DEFAULTS doesn't print assert information + select LOG_DEFAULT_MINIMAL + select ASSERT + select ASSERT_VERBOSE + # Without this reset on fatal error is triggered + select DEBUG + ### select EXPERIMENTAL if !SOC_NRF5340_CPUAPP_QKAA help WPA supplicant implements 802.1X related functions. if WPA_SUPP +# For asserts, this avoids continuous reset +config RESET_ON_FATAL_ERROR + default n + +config NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE + default 30720 + config WPA_SUPP_THREAD_STACK_SIZE int "Stack size for wpa_supplicant thread" default 8192 From ed721462c7bb565dfab177f935d5f89fbdc9301d Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 20 Feb 2023 13:36:02 +0530 Subject: [PATCH 113/150] Revert "Add assert for minimum libc HEAP" This reverts commit 4ccdf0537669e861d97b157bc8c73c2d234c02f6. --- zephyr/Kconfig | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e202444336..b064ee8ad4 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -12,26 +12,12 @@ config WPA_SUPP select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT - # For newlib min HEAP check, NCS_SAMPLE_DEFAULTS doesn't print assert information - select LOG_DEFAULT_MINIMAL - select ASSERT - select ASSERT_VERBOSE - # Without this reset on fatal error is triggered - select DEBUG - ### select EXPERIMENTAL if !SOC_NRF5340_CPUAPP_QKAA help WPA supplicant implements 802.1X related functions. if WPA_SUPP -# For asserts, this avoids continuous reset -config RESET_ON_FATAL_ERROR - default n - -config NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE - default 30720 - config WPA_SUPP_THREAD_STACK_SIZE int "Stack size for wpa_supplicant thread" default 8192 From bdc51f53d418d5ace1db87ca3016103df3516612 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 16 Feb 2023 13:40:07 +0530 Subject: [PATCH 114/150] Remove commented code Zephyr now implements proper control interface code, so, remove the hack. Signed-off-by: Krishna T --- wpa_supplicant/wpa_supplicant.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 133d9da131..82045cffab 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6998,10 +6998,9 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, if (terminate) wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); -#ifndef CONFIG_ZEPHYR + wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface); wpa_s->ctrl_iface = NULL; -#endif #ifdef CONFIG_MESH if (wpa_s->ifmsh) { From 8ef422879444870f1a8e0e2c24fa73ceeee7e3d4 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 16 Feb 2023 14:02:19 +0530 Subject: [PATCH 115/150] Protect events with a mutex In case multiple threads use this to post events to WPA supplicant. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index e07eafba1e..e63eec5f57 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -66,6 +66,7 @@ static struct k_work_q z_wpas_iface_wq; static K_WORK_DEFINE(z_wpas_iface_work, z_wpas_iface_work_handler); +K_MUTEX_DEFINE(z_wpas_event_mutex); #ifdef CONFIG_MATCH_IFACE static int z_wpas_init_match(struct wpa_global *global) @@ -290,8 +291,10 @@ int z_wpas_send_event(const struct wpa_supplicant_event_msg *msg) int ret; unsigned int retry = 0; + k_mutex_lock(&z_wpas_event_mutex, K_FOREVER); + if (z_wpas_event_sockpair[1] < 0) { - return -1; + goto err; } retry_send: @@ -304,16 +307,19 @@ int z_wpas_send_event(const struct wpa_supplicant_event_msg *msg) } else { wpa_printf(MSG_WARNING, "Dummy socket send fail (max retries): %s", strerror(errno)); - return -1; + goto err; } } else { wpa_printf(MSG_WARNING, "Dummy socket send fail: %s", strerror(errno)); - return -1; + goto err; } } - return 0; + ret = 0; +err: + k_mutex_unlock(&z_wpas_event_mutex); + return -1; } static void z_wpas_start(void) From d378cd16fb49a42e7adabe13943ede3cf4a83ef5 Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 16 Feb 2023 14:11:16 +0530 Subject: [PATCH 116/150] Remove the dummy socket This is now obsolete as we implement full fledged control interface. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 8 ++------ zephyr/src/supp_main.h | 2 -- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index e63eec5f57..198e293e5d 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -257,10 +257,6 @@ static void z_wpas_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) return; } - if (msg.ignore_msg) { - return; - } - wpa_printf(MSG_DEBUG, "Passing message %d to wpa_supplicant", msg.event); wpa_supplicant_event(msg.ctx, msg.event, msg.data); @@ -305,12 +301,12 @@ int z_wpas_send_event(const struct wpa_supplicant_event_msg *msg) if (retry++ < 3) { goto retry_send; } else { - wpa_printf(MSG_WARNING, "Dummy socket send fail (max retries): %s", + wpa_printf(MSG_WARNING, "Event send fail (max retries): %s", strerror(errno)); goto err; } } else { - wpa_printf(MSG_WARNING, "Dummy socket send fail: %s", + wpa_printf(MSG_WARNING, "Event send fail: %s", strerror(errno)); goto err; } diff --git a/zephyr/src/supp_main.h b/zephyr/src/supp_main.h index 447e41077e..2d38432d0c 100644 --- a/zephyr/src/supp_main.h +++ b/zephyr/src/supp_main.h @@ -10,8 +10,6 @@ struct wpa_supplicant *z_wpas_get_handle_by_ifname(const char* ifname); struct wpa_supplicant_event_msg { - /* Dummy messages to unblock select */ - bool ignore_msg; void *ctx; unsigned int event; void *data; From 418cc2edfcc9f15028e3505a0411e5fcef24b6ee Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 16 Feb 2023 15:39:30 +0530 Subject: [PATCH 117/150] Add global event support For handling interface events they need to go through global control interface. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 6 +++++- zephyr/src/supp_main.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 198e293e5d..30ec73b5c8 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -259,7 +259,11 @@ static void z_wpas_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) wpa_printf(MSG_DEBUG, "Passing message %d to wpa_supplicant", msg.event); - wpa_supplicant_event(msg.ctx, msg.event, msg.data); + if (msg.global) { + wpa_supplicant_event_global(msg.ctx, msg.event, msg.data); + } else { + wpa_supplicant_event(msg.ctx, msg.event, msg.data); + } if (msg.data) { os_free(msg.data); diff --git a/zephyr/src/supp_main.h b/zephyr/src/supp_main.h index 2d38432d0c..d7bd862b27 100644 --- a/zephyr/src/supp_main.h +++ b/zephyr/src/supp_main.h @@ -10,6 +10,7 @@ struct wpa_supplicant *z_wpas_get_handle_by_ifname(const char* ifname); struct wpa_supplicant_event_msg { + bool global; void *ctx; unsigned int event; void *data; From 6530ef40f2ae5f4ab2ae70a2765c677fd47a2a97 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 17 Feb 2023 02:23:40 +0530 Subject: [PATCH 118/150] Close the L2 packet socket Signed-off-by: Krishna T --- src/l2_packet/l2_packet_zephyr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index 43018e14e9..eda315be5e 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -211,7 +211,7 @@ void l2_packet_deinit(struct l2_packet_data *l2) if (l2->fd >= 0) { eloop_unregister_read_sock(l2->fd); - /* TODO: close connection */ + close(l2->fd); } os_free(l2); From 3c38b724f0b4d8d2a9d3126c396b7e627dca1de1 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 17 Feb 2023 02:24:21 +0530 Subject: [PATCH 119/150] Add debugs in global interface * Entry point * Memory allocation failure Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface_zephyr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/ctrl_iface_zephyr.c b/wpa_supplicant/ctrl_iface_zephyr.c index 6b902a3dce..d17c73b704 100644 --- a/wpa_supplicant/ctrl_iface_zephyr.c +++ b/wpa_supplicant/ctrl_iface_zephyr.c @@ -132,9 +132,13 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, char *reply = NULL; size_t reply_len = 0; + wpa_printf(MSG_DEBUG, "Global ctrl_iface received"); + buf = os_zalloc(CTRL_IFACE_MAX_LEN + 1); - if (!buf) + if (!buf) { + wpa_printf(MSG_ERROR, "Global ctrl_iface: no memory"); return; + } res = recv(sock, buf, CTRL_IFACE_MAX_LEN, 0); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", From e2407fae24a408e0575ce12851c675b02debbffc Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 17 Feb 2023 02:25:01 +0530 Subject: [PATCH 120/150] Fix a typo Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 30ec73b5c8..fb652855c5 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -252,7 +252,7 @@ static void z_wpas_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) } if (ret != sizeof(msg)) { - wpa_printf(MSG_ERROR, "Recieved incomplete message: got: %d, expected:%d", + wpa_printf(MSG_ERROR, "Received incomplete message: got: %d, expected:%d", ret, sizeof(msg)); return; } From 9b77f004c8a78993a3095cc6c1a3e8265c3447fc Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 16 Feb 2023 16:08:38 +0530 Subject: [PATCH 121/150] Notify WPA supplicant before removing interface This disables all further processing in the WPA supplicant before we remove the interface. Also, add a check after interface add/remove to make sure it worked before proceeding ahead. Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 50 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index fb652855c5..182ead4ae9 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -122,10 +122,17 @@ static int z_wpas_get_iface_count(void) return count; } +#define Z_WPA_S_IFACE_NOTIFY_TIMEOUT_MS 1000 +#define Z_WPA_S_IFACE_NOTIFY_RETRY_MS 10 + static int z_wpas_add_interface(const char* ifname) { struct wpa_supplicant *wpa_s; int ret; + union wpa_event_data *event; + int retry = 0, count = Z_WPA_S_IFACE_NOTIFY_TIMEOUT_MS / Z_WPA_S_IFACE_NOTIFY_RETRY_MS; + + wpa_printf(MSG_DEBUG, "Adding interface %s\n", ifname); ret = z_wpa_cli_global_cmd_v("interface_add %s %s %s %s", ifname, "zephyr", "zephyr", "zephyr"); @@ -135,6 +142,10 @@ static int z_wpas_add_interface(const char* ifname) } /* This cannot be through control interface as need the handle */ + while (retry ++ < count && !wpa_supplicant_get_iface(global, ifname)) { + k_sleep(K_MSEC(Z_WPA_S_IFACE_NOTIFY_RETRY_MS)); + } + wpa_s = wpa_supplicant_get_iface(global, ifname); if (wpa_s == NULL) { wpa_printf(MSG_ERROR, "Failed to add iface: %s", ifname); @@ -156,12 +167,47 @@ static int z_wpas_add_interface(const char* ifname) static int z_wpas_remove_interface(const char* ifname) { int ret; + union wpa_event_data *event = os_zalloc(sizeof(*event)); + struct wpa_supplicant *wpa_s = wpa_supplicant_get_iface(global, ifname); + int retry = 0, count = Z_WPA_S_IFACE_NOTIFY_TIMEOUT_MS / Z_WPA_S_IFACE_NOTIFY_RETRY_MS; + + if (!event) { + wpa_printf(MSG_ERROR, "Failed to allocate event data"); + return -1; + } + + if (!wpa_s) { + wpa_printf(MSG_ERROR, "Failed to get wpa_s handle for %s", ifname); + return -1; + } + + wpa_printf(MSG_DEBUG, "Remove interface %s\n", ifname); + + os_memcpy(event->interface_status.ifname, ifname, IFNAMSIZ); + event->interface_status.ievent = EVENT_INTERFACE_REMOVED; + + struct wpa_supplicant_event_msg msg = { + .global = true, + .ctx = global, + .event = EVENT_INTERFACE_STATUS, + .data = event, + }; + + z_wpas_send_event(&msg); - wpa_printf(MSG_INFO, "Remove interface %s\n", ifname); + while (retry++ < count && + wpa_s->wpa_state != WPA_INTERFACE_DISABLED) { + k_sleep(K_MSEC(Z_WPA_S_IFACE_NOTIFY_RETRY_MS)); + } + + if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) { + wpa_printf(MSG_ERROR, "Failed to notify remove interface: %s", ifname); + return -1; + } ret = z_wpa_cli_global_cmd_v("interface_remove %s", ifname); if (ret) { - wpa_printf(MSG_ERROR, "Failed to add interface: %s", ifname); + wpa_printf(MSG_ERROR, "Failed to remove interface: %s", ifname); return -1; } From 9d2af8bac4cd8e92392e5b957d45e56e2985cfd3 Mon Sep 17 00:00:00 2001 From: krishna T Date: Sun, 19 Feb 2023 01:28:05 +0530 Subject: [PATCH 122/150] Fix control interface socket close We register Socket 1 to Eloop, so, socket 1 should be closed. Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface_zephyr.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/wpa_supplicant/ctrl_iface_zephyr.c b/wpa_supplicant/ctrl_iface_zephyr.c index d17c73b704..d3b9f07c33 100644 --- a/wpa_supplicant/ctrl_iface_zephyr.c +++ b/wpa_supplicant/ctrl_iface_zephyr.c @@ -104,14 +104,14 @@ void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s, if (!priv) return; - if (priv->sock_pair[0] > -1) { - eloop_unregister_read_sock(priv->sock_pair[0]); - close(priv->sock_pair[0]); - priv->sock_pair[0] = -1; + if (priv->sock_pair[1] > -1) { + eloop_unregister_read_sock(priv->sock_pair[1]); + close(priv->sock_pair[1]); + priv->sock_pair[1] = -1; } - if (priv->sock_pair[1] >= 0) - close(priv->sock_pair[1]); + if (priv->sock_pair[0] >= 0) + close(priv->sock_pair[0]); os_free(priv); } @@ -217,14 +217,14 @@ wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) if (!priv) return; - if (priv->sock_pair[0] > -1) { - eloop_unregister_read_sock(priv->sock_pair[0]); - close(priv->sock_pair[0]); - priv->sock_pair[0] = -1; + if (priv->sock_pair[1] > -1) { + eloop_unregister_read_sock(priv->sock_pair[1]); + close(priv->sock_pair[1]); + priv->sock_pair[1] = -1; } - if (priv->sock_pair[1] >= 0) - close(priv->sock_pair[1]); + if (priv->sock_pair[0] >= 0) + close(priv->sock_pair[0]); os_free(priv); } From df5157bd402846c3bfbed88b1b88f6bf476eb667 Mon Sep 17 00:00:00 2001 From: krishna T Date: Sun, 19 Feb 2023 02:14:40 +0530 Subject: [PATCH 123/150] Fix the return value check In case of failure set return value to avoid doing further work. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 2fe1e86f6b..b26edeaf99 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -161,6 +161,7 @@ int z_wpa_supplicant_connect(const struct device *dev, wpa_s = get_wpa_s_handle(dev); if (!wpa_s) { + ret = -1; goto out; } From b48ccf9908613aeffccde22d767cc4b74da253bc Mon Sep 17 00:00:00 2001 From: krishna T Date: Sun, 19 Feb 2023 02:32:48 +0530 Subject: [PATCH 124/150] Remove unnecessary Zephyr define This is file is not even included in build. Signed-off-by: Krishna T --- wpa_supplicant/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index ad73300125..51a8a0298a 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -199,7 +199,6 @@ int main(int argc, char *argv[]) wpa_supplicant_fd_workaround(1); -#ifndef CONFIG_ZEPHYR //TODO: use shell_getopt in zephyr for (;;) { c = getopt(argc, argv, "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); @@ -338,7 +337,6 @@ int main(int argc, char *argv[]) goto out; } } -#endif exitcode = 0; global = wpa_supplicant_init(¶ms); From 75c41458fbfc5042674bb5f4eb7da02859300927 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 20 Feb 2023 03:53:51 +0530 Subject: [PATCH 125/150] Decrease logs These are mainly for debugging, so, use DEBUG macro. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 2 +- src/l2_packet/l2_packet_zephyr.c | 2 +- zephyr/src/supp_main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 1b9a5582da..c976f22321 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -1181,7 +1181,7 @@ static int wpa_drv_zep_get_ssid(void *priv, if_ctx = priv; - wpa_printf(MSG_INFO, + wpa_printf(MSG_DEBUG, "%s: SSID size: %d\n", __func__, if_ctx->ssid_len); diff --git a/src/l2_packet/l2_packet_zephyr.c b/src/l2_packet/l2_packet_zephyr.c index eda315be5e..a22c7d050d 100644 --- a/src/l2_packet/l2_packet_zephyr.c +++ b/src/l2_packet/l2_packet_zephyr.c @@ -180,7 +180,7 @@ l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol, eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); } - wpa_printf(MSG_INFO, "l2_packet_init: iface %s ifindex %d", l2->ifname, + wpa_printf(MSG_DEBUG, "l2_packet_init: iface %s ifindex %d", l2->ifname, l2->ifindex); return l2; diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 182ead4ae9..b3dfd082d3 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -219,7 +219,7 @@ static void iface_event_handler(struct net_mgmt_event_callback *cb, { const char *ifname = iface->if_dev->dev->name; - wpa_printf(MSG_INFO, "Event: %d", mgmt_event); + wpa_printf(MSG_DEBUG, "Event: %d", mgmt_event); if (mgmt_event == NET_EVENT_IF_ADMIN_UP) { z_wpas_add_interface(ifname); } else if (mgmt_event == NET_EVENT_IF_ADMIN_DOWN) { From 1ab4c963fa49bd1dbc57e88727402e4b07f566db Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 20 Feb 2023 15:26:54 +0530 Subject: [PATCH 126/150] Mark nRF9160 as supported This is now fully supported. Signed-off-by: Krishna T --- zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index b064ee8ad4..d2a99c656f 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -12,7 +12,7 @@ config WPA_SUPP select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT - select EXPERIMENTAL if !SOC_NRF5340_CPUAPP_QKAA + select EXPERIMENTAL if !SOC_SERIES_NRF53X && !SOC_SERIES_NRF91X help WPA supplicant implements 802.1X related functions. From d0fe3f71f80e0cfd9685726904df4369d64f5514 Mon Sep 17 00:00:00 2001 From: krishna T Date: Mon, 20 Feb 2023 22:31:03 +0530 Subject: [PATCH 127/150] Fix unused variable warning Signed-off-by: Krishna T --- zephyr/src/supp_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index b3dfd082d3..b32431e571 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -129,7 +129,6 @@ static int z_wpas_add_interface(const char* ifname) { struct wpa_supplicant *wpa_s; int ret; - union wpa_event_data *event; int retry = 0, count = Z_WPA_S_IFACE_NOTIFY_TIMEOUT_MS / Z_WPA_S_IFACE_NOTIFY_RETRY_MS; wpa_printf(MSG_DEBUG, "Adding interface %s\n", ifname); From 90c2e9afc5bca95fe2c1b2718d2ffbe3f1c8ee26 Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Mon, 9 Jan 2023 14:56:35 +0530 Subject: [PATCH 128/150] wifi : Bugfix for RRM request handling SHEL-877: DUT did not respond to AP beacon request frame Enable RRM request/response frame handling. Fix BSS expiration issue. Signed-off-by: Sridhar Nuvusetty --- src/drivers/driver_zephyr.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index c976f22321..4675bd5257 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -507,6 +507,14 @@ static int wpa_drv_mgmt_subscribe_non_ap(struct zep_drv_if_ctx *if_ctx) if (wpa_drv_register_action_frame(if_ctx, (u8 *)"\x0a\x07", 2) < 0) ret = -1; + /* Radio Measurement - Neighbor Report Response */ + if (wpa_drv_register_action_frame(if_ctx, (u8 *)"\x05\x05", 2) < 0) + ret = -1; + + /* Radio Measurement - Radio Measurement Request */ + if (wpa_drv_register_action_frame(if_ctx, (u8 *)"\x05\x00", 2) < 0) + ret = -1; + return ret; } @@ -1127,7 +1135,6 @@ static int wpa_drv_zep_set_key(void* priv, static int wpa_drv_zep_get_capa(void *priv, struct wpa_driver_capa *capa) { - struct zep_drv_if_ctx *if_ctx = NULL; const struct zep_wpa_supp_dev_ops *dev_ops = NULL; int ret = -1; From 954a37928703f4141b07ab5ca5f33cd7fdb35aa7 Mon Sep 17 00:00:00 2001 From: Sridhar Nuvusetty Date: Thu, 9 Feb 2023 11:15:29 +0530 Subject: [PATCH 129/150] wifi : Bugfix for BTM request handling SHEL-859: No BTM response for request from AP Handle deauth during BSS transition Signed-off-by: Sridhar Nuvusetty --- src/drivers/driver_zephyr.c | 39 ++++++++++++++++++++++++++++++++++++- src/drivers/driver_zephyr.h | 7 ++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 4675bd5257..f44802e589 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -186,8 +186,32 @@ void wpa_drv_zep_event_proc_assoc_resp(struct zep_drv_if_ctx *if_ctx, void wpa_drv_zep_event_proc_deauth(struct zep_drv_if_ctx *if_ctx, - union wpa_event_data *event) + union wpa_event_data *event, const struct ieee80211_mgmt *mgmt) { + const u8 *bssid = NULL; + + bssid = mgmt->bssid; + + if ((if_ctx->capa.flags & WPA_DRIVER_FLAGS_SME) && + !if_ctx->associated && + os_memcmp(bssid, if_ctx->auth_bssid, ETH_ALEN) != 0 && + os_memcmp(bssid, if_ctx->auth_attempt_bssid, ETH_ALEN) != 0 && + os_memcmp(bssid, if_ctx->prev_bssid, ETH_ALEN) == 0) + { + /* + * Avoid issues with some roaming cases where + * disconnection event for the old AP may show up after + * we have started connection with the new AP. + * In case of locally generated event clear + * ignore_next_local_deauth as well, to avoid next local + * deauth event be wrongly ignored. + */ + wpa_printf(MSG_DEBUG, + "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR, + MAC2STR(bssid), + MAC2STR(if_ctx->auth_attempt_bssid)); + return; + } wpa_supplicant_event_wrapper(if_ctx->supp_if_ctx, EVENT_DEAUTH, event); @@ -1011,6 +1035,16 @@ static int wpa_drv_zep_authenticate(void *priv, ret = -1; goto out; } + + if (params->bssid) + os_memcpy(if_ctx->auth_attempt_bssid, params->bssid, ETH_ALEN); + + if (if_ctx->associated) + os_memcpy(if_ctx->prev_bssid, if_ctx->bssid, ETH_ALEN); + + os_memset(if_ctx->auth_bssid, 0, ETH_ALEN); + + if_ctx->associated = false; ret = dev_ops->authenticate(if_ctx->dev_priv, params, @@ -1161,6 +1195,9 @@ static int wpa_drv_zep_get_capa(void *priv, } ret = 0; + + if_ctx->capa = *capa; + out: return ret; } diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index ba80237c71..ec76b2023f 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -124,6 +124,11 @@ struct zep_drv_if_ctx { bool associated; void *phy_info_arg; + struct wpa_driver_capa capa; + + unsigned char prev_bssid[6]; + unsigned char auth_bssid[6]; + unsigned char auth_attempt_bssid[6]; }; @@ -143,7 +148,7 @@ struct zep_wpa_supp_dev_callbk_fns { union wpa_event_data *event, unsigned int status); void (*deauth)(struct zep_drv_if_ctx *if_ctx, - union wpa_event_data *event); + union wpa_event_data *event, const struct ieee80211_mgmt *mgmt); void (*disassoc)(struct zep_drv_if_ctx *if_ctx, union wpa_event_data *event); From 73de50a279b35adf345eae35231813d0945991fd Mon Sep 17 00:00:00 2001 From: krishna T Date: Sun, 26 Feb 2023 00:08:11 +0530 Subject: [PATCH 130/150] Fix hidden SSID association Always scan for SSID's to handle hidden SSID case. Signed-off-by: Krishna T --- zephyr/src/supp_api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index b26edeaf99..531e288aaf 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -174,6 +174,7 @@ int z_wpa_supplicant_connect(const struct device *dev, wpa_printf(MSG_DEBUG, "NET added: %d\n", resp.network_id); _wpa_cli_cmd_v("set_network %d ssid \"%s\"", resp.network_id, params->ssid); + _wpa_cli_cmd_v("set_network %d scan_ssid 1", resp.network_id); _wpa_cli_cmd_v("set_network %d key_mgmt NONE", resp.network_id); _wpa_cli_cmd_v("set_network %d ieee80211w 0", resp.network_id); if (params->security != WIFI_SECURITY_TYPE_NONE) { From 6d949b2b1f95d53bc91f798ace564587e0408bd1 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Wed, 8 Mar 2023 12:51:37 +0530 Subject: [PATCH 131/150] Remove base64 utilities These are currently unused in hostap, but conflict with Zephyr's implementation (duplicate function), revisit when this is actually used as the function signatures b/w hostap and Zephyr are different. Signed-off-by: Krishna T --- zephyr/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 7056ff2483..02b6fa84f7 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -62,7 +62,6 @@ zephyr_library_sources( ${COMMON_SRC_BASE}/drivers/drivers.c ${COMMON_SRC_BASE}/l2_packet/l2_packet_zephyr.c ${COMMON_SRC_BASE}/drivers/driver_zephyr.c - ${COMMON_SRC_BASE}/utils/base64.c ${COMMON_SRC_BASE}/utils/common.c ${COMMON_SRC_BASE}/utils/wpabuf.c ${COMMON_SRC_BASE}/utils/bitfield.c From a7c991e1c10b0d42bdb73bea95d1b45b87b7adbd Mon Sep 17 00:00:00 2001 From: Sachin D Kulkarni Date: Wed, 29 Mar 2023 15:19:08 +0530 Subject: [PATCH 132/150] CODEOWNERS: Update owners list Replace @sr1dh48r with @rado17 Signed-off-by: Sachin D Kulkarni --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index d81cb55525..4e3069ec61 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,4 +5,4 @@ # precedence. # Root folder -* @krish2718 @sr1dh48r @rlubos @sachinthegreen +* @krish2718 @rado17 @rlubos @sachinthegreen From e2597a8bd49bc32f7ceabe2112b7ebbd0462bef1 Mon Sep 17 00:00:00 2001 From: Sachin D Kulkarni Date: Wed, 29 Mar 2023 18:13:40 +0530 Subject: [PATCH 133/150] Clean boot log Remove non-essential boot log messages. Signed-off-by: Sachin D Kulkarni --- zephyr/src/supp_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index b32431e571..306b18bab9 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -382,9 +382,6 @@ static void z_wpas_start(void) os_memset(¶ms, 0, sizeof(params)); params.wpa_debug_level = CONFIG_WPA_SUPP_DEBUG_LEVEL; - wpa_printf(MSG_INFO, "%s: %d Starting wpa_supplicant thread with debug level: %d\n", - __func__, __LINE__, params.wpa_debug_level); - exitcode = 0; global = wpa_supplicant_init(¶ms); if (global == NULL) { From 2e02dcd730a307d19cca8e8f36cc82b6b450eab7 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Mon, 10 Apr 2023 22:25:37 +0530 Subject: [PATCH 134/150] Make EAPoL Supplicant separate This is a common modules used by P2P, WPA3 and Enterprise, so, it needs to be enabled with a custom config to avoid re-definitions. Signed-off-by: Ravi Dondaputi --- zephyr/CMakeLists.txt | 17 ++++++++--------- zephyr/Kconfig | 4 ++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 02b6fa84f7..b2e7452fbe 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -239,10 +239,6 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_WPS ${COMMON_SRC_BASE}/wps/wps_dev_attr.c ${COMMON_SRC_BASE}/wps/wps_enrollee.c ${COMMON_SRC_BASE}/wps/wps_registrar.c - ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c - ${COMMON_SRC_BASE}/eap_peer/eap.c - ${COMMON_SRC_BASE}/eap_peer/eap_methods.c - ${COMMON_SRC_BASE}/eap_common/eap_common.c ${COMMON_SRC_BASE}/crypto/dh_groups.c ${COMMON_SRC_BASE}/crypto/dh_group5.c ) @@ -256,17 +252,12 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_P2P zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_WPS CONFIG_WPS CONFIG_EAP_WSC - CONFIG_IEEE8021X_EAPOL ) zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE ${COMMON_SRC_BASE}/eap_peer/eap_tls.c ${COMMON_SRC_BASE}/eap_peer/eap_tls_common.c - ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c - ${COMMON_SRC_BASE}/eap_peer/eap.c - ${COMMON_SRC_BASE}/eap_peer/eap_methods.c - ${COMMON_SRC_BASE}/eap_common/eap_common.c ${COMMON_SRC_BASE}/eap_peer/eap_peap.c ${COMMON_SRC_BASE}/eap_common/eap_peap_common.c @@ -334,4 +325,12 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE CONFIG_EAP_EKE CONFIG_EAP_IKEv2 ) + +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_EAPOL + ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c + ${COMMON_SRC_BASE}/eap_peer/eap.c + ${COMMON_SRC_BASE}/eap_peer/eap_methods.c + ${COMMON_SRC_BASE}/eap_common/eap_common.c +) + endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index d2a99c656f..be2e922314 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -72,6 +72,10 @@ config WPA_SUPP_P2P select WPA_SUPP_AP select WPA_SUPP_WPS +config WPA_SUPP_EAPOL + bool "Enable EAPoL supplicant" + default y if WPA_SUPP_WPA3 || WPA_SUPP_P2P || WPA_SUPP_CRYPTO_ENTERPRISE + config WPA_CLI bool "CLI support for wpa_supplicant" default n From 70eb7647cf78e630c6d5fff512ff1f061e5f20a6 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Mon, 10 Apr 2023 22:26:53 +0530 Subject: [PATCH 135/150] Fix WPA3 PMKSA caching WPA3 also needs to enable PMKSA caching, though the file is included but the define (IEEE8021X_EAPOL) is not passed. Signed-off-by: Ravi Dondaputi --- zephyr/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b2e7452fbe..aa2a93f894 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -172,7 +172,6 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO ${COMMON_SRC_BASE}/common/wpa_common.c ${COMMON_SRC_BASE}/rsn_supp/wpa.c ${COMMON_SRC_BASE}/rsn_supp/preauth.c - ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c ${COMMON_SRC_BASE}/rsn_supp/wpa_ie.c ${COMMON_SRC_BASE}/crypto/crypto_mbedtls-bignum.c @@ -331,6 +330,10 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_EAPOL ${COMMON_SRC_BASE}/eap_peer/eap.c ${COMMON_SRC_BASE}/eap_peer/eap_methods.c ${COMMON_SRC_BASE}/eap_common/eap_common.c + ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c ) +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_EAPOL + IEEE8021X_EAPOL +) endif() From ac88cbf9e97f9864848ba3986c4ef50bd9e198a7 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 28 Mar 2023 20:55:37 +0530 Subject: [PATCH 136/150] Fix build failure with signal API With upstream commit [1] when CONFIG_POSIX_API is enabled then Zephyr's header are included before the `libc` headers causing issues as Zephyr doesn't support POSIX signal implementation. Resolve this by not using POSIX_API and add a negative dependency. [1] - https://github.com/zephyrproject-rtos/zephyr/commit/43110ddb71680db3ddd3411317dbaf0476e298f5 Signed-off-by: Krishna T --- zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index be2e922314..540e02fb79 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -8,7 +8,8 @@ config WPA_SUPP bool "WPA supplicant support" depends on NET_SOCKETS - depends on NET_SOCKETS_POSIX_NAMES || POSIX_API + # Need full POSIX from libc, Zephyr's POSIX support is only partial + depends on !POSIX_API select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT From bdb0ceb98f566375af66bcdf03779959ba8b48a1 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Tue, 28 Mar 2023 21:01:15 +0530 Subject: [PATCH 137/150] Enable POSIX_CLOCK automatically Without this the build fails, so, should be selected automatically rather than relying on the application. Signed-off-by: Krishna T --- zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 540e02fb79..c0091ad145 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -10,6 +10,7 @@ config WPA_SUPP depends on NET_SOCKETS # Need full POSIX from libc, Zephyr's POSIX support is only partial depends on !POSIX_API + select POSIX_CLOCK select NET_SOCKETS_PACKET select NET_SOCKETPAIR select NET_L2_WIFI_MGMT From 672ea37736fdf65f17757bb9ff673bc5add87d4a Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 12 Apr 2023 14:14:26 +0200 Subject: [PATCH 138/150] Revert "Fix WPA3 PMKSA caching" This reverts commit 70eb7647cf78e630c6d5fff512ff1f061e5f20a6. This commit is part of a PR that introduced "section `rodata' will not fit in region `FLASH'" regression to sdk-nrf. Signed-off-by: Johann Fischer --- zephyr/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index aa2a93f894..b2e7452fbe 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -172,6 +172,7 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO ${COMMON_SRC_BASE}/common/wpa_common.c ${COMMON_SRC_BASE}/rsn_supp/wpa.c ${COMMON_SRC_BASE}/rsn_supp/preauth.c + ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c ${COMMON_SRC_BASE}/rsn_supp/wpa_ie.c ${COMMON_SRC_BASE}/crypto/crypto_mbedtls-bignum.c @@ -330,10 +331,6 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_EAPOL ${COMMON_SRC_BASE}/eap_peer/eap.c ${COMMON_SRC_BASE}/eap_peer/eap_methods.c ${COMMON_SRC_BASE}/eap_common/eap_common.c - ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c ) -zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_EAPOL - IEEE8021X_EAPOL -) endif() From a0d06f6e2e9d3dcaa7e23c6dc29cbc33436a02cd Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 12 Apr 2023 14:17:28 +0200 Subject: [PATCH 139/150] Revert "Make EAPoL Supplicant separate" This reverts commit 2e02dcd730a307d19cca8e8f36cc82b6b450eab7. This commit is part of a PR that introduced "section `rodata' will not fit in region `FLASH'" regression to sdk-nrf. Signed-off-by: Johann Fischer --- zephyr/CMakeLists.txt | 17 +++++++++-------- zephyr/Kconfig | 4 ---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b2e7452fbe..02b6fa84f7 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -239,6 +239,10 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_WPS ${COMMON_SRC_BASE}/wps/wps_dev_attr.c ${COMMON_SRC_BASE}/wps/wps_enrollee.c ${COMMON_SRC_BASE}/wps/wps_registrar.c + ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c + ${COMMON_SRC_BASE}/eap_peer/eap.c + ${COMMON_SRC_BASE}/eap_peer/eap_methods.c + ${COMMON_SRC_BASE}/eap_common/eap_common.c ${COMMON_SRC_BASE}/crypto/dh_groups.c ${COMMON_SRC_BASE}/crypto/dh_group5.c ) @@ -252,12 +256,17 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_P2P zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_WPS CONFIG_WPS CONFIG_EAP_WSC + CONFIG_IEEE8021X_EAPOL ) zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE ${COMMON_SRC_BASE}/eap_peer/eap_tls.c ${COMMON_SRC_BASE}/eap_peer/eap_tls_common.c + ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c + ${COMMON_SRC_BASE}/eap_peer/eap.c + ${COMMON_SRC_BASE}/eap_peer/eap_methods.c + ${COMMON_SRC_BASE}/eap_common/eap_common.c ${COMMON_SRC_BASE}/eap_peer/eap_peap.c ${COMMON_SRC_BASE}/eap_common/eap_peap_common.c @@ -325,12 +334,4 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE CONFIG_EAP_EKE CONFIG_EAP_IKEv2 ) - -zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_EAPOL - ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c - ${COMMON_SRC_BASE}/eap_peer/eap.c - ${COMMON_SRC_BASE}/eap_peer/eap_methods.c - ${COMMON_SRC_BASE}/eap_common/eap_common.c -) - endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index c0091ad145..ce4255806d 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -74,10 +74,6 @@ config WPA_SUPP_P2P select WPA_SUPP_AP select WPA_SUPP_WPS -config WPA_SUPP_EAPOL - bool "Enable EAPoL supplicant" - default y if WPA_SUPP_WPA3 || WPA_SUPP_P2P || WPA_SUPP_CRYPTO_ENTERPRISE - config WPA_CLI bool "CLI support for wpa_supplicant" default n From a5b03c432030923779abb2c060988fc5d4ee1253 Mon Sep 17 00:00:00 2001 From: krishna T Date: Fri, 21 Apr 2023 01:10:21 +0530 Subject: [PATCH 140/150] Add support to configure SAE-H2E Before the control interface changes we had added a new command to set the H2E in the WPA supplicant configuration, but this was removed, so, add back the command that can be set through WPA cli. Signed-off-by: Krishna T --- wpa_supplicant/ctrl_iface.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index cd82b2bdb7..c61d919530 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -924,6 +924,17 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, #endif /* CONFIG_WNM */ } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) { wpa_s->enable_dscp_policy_capa = !!atoi(value); +#ifdef CONFIG_SAE + } else if (os_strcasecmp(cmd, "sae_pwe") == 0) { + int pwe = atoi(value); + + if (pwe < 0 || pwe > 2) { + wpa_printf(MSG_ERROR, + "Invalid SAE PWE value %d", pwe); + return -1; + } + wpa_s->conf->sae_pwe = pwe; +#endif /* CONFIG_SAE */ } else { value[-1] = '='; ret = wpa_config_process_global(wpa_s->conf, cmd, -1); From 3462b1e407aabc4cbb016df854a5cd07eface186 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Mon, 10 Apr 2023 22:25:37 +0530 Subject: [PATCH 141/150] Make EAPoL Supplicant separate This is a common modules used by P2P, WPA3 and Enterprise, so, it needs to be enabled with a custom config to avoid re-definitions. Signed-off-by: Ravi Dondaputi --- zephyr/CMakeLists.txt | 17 ++++++++--------- zephyr/Kconfig | 6 +++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 02b6fa84f7..b2e7452fbe 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -239,10 +239,6 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_WPS ${COMMON_SRC_BASE}/wps/wps_dev_attr.c ${COMMON_SRC_BASE}/wps/wps_enrollee.c ${COMMON_SRC_BASE}/wps/wps_registrar.c - ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c - ${COMMON_SRC_BASE}/eap_peer/eap.c - ${COMMON_SRC_BASE}/eap_peer/eap_methods.c - ${COMMON_SRC_BASE}/eap_common/eap_common.c ${COMMON_SRC_BASE}/crypto/dh_groups.c ${COMMON_SRC_BASE}/crypto/dh_group5.c ) @@ -256,17 +252,12 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_P2P zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_WPS CONFIG_WPS CONFIG_EAP_WSC - CONFIG_IEEE8021X_EAPOL ) zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE ${COMMON_SRC_BASE}/eap_peer/eap_tls.c ${COMMON_SRC_BASE}/eap_peer/eap_tls_common.c - ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c - ${COMMON_SRC_BASE}/eap_peer/eap.c - ${COMMON_SRC_BASE}/eap_peer/eap_methods.c - ${COMMON_SRC_BASE}/eap_common/eap_common.c ${COMMON_SRC_BASE}/eap_peer/eap_peap.c ${COMMON_SRC_BASE}/eap_common/eap_peap_common.c @@ -334,4 +325,12 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_CRYPTO_ENTERPRISE CONFIG_EAP_EKE CONFIG_EAP_IKEv2 ) + +zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_EAPOL + ${COMMON_SRC_BASE}/eapol_supp/eapol_supp_sm.c + ${COMMON_SRC_BASE}/eap_peer/eap.c + ${COMMON_SRC_BASE}/eap_peer/eap_methods.c + ${COMMON_SRC_BASE}/eap_common/eap_common.c +) + endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index ce4255806d..0cc02cf8d2 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -60,7 +60,7 @@ config WPA_SUPP_CRYPTO_ENTERPRISE config WPA_SUPP_WPA3 bool "WPA3 support" select WPA_SUPP_CRYPTO - default y + default n config WPA_SUPP_AP bool "AP mode support" @@ -74,6 +74,10 @@ config WPA_SUPP_P2P select WPA_SUPP_AP select WPA_SUPP_WPS +config WPA_SUPP_EAPOL + bool "Enable EAPoL supplicant" + default y if WPA_SUPP_WPA3 || WPA_SUPP_P2P || WPA_SUPP_CRYPTO_ENTERPRISE + config WPA_CLI bool "CLI support for wpa_supplicant" default n From ff98ecf541f1e43a9e89e4d47f24e7c59c65f5fe Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Mon, 10 Apr 2023 22:26:53 +0530 Subject: [PATCH 142/150] Fix WPA3 PMKSA caching WPA3 also needs to enable PMKSA caching, though the file is included but the define (IEEE8021X_EAPOL) is not passed. Due to code size (text) increase when WPA_SUPP_EAPOL is enabled, this feature is not enabled by default. If required this can be enabled explicitly by application. Signed-off-by: Ravi Dondaputi --- zephyr/CMakeLists.txt | 5 ++++- zephyr/Kconfig | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b2e7452fbe..aa2a93f894 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -172,7 +172,6 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_CRYPTO ${COMMON_SRC_BASE}/common/wpa_common.c ${COMMON_SRC_BASE}/rsn_supp/wpa.c ${COMMON_SRC_BASE}/rsn_supp/preauth.c - ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c ${COMMON_SRC_BASE}/rsn_supp/wpa_ie.c ${COMMON_SRC_BASE}/crypto/crypto_mbedtls-bignum.c @@ -331,6 +330,10 @@ zephyr_library_sources_ifdef(CONFIG_WPA_SUPP_EAPOL ${COMMON_SRC_BASE}/eap_peer/eap.c ${COMMON_SRC_BASE}/eap_peer/eap_methods.c ${COMMON_SRC_BASE}/eap_common/eap_common.c + ${COMMON_SRC_BASE}/rsn_supp/pmksa_cache.c ) +zephyr_library_compile_definitions_ifdef(CONFIG_WPA_SUPP_EAPOL + IEEE8021X_EAPOL +) endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 0cc02cf8d2..b9206ca902 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -60,7 +60,7 @@ config WPA_SUPP_CRYPTO_ENTERPRISE config WPA_SUPP_WPA3 bool "WPA3 support" select WPA_SUPP_CRYPTO - default n + default y config WPA_SUPP_AP bool "AP mode support" @@ -76,7 +76,6 @@ config WPA_SUPP_P2P config WPA_SUPP_EAPOL bool "Enable EAPoL supplicant" - default y if WPA_SUPP_WPA3 || WPA_SUPP_P2P || WPA_SUPP_CRYPTO_ENTERPRISE config WPA_CLI bool "CLI support for wpa_supplicant" From 994312fdb673e53aa41a939704b79a867fc266eb Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Tue, 10 Jan 2023 15:59:44 +0530 Subject: [PATCH 143/150] hostap: Read beacon interval and DTIM period Read beacon interval and DTIM period as part of Wi-Fi status. Signed-off-by: Ravi Dondaputi --- src/drivers/driver.h | 14 ++++++++++++ src/drivers/driver_zephyr.c | 40 +++++++++++++++++++++++++++++++++ src/drivers/driver_zephyr.h | 3 +++ wpa_supplicant/driver_i.h | 3 +++ wpa_supplicant/wpa_supplicant.c | 11 +++++++++ zephyr/src/supp_api.c | 18 +++++++++++++++ 6 files changed, 89 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 2a9c1a7bb3..21f8efa291 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2328,6 +2328,13 @@ struct wpa_signal_info { int center_frq2; }; + +struct wpa_conn_info { + unsigned short beacon_interval; + unsigned char dtim_period; +}; + + /** * struct wpa_channel_info - Information about the current channel * @frequency: Center frequency of the primary 20 MHz channel @@ -3786,6 +3793,13 @@ struct wpa_driver_ops { */ int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info); + /** + * beacon_poll - Get beacon info of current SSID + * @priv: Private driver interface data + * @beacon_info: Beacon info structure + */ + int (*get_conn_info)(void *priv, struct wpa_conn_info *conn_info); + /** * channel_info - Get parameters of the current operating channel * @priv: Private driver interface data diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index f44802e589..78d4a5168b 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -1356,6 +1356,45 @@ static int nl80211_get_ext_capab(void *priv, enum wpa_driver_if_type type, return 0; } +static int wpa_drv_zep_get_conn_info(void *priv, struct wpa_conn_info *ci) +{ + struct zep_drv_if_ctx *if_ctx = NULL; + const struct zep_wpa_supp_dev_ops *dev_ops = NULL; + int ret = -1; + + if (!priv) { + wpa_printf(MSG_ERROR, "%s: Invalid handle\n", __func__); + goto out; + } + + if (!ci) { + wpa_printf(MSG_ERROR, "%s: Invalid params\n", __func__); + goto out; + } + + if_ctx = priv; + dev_ops = if_ctx->dev_ctx->config; + + if (!dev_ops) { + wpa_printf(MSG_ERROR, "%s:Failed to get config handle\n", __func__); + goto out; + } + + if (dev_ops->get_conn_info) { + ret = dev_ops->get_conn_info(if_ctx->dev_priv, ci); + if (ret) { + wpa_printf(MSG_ERROR, "%s: Failed to get connection info: %d\n", __func__, ret); + goto out; + } + } else { + wpa_printf(MSG_ERROR, "%s: Getting connection info is not supported\n", __func__); + goto out; + } + +out: + return ret; +} + const struct wpa_driver_ops wpa_driver_zep_ops = { .name = "zephyr", .desc = "Zephyr wpa_supplicant driver", @@ -1378,4 +1417,5 @@ const struct wpa_driver_ops wpa_driver_zep_ops = { .send_action = wpa_drv_zep_send_action, .get_hw_feature_data = wpa_drv_get_hw_feature_data, .get_ext_capab = nl80211_get_ext_capab, + .get_conn_info = wpa_drv_zep_get_conn_info, }; diff --git a/src/drivers/driver_zephyr.h b/src/drivers/driver_zephyr.h index ec76b2023f..e2d24839e2 100644 --- a/src/drivers/driver_zephyr.h +++ b/src/drivers/driver_zephyr.h @@ -218,6 +218,9 @@ struct zep_wpa_supp_dev_ops { int (*get_capa)(void *if_priv, struct wpa_driver_capa *capa); + + int (*get_conn_info)(void *if_priv, + struct wpa_conn_info *info); }; #endif /* DRIVER_ZEPHYR_H */ diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 237f4e0851..af74a27b33 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -523,6 +523,9 @@ static inline int wpa_drv_signal_monitor(struct wpa_supplicant *wpa_s, int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s, struct wpa_signal_info *si); +int wpa_drv_get_conn_info(struct wpa_supplicant *wpa_s, + struct wpa_conn_info *conn_info); + static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s, struct wpa_channel_info *ci) { diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 82045cffab..0feec5252e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -8611,6 +8611,17 @@ int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s, return 0; } +int wpa_drv_get_conn_info(struct wpa_supplicant *wpa_s, struct wpa_conn_info *ci) +{ + int res; + + if (!wpa_s->driver->get_conn_info) + return -1; + + res = wpa_s->driver->get_conn_info(wpa_s->drv_priv, ci); + + return res; +} int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s, struct wpa_signal_info *si) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 531e288aaf..79a22453a4 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -302,6 +302,7 @@ int z_wpa_supplicant_status(const struct device *dev, struct wpa_supplicant *wpa_s; int ret = -1; struct wpa_signal_info *si = NULL; + struct wpa_conn_info *conn_info = NULL; k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); @@ -365,6 +366,23 @@ int z_wpa_supplicant_status(const struct device *dev, __func__); status->rssi = -WPA_INVALID_NOISE; } + + conn_info = os_zalloc(sizeof(struct wpa_conn_info)); + if (!conn_info) { + wpa_printf(MSG_ERROR, "%s:Failed to allocate memory\n", + __func__); + ret = -ENOMEM; + goto out; + } + ret = wpa_drv_get_conn_info(wpa_s, conn_info); + if (!ret) { + status->beacon_interval = conn_info->beacon_interval; + status->dtim_period = conn_info->dtim_period; + } else { + wpa_printf(MSG_ERROR, "%s: Failed to get connection info\n", + __func__); + goto out; + } } else { ret = 0; } From eea379100ad50db2caa0207bf96f531c36849181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Tue, 18 Apr 2023 14:23:32 -0700 Subject: [PATCH 144/150] [nrf noup] zephyr: remove unnecessary SYS_INIT() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 044ed05fe11cc2e59e1e915dc6fadcdde6bf0820 ("Make WPA CLI as passthrough") made this SYS_INIT() a no-op. It's breaking the build now that SYS_INIT function signatures are 'int callback(void)'. Remove it entirely since it does nothing. Signed-off-by: Martí Bolívar --- zephyr/src/wpa_cli.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/zephyr/src/wpa_cli.c b/zephyr/src/wpa_cli.c index daafba1735..3ad1e5d9fb 100644 --- a/zephyr/src/wpa_cli.c +++ b/zephyr/src/wpa_cli.c @@ -36,15 +36,3 @@ SHELL_CMD_REGISTER(wpa_cli, NULL, "wpa_cli commands (only for internal use)", cmd_wpa_cli); - - -static int wpa_cli_init(const struct device *unused) -{ - ARG_UNUSED(unused); - - return 0; -} - -SYS_INIT(wpa_cli_init, - APPLICATION, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From ec4a32a3a7037603aa87dd5b31622141ceddf32b Mon Sep 17 00:00:00 2001 From: krishna T Date: Thu, 20 Apr 2023 00:47:42 +0530 Subject: [PATCH 145/150] Fix use after free warning introduced by gcc 12.1 gcc 12.1 complains about using pointer after realloc as it could potentially be moved/freed, causing any uses after UB. Fix this by doing checks before alloc and use those statuses and update with new BSS. Signed-off-by: Krishna T --- wpa_supplicant/bss.c | 46 +++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 65b58bd790..117c331523 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -182,9 +182,26 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp) os_free(anqp); } +static bool wpa_bss_check_pending_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ + struct wpa_radio_work *work; + struct wpa_connect_work *cwork; + + work = radio_work_pending(wpa_s, "sme-connect"); + if (!work) + work = radio_work_pending(wpa_s, "connect"); + if (!work) + return false; + + cwork = work->ctx; + if (cwork->bss != bss) + return false; + + return true; +} static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s, - struct wpa_bss *old_bss, struct wpa_bss *new_bss) { struct wpa_radio_work *work; @@ -197,8 +214,6 @@ static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s, return; cwork = work->ctx; - if (cwork->bss != old_bss) - return; wpa_printf(MSG_DEBUG, "Update BSS pointer for the pending connect radio work"); @@ -224,7 +239,8 @@ void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } } } - wpa_bss_update_pending_connect(wpa_s, bss, NULL); + if (wpa_bss_check_pending_connect(wpa_s, bss)) + wpa_bss_update_pending_connect(wpa_s, NULL); dl_list_del(&bss->list); dl_list_del(&bss->list_id); wpa_s->num_bss--; @@ -685,20 +701,24 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } else { struct wpa_bss *nbss; struct dl_list *prev = bss->list_id.prev; + bool update_pending_connect = wpa_bss_check_pending_connect( + wpa_s, bss); + unsigned int i; + bool update_current_bss = wpa_s->current_bss == bss; + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + if (wpa_s->last_scan_res[i] == bss) + break; + } dl_list_del(&bss->list_id); nbss = os_realloc(bss, sizeof(*bss) + res->ie_len + res->beacon_ie_len); if (nbss) { - unsigned int i; - for (i = 0; i < wpa_s->last_scan_res_used; i++) { - if (wpa_s->last_scan_res[i] == bss) { - wpa_s->last_scan_res[i] = nbss; - break; - } - } - if (wpa_s->current_bss == bss) + if (i != wpa_s->last_scan_res_used) + wpa_s->last_scan_res[i] = nbss; + if (update_current_bss) wpa_s->current_bss = nbss; - wpa_bss_update_pending_connect(wpa_s, bss, nbss); + if (update_pending_connect) + wpa_bss_update_pending_connect(wpa_s, nbss); bss = nbss; os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); From 490d2fd301c68f3f48ae04695aafb602dd429bdc Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Tue, 2 May 2023 18:17:55 +0530 Subject: [PATCH 146/150] Rectify error handling while fetching connection info While fetching connection info as part of processing the interface status command, if error is returned by driver, set the params to 0 and reset the return value, so that other params are not ignored by the caller. Signed-off-by: Ravi Dondaputi --- zephyr/src/supp_api.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/zephyr/src/supp_api.c b/zephyr/src/supp_api.c index 79a22453a4..333a894766 100644 --- a/zephyr/src/supp_api.c +++ b/zephyr/src/supp_api.c @@ -362,9 +362,10 @@ int z_wpa_supplicant_status(const struct device *dev, if (!ret) { status->rssi = signal_poll.rssi; } else { - wpa_printf(MSG_ERROR, "%s:Failed to read RSSI\n", + wpa_printf(MSG_WARNING, "%s:Failed to read RSSI\n", __func__); status->rssi = -WPA_INVALID_NOISE; + ret = 0; } conn_info = os_zalloc(sizeof(struct wpa_conn_info)); @@ -379,9 +380,11 @@ int z_wpa_supplicant_status(const struct device *dev, status->beacon_interval = conn_info->beacon_interval; status->dtim_period = conn_info->dtim_period; } else { - wpa_printf(MSG_ERROR, "%s: Failed to get connection info\n", + wpa_printf(MSG_WARNING, "%s: Failed to get connection info\n", __func__); - goto out; + status->beacon_interval = 0; + status->dtim_period = 0; + ret = 0; } } else { ret = 0; From 91e968deb55f4f638a780afd776fc45002078d02 Mon Sep 17 00:00:00 2001 From: Krishna T Date: Thu, 27 Apr 2023 23:13:58 +0530 Subject: [PATCH 147/150] Fix handling of IEs in authentication When copying event from driver and postnig to WPA supplicant, the IE's are not copied, so, if WPA supplicant takes longer to process the event the driver frees the IEs causing invalid data to be processed by WPA supplicant. This is a common issue to all events. For now Authentication events are being affected due to WPA3-SAE taking longer to process, so, fix only Authentication events for now as a generic fix needs more work and thought. Signed-off-by: Krishna T --- src/drivers/driver_zephyr.c | 15 +++++++++++++++ zephyr/src/supp_main.c | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/src/drivers/driver_zephyr.c b/src/drivers/driver_zephyr.c index 78d4a5168b..1aa34d224b 100644 --- a/src/drivers/driver_zephyr.c +++ b/src/drivers/driver_zephyr.c @@ -32,6 +32,21 @@ void wpa_supplicant_event_wrapper(void *ctx, return; } os_memcpy(msg.data, data, sizeof(*data)); + if (event == EVENT_AUTH) { + union wpa_event_data *data_tmp = msg.data; + + if (data->auth.ies) { + char *ies = os_zalloc(data->auth.ies_len); + + if (!ies) { + wpa_printf(MSG_ERROR, "%s: Failed to alloc ies\n", __func__); + return; + } + + os_memcpy(ies, data->auth.ies, data->auth.ies_len); + data_tmp->auth.ies = ies; + } + } } z_wpas_send_event(&msg); } diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 306b18bab9..15c915682c 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -311,6 +311,11 @@ static void z_wpas_event_sock_handler(int sock, void *eloop_ctx, void *sock_ctx) } if (msg.data) { + if (msg.event == EVENT_AUTH) { + union wpa_event_data *data = msg.data; + + os_free((char *)data->auth.ies); + } os_free(msg.data); } } From ec738bf6bcc902bc5508ddcdcffa7f6f7e6af169 Mon Sep 17 00:00:00 2001 From: krishna T Date: Sun, 30 Apr 2023 00:16:31 +0530 Subject: [PATCH 148/150] Revert "Add support to configure SAE-H2E" As the command is a global configuration, no need to add a separate command, it can be set using "wpa_cli set" itself. This reverts commit a5b03c432030923779abb2c060988fc5d4ee1253. --- wpa_supplicant/ctrl_iface.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index c61d919530..cd82b2bdb7 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -924,17 +924,6 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, #endif /* CONFIG_WNM */ } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) { wpa_s->enable_dscp_policy_capa = !!atoi(value); -#ifdef CONFIG_SAE - } else if (os_strcasecmp(cmd, "sae_pwe") == 0) { - int pwe = atoi(value); - - if (pwe < 0 || pwe > 2) { - wpa_printf(MSG_ERROR, - "Invalid SAE PWE value %d", pwe); - return -1; - } - wpa_s->conf->sae_pwe = pwe; -#endif /* CONFIG_SAE */ } else { value[-1] = '='; ret = wpa_config_process_global(wpa_s->conf, cmd, -1); From 7c414d4d223251f437e4b90ca04290a0a7de6b69 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 9 May 2023 01:33:06 +0530 Subject: [PATCH 149/150] Use unbuffered logging for debugs WPA supplicant debugs are excessive and the incoming rate is high esp. during connection, so, even though we increase the log buffer size, we still miss quite a few events. So, disable buffered logging for debugs, one caveat is that we lose the timestamp that comes with LOG_ macros and also the prints might be jumbled but this is still preferred over losing events. Signed-off-by: Krishna T --- zephyr/Kconfig | 5 ----- zephyr/src/utils/wpa_debug.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index b9206ca902..49537d9726 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -115,9 +115,4 @@ config WPA_SUPP_DEBUG_LEVEL available levels and functions for emitting the messages. Note that runtime filtering can also be configured in addition to the compile-time filtering. - -# Debug logs need more buffer space -config LOG_BUFFER_SIZE - default 4096 if WPA_SUPP_LOG_LEVEL_DBG - default 2048 endif diff --git a/zephyr/src/utils/wpa_debug.c b/zephyr/src/utils/wpa_debug.c index 542f3e8dee..159d56c18d 100644 --- a/zephyr/src/utils/wpa_debug.c +++ b/zephyr/src/utils/wpa_debug.c @@ -54,7 +54,7 @@ void wpa_printf_impl(int level, const char *fmt, ...) case MSG_DEBUG: case MSG_MSGDUMP: case MSG_EXCESSIVE: - LOG_DBG("%s", buffer); + printf("%s\n", buffer); break; default: break; From 56456490d395a7e9f0af15f1dfa64ab0df6c9e72 Mon Sep 17 00:00:00 2001 From: krishna T Date: Tue, 9 May 2023 01:40:30 +0530 Subject: [PATCH 150/150] Add configuration for dumping keys This is handy in debugging crypto related issues. Also, configure the WPA supplicant after initialization. Signed-off-by: Krishna T --- zephyr/Kconfig | 7 +++++++ zephyr/src/supp_main.c | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 49537d9726..19c2243b1b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -115,4 +115,11 @@ config WPA_SUPP_DEBUG_LEVEL available levels and functions for emitting the messages. Note that runtime filtering can also be configured in addition to the compile-time filtering. + +config WPA_SUPP_DEBUG_SHOW_KEYS + bool "Show keys in debug output" + help + This option can be used to show keys (e.g., PSK, EAP session keys) in + debug log messages. This can be used to debug key derivation and + authentication issues. Please do not enable this option in production. endif diff --git a/zephyr/src/supp_main.c b/zephyr/src/supp_main.c index 15c915682c..983601f24b 100644 --- a/zephyr/src/supp_main.c +++ b/zephyr/src/supp_main.c @@ -404,6 +404,14 @@ static void z_wpas_start(void) goto out; } +#if defined (CONFIG_WPA_SUPP_LOG_LEVEL_DBG) && defined (CONFIG_WPA_SUPP_DEBUG_SHOW_KEYS) + wpa_supplicant_set_debug_params(global, MSG_DEBUG, 1, 1); +#elif defined (CONFIG_WPA_SUPP_LOG_LEVEL_DBG) + wpa_supplicant_set_debug_params(global, MSG_DEBUG, 1, 0); +#else + wpa_supplicant_set_debug_params(global, MSG_INFO, 0, 0); +#endif + #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE) if (!fst_global_add_ctrl(fst_ctrl_cli)) { wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");