/* * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ /* @file * @brief wpa_cli implementation for Zephyr OS */ #include #include #include #include #include #include #include #include "supp_main.h" #include "common.h" #include "wpa_supplicant_i.h" #include "wpa_cli_zephyr.h" #ifdef CONFIG_WIFI_NM_HOSTAPD_AP #include "hostapd.h" #include "hapd_main.h" #include "hostapd_cli_zephyr.h" #endif static int cmd_wpa_cli(const struct shell *sh, size_t argc, const char *argv[]) { struct net_if *iface = NULL; char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; struct wpa_supplicant *wpa_s = NULL; size_t arg_offset = 1; int idx = -1; bool iface_found = false; if (argc > 2 && ((strcmp(argv[1], "-i") == 0) || (strncmp(argv[1], "-i", 2) == 0 && argv[1][2] != '\0'))) { /* Handle both "-i 2" and "-i2" */ if (strcmp(argv[1], "-i") == 0) { idx = strtol(argv[2], NULL, 10); arg_offset = 3; } else { idx = strtol(&argv[1][2], NULL, 10); arg_offset = 2; } iface = net_if_get_by_index(idx); if (!iface) { shell_error(sh, "Interface index %d not found", idx); return -ENODEV; } net_if_get_name(iface, if_name, sizeof(if_name)); if_name[sizeof(if_name) - 1] = '\0'; iface_found = true; } else { /* Default to first Wi-Fi interface */ iface = net_if_get_first_wifi(); if (!iface) { shell_error(sh, "No Wi-Fi interface found"); return -ENOENT; } net_if_get_name(iface, if_name, sizeof(if_name)); if_name[sizeof(if_name) - 1] = '\0'; arg_offset = 1; iface_found = true; } if (!iface_found) { shell_error(sh, "No interface found"); return -ENODEV; } wpa_s = zephyr_get_handle_by_ifname(if_name); if (!wpa_s) { shell_error(sh, "No wpa_supplicant context for interface '%s'", if_name); return -ENODEV; } if (argc <= arg_offset) { shell_error(sh, "Missing argument"); return -EINVAL; } argv[argc] = "interactive"; argc++; /* Remove wpa_cli from the argument list */ return zephyr_wpa_ctrl_zephyr_cmd(wpa_s->ctrl_conn, argc - arg_offset, &argv[arg_offset]); } #ifdef CONFIG_WIFI_NM_HOSTAPD_AP static int cmd_hostapd_cli(const struct shell *sh, size_t argc, const char *argv[]) { struct net_if *iface = NULL; size_t arg_offset = 1; struct hostapd_iface *hapd_iface; int idx = -1; bool iface_found = false; char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; int ret; if (argc > 2 && ((strcmp(argv[1], "-i") == 0) || (strncmp(argv[1], "-i", 2) == 0 && argv[1][2] != '\0'))) { /* Handle both "-i 2" and "-i2" */ if (strcmp(argv[1], "-i") == 0) { idx = strtol(argv[2], NULL, 10); arg_offset = 3; } else { idx = strtol(&argv[1][2], NULL, 10); arg_offset = 2; } iface = net_if_get_by_index(idx); if (!iface) { shell_error(sh, "Interface index %d not found", idx); return -ENODEV; } iface_found = true; } else { iface = net_if_get_wifi_sap(); if (!iface) { shell_error(sh, "No Wi-Fi interface found"); return -ENOENT; } arg_offset = 1; iface_found = true; } if (!iface_found) { shell_error(sh, "No interface found"); return -ENODEV; } ret = net_if_get_name(iface, if_name, sizeof(if_name)); if (!ret) { shell_error(sh, "Cannot get interface name (%d)", ret); return -ENODEV; } hapd_iface = zephyr_get_hapd_handle_by_ifname(if_name); if (!hapd_iface) { shell_error(sh, "No hostapd context for interface '%s'", if_name); return -ENODEV; } if (argc <= arg_offset) { shell_error(sh, "Missing argument"); return -EINVAL; } argv[argc] = "interactive"; argc++; /* Remove hostapd_cli from the argument list */ return zephyr_hostapd_ctrl_zephyr_cmd(hapd_iface->ctrl_conn, argc - arg_offset, &argv[arg_offset]); } #endif /* Persisting with "wpa_cli" naming for compatibility with Wi-Fi * certification applications and scripts. */ SHELL_CMD_REGISTER(wpa_cli, NULL, "wpa_cli [-i idx] (only for internal use)", cmd_wpa_cli); #ifdef CONFIG_WIFI_NM_HOSTAPD_AP SHELL_CMD_REGISTER(hostapd_cli, NULL, "hostapd_cli [-i idx] (only for internal use)", cmd_hostapd_cli); #endif