1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * hostapd / UNIX domain socket -based control interface 3e5b75505Sopenharmony_ci * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "utils/includes.h" 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#ifndef CONFIG_NATIVE_WINDOWS 12e5b75505Sopenharmony_ci 13e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 14e5b75505Sopenharmony_ci#include <net/ethernet.h> 15e5b75505Sopenharmony_ci#include <netinet/ip.h> 16e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 17e5b75505Sopenharmony_ci 18e5b75505Sopenharmony_ci#include <sys/un.h> 19e5b75505Sopenharmony_ci#include <sys/stat.h> 20e5b75505Sopenharmony_ci#include <stddef.h> 21e5b75505Sopenharmony_ci 22e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 23e5b75505Sopenharmony_ci#include <netdb.h> 24e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 25e5b75505Sopenharmony_ci 26e5b75505Sopenharmony_ci#include "utils/common.h" 27e5b75505Sopenharmony_ci#include "utils/eloop.h" 28e5b75505Sopenharmony_ci#include "utils/module_tests.h" 29e5b75505Sopenharmony_ci#include "common/version.h" 30e5b75505Sopenharmony_ci#include "common/ieee802_11_defs.h" 31e5b75505Sopenharmony_ci#include "common/ctrl_iface_common.h" 32e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 33e5b75505Sopenharmony_ci#include "common/dpp.h" 34e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 35e5b75505Sopenharmony_ci#include "common/wpa_ctrl.h" 36e5b75505Sopenharmony_ci#include "crypto/tls.h" 37e5b75505Sopenharmony_ci#include "drivers/driver.h" 38e5b75505Sopenharmony_ci#include "eapol_auth/eapol_auth_sm.h" 39e5b75505Sopenharmony_ci#include "radius/radius_client.h" 40e5b75505Sopenharmony_ci#include "radius/radius_server.h" 41e5b75505Sopenharmony_ci#include "l2_packet/l2_packet.h" 42e5b75505Sopenharmony_ci#include "ap/hostapd.h" 43e5b75505Sopenharmony_ci#include "ap/ap_config.h" 44e5b75505Sopenharmony_ci#include "ap/ieee802_1x.h" 45e5b75505Sopenharmony_ci#include "ap/wpa_auth.h" 46e5b75505Sopenharmony_ci#include "ap/ieee802_11.h" 47e5b75505Sopenharmony_ci#include "ap/sta_info.h" 48e5b75505Sopenharmony_ci#include "ap/wps_hostapd.h" 49e5b75505Sopenharmony_ci#include "ap/ctrl_iface_ap.h" 50e5b75505Sopenharmony_ci#include "ap/ap_drv_ops.h" 51e5b75505Sopenharmony_ci#include "ap/hs20.h" 52e5b75505Sopenharmony_ci#include "ap/wnm_ap.h" 53e5b75505Sopenharmony_ci#include "ap/wpa_auth.h" 54e5b75505Sopenharmony_ci#include "ap/beacon.h" 55e5b75505Sopenharmony_ci#include "ap/neighbor_db.h" 56e5b75505Sopenharmony_ci#include "ap/rrm.h" 57e5b75505Sopenharmony_ci#include "ap/dpp_hostapd.h" 58e5b75505Sopenharmony_ci#include "wps/wps_defs.h" 59e5b75505Sopenharmony_ci#include "wps/wps.h" 60e5b75505Sopenharmony_ci#include "fst/fst_ctrl_iface.h" 61e5b75505Sopenharmony_ci#include "config_file.h" 62e5b75505Sopenharmony_ci#include "ctrl_iface.h" 63e5b75505Sopenharmony_ci 64e5b75505Sopenharmony_ci 65e5b75505Sopenharmony_ci#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256 66e5b75505Sopenharmony_ci 67e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 68e5b75505Sopenharmony_ci#define COOKIE_LEN 8 69e5b75505Sopenharmony_cistatic unsigned char cookie[COOKIE_LEN]; 70e5b75505Sopenharmony_cistatic unsigned char gcookie[COOKIE_LEN]; 71e5b75505Sopenharmony_ci#define HOSTAPD_CTRL_IFACE_PORT 9877 72e5b75505Sopenharmony_ci#define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50 73e5b75505Sopenharmony_ci#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878 74e5b75505Sopenharmony_ci#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50 75e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 76e5b75505Sopenharmony_ci 77e5b75505Sopenharmony_cistatic void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 78e5b75505Sopenharmony_ci enum wpa_msg_type type, 79e5b75505Sopenharmony_ci const char *buf, size_t len); 80e5b75505Sopenharmony_ci 81e5b75505Sopenharmony_ci 82e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 83e5b75505Sopenharmony_ci struct sockaddr_storage *from, 84e5b75505Sopenharmony_ci socklen_t fromlen, const char *input) 85e5b75505Sopenharmony_ci{ 86e5b75505Sopenharmony_ci return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen, input); 87e5b75505Sopenharmony_ci} 88e5b75505Sopenharmony_ci 89e5b75505Sopenharmony_ci 90e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 91e5b75505Sopenharmony_ci struct sockaddr_storage *from, 92e5b75505Sopenharmony_ci socklen_t fromlen) 93e5b75505Sopenharmony_ci{ 94e5b75505Sopenharmony_ci return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen); 95e5b75505Sopenharmony_ci} 96e5b75505Sopenharmony_ci 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 99e5b75505Sopenharmony_ci struct sockaddr_storage *from, 100e5b75505Sopenharmony_ci socklen_t fromlen, 101e5b75505Sopenharmony_ci char *level) 102e5b75505Sopenharmony_ci{ 103e5b75505Sopenharmony_ci return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level); 104e5b75505Sopenharmony_ci} 105e5b75505Sopenharmony_ci 106e5b75505Sopenharmony_ci 107e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 108e5b75505Sopenharmony_ci const char *txtaddr) 109e5b75505Sopenharmony_ci{ 110e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 111e5b75505Sopenharmony_ci struct sta_info *sta; 112e5b75505Sopenharmony_ci 113e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 114e5b75505Sopenharmony_ci 115e5b75505Sopenharmony_ci if (hwaddr_aton(txtaddr, addr)) 116e5b75505Sopenharmony_ci return -1; 117e5b75505Sopenharmony_ci 118e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 119e5b75505Sopenharmony_ci if (sta) 120e5b75505Sopenharmony_ci return 0; 121e5b75505Sopenharmony_ci 122e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 123e5b75505Sopenharmony_ci "notification", MAC2STR(addr)); 124e5b75505Sopenharmony_ci sta = ap_sta_add(hapd, addr); 125e5b75505Sopenharmony_ci if (sta == NULL) 126e5b75505Sopenharmony_ci return -1; 127e5b75505Sopenharmony_ci 128e5b75505Sopenharmony_ci hostapd_new_assoc_sta(hapd, sta, 0); 129e5b75505Sopenharmony_ci return 0; 130e5b75505Sopenharmony_ci} 131e5b75505Sopenharmony_ci 132e5b75505Sopenharmony_ci 133e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 134e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 135e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 136e5b75505Sopenharmony_ci const char *txtaddr) 137e5b75505Sopenharmony_ci{ 138e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 139e5b75505Sopenharmony_ci u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 140e5b75505Sopenharmony_ci 141e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 142e5b75505Sopenharmony_ci 143e5b75505Sopenharmony_ci if (hwaddr_aton(txtaddr, addr) || 144e5b75505Sopenharmony_ci os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 145e5b75505Sopenharmony_ci return -1; 146e5b75505Sopenharmony_ci 147e5b75505Sopenharmony_ci ieee802_11_send_sa_query_req(hapd, addr, trans_id); 148e5b75505Sopenharmony_ci 149e5b75505Sopenharmony_ci return 0; 150e5b75505Sopenharmony_ci} 151e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 152e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 153e5b75505Sopenharmony_ci 154e5b75505Sopenharmony_ci 155e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 156e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 157e5b75505Sopenharmony_ci{ 158e5b75505Sopenharmony_ci char *pin = os_strchr(txt, ' '); 159e5b75505Sopenharmony_ci char *timeout_txt; 160e5b75505Sopenharmony_ci int timeout; 161e5b75505Sopenharmony_ci u8 addr_buf[ETH_ALEN], *addr = NULL; 162e5b75505Sopenharmony_ci char *pos; 163e5b75505Sopenharmony_ci 164e5b75505Sopenharmony_ci if (pin == NULL) 165e5b75505Sopenharmony_ci return -1; 166e5b75505Sopenharmony_ci *pin++ = '\0'; 167e5b75505Sopenharmony_ci 168e5b75505Sopenharmony_ci timeout_txt = os_strchr(pin, ' '); 169e5b75505Sopenharmony_ci if (timeout_txt) { 170e5b75505Sopenharmony_ci *timeout_txt++ = '\0'; 171e5b75505Sopenharmony_ci timeout = atoi(timeout_txt); 172e5b75505Sopenharmony_ci pos = os_strchr(timeout_txt, ' '); 173e5b75505Sopenharmony_ci if (pos) { 174e5b75505Sopenharmony_ci *pos++ = '\0'; 175e5b75505Sopenharmony_ci if (hwaddr_aton(pos, addr_buf) == 0) 176e5b75505Sopenharmony_ci addr = addr_buf; 177e5b75505Sopenharmony_ci } 178e5b75505Sopenharmony_ci } else 179e5b75505Sopenharmony_ci timeout = 0; 180e5b75505Sopenharmony_ci 181e5b75505Sopenharmony_ci return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 182e5b75505Sopenharmony_ci} 183e5b75505Sopenharmony_ci 184e5b75505Sopenharmony_ci 185e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_check_pin( 186e5b75505Sopenharmony_ci struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 187e5b75505Sopenharmony_ci{ 188e5b75505Sopenharmony_ci char pin[9]; 189e5b75505Sopenharmony_ci size_t len; 190e5b75505Sopenharmony_ci char *pos; 191e5b75505Sopenharmony_ci int ret; 192e5b75505Sopenharmony_ci 193e5b75505Sopenharmony_ci wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 194e5b75505Sopenharmony_ci (u8 *) cmd, os_strlen(cmd)); 195e5b75505Sopenharmony_ci for (pos = cmd, len = 0; *pos != '\0'; pos++) { 196e5b75505Sopenharmony_ci if (*pos < '0' || *pos > '9') 197e5b75505Sopenharmony_ci continue; 198e5b75505Sopenharmony_ci pin[len++] = *pos; 199e5b75505Sopenharmony_ci if (len == 9) { 200e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 201e5b75505Sopenharmony_ci return -1; 202e5b75505Sopenharmony_ci } 203e5b75505Sopenharmony_ci } 204e5b75505Sopenharmony_ci if (len != 4 && len != 8) { 205e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 206e5b75505Sopenharmony_ci return -1; 207e5b75505Sopenharmony_ci } 208e5b75505Sopenharmony_ci pin[len] = '\0'; 209e5b75505Sopenharmony_ci 210e5b75505Sopenharmony_ci if (len == 8) { 211e5b75505Sopenharmony_ci unsigned int pin_val; 212e5b75505Sopenharmony_ci pin_val = atoi(pin); 213e5b75505Sopenharmony_ci if (!wps_pin_valid(pin_val)) { 214e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 215e5b75505Sopenharmony_ci ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 216e5b75505Sopenharmony_ci if (os_snprintf_error(buflen, ret)) 217e5b75505Sopenharmony_ci return -1; 218e5b75505Sopenharmony_ci return ret; 219e5b75505Sopenharmony_ci } 220e5b75505Sopenharmony_ci } 221e5b75505Sopenharmony_ci 222e5b75505Sopenharmony_ci ret = os_snprintf(buf, buflen, "%s", pin); 223e5b75505Sopenharmony_ci if (os_snprintf_error(buflen, ret)) 224e5b75505Sopenharmony_ci return -1; 225e5b75505Sopenharmony_ci 226e5b75505Sopenharmony_ci return ret; 227e5b75505Sopenharmony_ci} 228e5b75505Sopenharmony_ci 229e5b75505Sopenharmony_ci 230e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_NFC 231e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 232e5b75505Sopenharmony_ci char *pos) 233e5b75505Sopenharmony_ci{ 234e5b75505Sopenharmony_ci size_t len; 235e5b75505Sopenharmony_ci struct wpabuf *buf; 236e5b75505Sopenharmony_ci int ret; 237e5b75505Sopenharmony_ci 238e5b75505Sopenharmony_ci len = os_strlen(pos); 239e5b75505Sopenharmony_ci if (len & 0x01) 240e5b75505Sopenharmony_ci return -1; 241e5b75505Sopenharmony_ci len /= 2; 242e5b75505Sopenharmony_ci 243e5b75505Sopenharmony_ci buf = wpabuf_alloc(len); 244e5b75505Sopenharmony_ci if (buf == NULL) 245e5b75505Sopenharmony_ci return -1; 246e5b75505Sopenharmony_ci if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 247e5b75505Sopenharmony_ci wpabuf_free(buf); 248e5b75505Sopenharmony_ci return -1; 249e5b75505Sopenharmony_ci } 250e5b75505Sopenharmony_ci 251e5b75505Sopenharmony_ci ret = hostapd_wps_nfc_tag_read(hapd, buf); 252e5b75505Sopenharmony_ci wpabuf_free(buf); 253e5b75505Sopenharmony_ci 254e5b75505Sopenharmony_ci return ret; 255e5b75505Sopenharmony_ci} 256e5b75505Sopenharmony_ci 257e5b75505Sopenharmony_ci 258e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 259e5b75505Sopenharmony_ci char *cmd, char *reply, 260e5b75505Sopenharmony_ci size_t max_len) 261e5b75505Sopenharmony_ci{ 262e5b75505Sopenharmony_ci int ndef; 263e5b75505Sopenharmony_ci struct wpabuf *buf; 264e5b75505Sopenharmony_ci int res; 265e5b75505Sopenharmony_ci 266e5b75505Sopenharmony_ci if (os_strcmp(cmd, "WPS") == 0) 267e5b75505Sopenharmony_ci ndef = 0; 268e5b75505Sopenharmony_ci else if (os_strcmp(cmd, "NDEF") == 0) 269e5b75505Sopenharmony_ci ndef = 1; 270e5b75505Sopenharmony_ci else 271e5b75505Sopenharmony_ci return -1; 272e5b75505Sopenharmony_ci 273e5b75505Sopenharmony_ci buf = hostapd_wps_nfc_config_token(hapd, ndef); 274e5b75505Sopenharmony_ci if (buf == NULL) 275e5b75505Sopenharmony_ci return -1; 276e5b75505Sopenharmony_ci 277e5b75505Sopenharmony_ci res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 278e5b75505Sopenharmony_ci wpabuf_len(buf)); 279e5b75505Sopenharmony_ci reply[res++] = '\n'; 280e5b75505Sopenharmony_ci reply[res] = '\0'; 281e5b75505Sopenharmony_ci 282e5b75505Sopenharmony_ci wpabuf_free(buf); 283e5b75505Sopenharmony_ci 284e5b75505Sopenharmony_ci return res; 285e5b75505Sopenharmony_ci} 286e5b75505Sopenharmony_ci 287e5b75505Sopenharmony_ci 288e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 289e5b75505Sopenharmony_ci char *reply, size_t max_len, 290e5b75505Sopenharmony_ci int ndef) 291e5b75505Sopenharmony_ci{ 292e5b75505Sopenharmony_ci struct wpabuf *buf; 293e5b75505Sopenharmony_ci int res; 294e5b75505Sopenharmony_ci 295e5b75505Sopenharmony_ci buf = hostapd_wps_nfc_token_gen(hapd, ndef); 296e5b75505Sopenharmony_ci if (buf == NULL) 297e5b75505Sopenharmony_ci return -1; 298e5b75505Sopenharmony_ci 299e5b75505Sopenharmony_ci res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 300e5b75505Sopenharmony_ci wpabuf_len(buf)); 301e5b75505Sopenharmony_ci reply[res++] = '\n'; 302e5b75505Sopenharmony_ci reply[res] = '\0'; 303e5b75505Sopenharmony_ci 304e5b75505Sopenharmony_ci wpabuf_free(buf); 305e5b75505Sopenharmony_ci 306e5b75505Sopenharmony_ci return res; 307e5b75505Sopenharmony_ci} 308e5b75505Sopenharmony_ci 309e5b75505Sopenharmony_ci 310e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 311e5b75505Sopenharmony_ci char *cmd, char *reply, 312e5b75505Sopenharmony_ci size_t max_len) 313e5b75505Sopenharmony_ci{ 314e5b75505Sopenharmony_ci if (os_strcmp(cmd, "WPS") == 0) 315e5b75505Sopenharmony_ci return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 316e5b75505Sopenharmony_ci max_len, 0); 317e5b75505Sopenharmony_ci 318e5b75505Sopenharmony_ci if (os_strcmp(cmd, "NDEF") == 0) 319e5b75505Sopenharmony_ci return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 320e5b75505Sopenharmony_ci max_len, 1); 321e5b75505Sopenharmony_ci 322e5b75505Sopenharmony_ci if (os_strcmp(cmd, "enable") == 0) 323e5b75505Sopenharmony_ci return hostapd_wps_nfc_token_enable(hapd); 324e5b75505Sopenharmony_ci 325e5b75505Sopenharmony_ci if (os_strcmp(cmd, "disable") == 0) { 326e5b75505Sopenharmony_ci hostapd_wps_nfc_token_disable(hapd); 327e5b75505Sopenharmony_ci return 0; 328e5b75505Sopenharmony_ci } 329e5b75505Sopenharmony_ci 330e5b75505Sopenharmony_ci return -1; 331e5b75505Sopenharmony_ci} 332e5b75505Sopenharmony_ci 333e5b75505Sopenharmony_ci 334e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd, 335e5b75505Sopenharmony_ci char *cmd, char *reply, 336e5b75505Sopenharmony_ci size_t max_len) 337e5b75505Sopenharmony_ci{ 338e5b75505Sopenharmony_ci struct wpabuf *buf; 339e5b75505Sopenharmony_ci int res; 340e5b75505Sopenharmony_ci char *pos; 341e5b75505Sopenharmony_ci int ndef; 342e5b75505Sopenharmony_ci 343e5b75505Sopenharmony_ci pos = os_strchr(cmd, ' '); 344e5b75505Sopenharmony_ci if (pos == NULL) 345e5b75505Sopenharmony_ci return -1; 346e5b75505Sopenharmony_ci *pos++ = '\0'; 347e5b75505Sopenharmony_ci 348e5b75505Sopenharmony_ci if (os_strcmp(cmd, "WPS") == 0) 349e5b75505Sopenharmony_ci ndef = 0; 350e5b75505Sopenharmony_ci else if (os_strcmp(cmd, "NDEF") == 0) 351e5b75505Sopenharmony_ci ndef = 1; 352e5b75505Sopenharmony_ci else 353e5b75505Sopenharmony_ci return -1; 354e5b75505Sopenharmony_ci 355e5b75505Sopenharmony_ci if (os_strcmp(pos, "WPS-CR") == 0) 356e5b75505Sopenharmony_ci buf = hostapd_wps_nfc_hs_cr(hapd, ndef); 357e5b75505Sopenharmony_ci else 358e5b75505Sopenharmony_ci buf = NULL; 359e5b75505Sopenharmony_ci if (buf == NULL) 360e5b75505Sopenharmony_ci return -1; 361e5b75505Sopenharmony_ci 362e5b75505Sopenharmony_ci res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 363e5b75505Sopenharmony_ci wpabuf_len(buf)); 364e5b75505Sopenharmony_ci reply[res++] = '\n'; 365e5b75505Sopenharmony_ci reply[res] = '\0'; 366e5b75505Sopenharmony_ci 367e5b75505Sopenharmony_ci wpabuf_free(buf); 368e5b75505Sopenharmony_ci 369e5b75505Sopenharmony_ci return res; 370e5b75505Sopenharmony_ci} 371e5b75505Sopenharmony_ci 372e5b75505Sopenharmony_ci 373e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd, 374e5b75505Sopenharmony_ci char *cmd) 375e5b75505Sopenharmony_ci{ 376e5b75505Sopenharmony_ci size_t len; 377e5b75505Sopenharmony_ci struct wpabuf *req, *sel; 378e5b75505Sopenharmony_ci int ret; 379e5b75505Sopenharmony_ci char *pos, *role, *type, *pos2; 380e5b75505Sopenharmony_ci 381e5b75505Sopenharmony_ci role = cmd; 382e5b75505Sopenharmony_ci pos = os_strchr(role, ' '); 383e5b75505Sopenharmony_ci if (pos == NULL) 384e5b75505Sopenharmony_ci return -1; 385e5b75505Sopenharmony_ci *pos++ = '\0'; 386e5b75505Sopenharmony_ci 387e5b75505Sopenharmony_ci type = pos; 388e5b75505Sopenharmony_ci pos = os_strchr(type, ' '); 389e5b75505Sopenharmony_ci if (pos == NULL) 390e5b75505Sopenharmony_ci return -1; 391e5b75505Sopenharmony_ci *pos++ = '\0'; 392e5b75505Sopenharmony_ci 393e5b75505Sopenharmony_ci pos2 = os_strchr(pos, ' '); 394e5b75505Sopenharmony_ci if (pos2 == NULL) 395e5b75505Sopenharmony_ci return -1; 396e5b75505Sopenharmony_ci *pos2++ = '\0'; 397e5b75505Sopenharmony_ci 398e5b75505Sopenharmony_ci len = os_strlen(pos); 399e5b75505Sopenharmony_ci if (len & 0x01) 400e5b75505Sopenharmony_ci return -1; 401e5b75505Sopenharmony_ci len /= 2; 402e5b75505Sopenharmony_ci 403e5b75505Sopenharmony_ci req = wpabuf_alloc(len); 404e5b75505Sopenharmony_ci if (req == NULL) 405e5b75505Sopenharmony_ci return -1; 406e5b75505Sopenharmony_ci if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 407e5b75505Sopenharmony_ci wpabuf_free(req); 408e5b75505Sopenharmony_ci return -1; 409e5b75505Sopenharmony_ci } 410e5b75505Sopenharmony_ci 411e5b75505Sopenharmony_ci len = os_strlen(pos2); 412e5b75505Sopenharmony_ci if (len & 0x01) { 413e5b75505Sopenharmony_ci wpabuf_free(req); 414e5b75505Sopenharmony_ci return -1; 415e5b75505Sopenharmony_ci } 416e5b75505Sopenharmony_ci len /= 2; 417e5b75505Sopenharmony_ci 418e5b75505Sopenharmony_ci sel = wpabuf_alloc(len); 419e5b75505Sopenharmony_ci if (sel == NULL) { 420e5b75505Sopenharmony_ci wpabuf_free(req); 421e5b75505Sopenharmony_ci return -1; 422e5b75505Sopenharmony_ci } 423e5b75505Sopenharmony_ci if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 424e5b75505Sopenharmony_ci wpabuf_free(req); 425e5b75505Sopenharmony_ci wpabuf_free(sel); 426e5b75505Sopenharmony_ci return -1; 427e5b75505Sopenharmony_ci } 428e5b75505Sopenharmony_ci 429e5b75505Sopenharmony_ci if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) { 430e5b75505Sopenharmony_ci ret = hostapd_wps_nfc_report_handover(hapd, req, sel); 431e5b75505Sopenharmony_ci } else { 432e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 433e5b75505Sopenharmony_ci "reported: role=%s type=%s", role, type); 434e5b75505Sopenharmony_ci ret = -1; 435e5b75505Sopenharmony_ci } 436e5b75505Sopenharmony_ci wpabuf_free(req); 437e5b75505Sopenharmony_ci wpabuf_free(sel); 438e5b75505Sopenharmony_ci 439e5b75505Sopenharmony_ci return ret; 440e5b75505Sopenharmony_ci} 441e5b75505Sopenharmony_ci 442e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_NFC */ 443e5b75505Sopenharmony_ci 444e5b75505Sopenharmony_ci 445e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 446e5b75505Sopenharmony_ci char *buf, size_t buflen) 447e5b75505Sopenharmony_ci{ 448e5b75505Sopenharmony_ci int timeout = 300; 449e5b75505Sopenharmony_ci char *pos; 450e5b75505Sopenharmony_ci const char *pin_txt; 451e5b75505Sopenharmony_ci 452e5b75505Sopenharmony_ci pos = os_strchr(txt, ' '); 453e5b75505Sopenharmony_ci if (pos) 454e5b75505Sopenharmony_ci *pos++ = '\0'; 455e5b75505Sopenharmony_ci 456e5b75505Sopenharmony_ci if (os_strcmp(txt, "disable") == 0) { 457e5b75505Sopenharmony_ci hostapd_wps_ap_pin_disable(hapd); 458e5b75505Sopenharmony_ci return os_snprintf(buf, buflen, "OK\n"); 459e5b75505Sopenharmony_ci } 460e5b75505Sopenharmony_ci 461e5b75505Sopenharmony_ci if (os_strcmp(txt, "random") == 0) { 462e5b75505Sopenharmony_ci if (pos) 463e5b75505Sopenharmony_ci timeout = atoi(pos); 464e5b75505Sopenharmony_ci pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 465e5b75505Sopenharmony_ci if (pin_txt == NULL) 466e5b75505Sopenharmony_ci return -1; 467e5b75505Sopenharmony_ci return os_snprintf(buf, buflen, "%s", pin_txt); 468e5b75505Sopenharmony_ci } 469e5b75505Sopenharmony_ci 470e5b75505Sopenharmony_ci if (os_strcmp(txt, "get") == 0) { 471e5b75505Sopenharmony_ci pin_txt = hostapd_wps_ap_pin_get(hapd); 472e5b75505Sopenharmony_ci if (pin_txt == NULL) 473e5b75505Sopenharmony_ci return -1; 474e5b75505Sopenharmony_ci return os_snprintf(buf, buflen, "%s", pin_txt); 475e5b75505Sopenharmony_ci } 476e5b75505Sopenharmony_ci 477e5b75505Sopenharmony_ci if (os_strcmp(txt, "set") == 0) { 478e5b75505Sopenharmony_ci char *pin; 479e5b75505Sopenharmony_ci if (pos == NULL) 480e5b75505Sopenharmony_ci return -1; 481e5b75505Sopenharmony_ci pin = pos; 482e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 483e5b75505Sopenharmony_ci if (pos) { 484e5b75505Sopenharmony_ci *pos++ = '\0'; 485e5b75505Sopenharmony_ci timeout = atoi(pos); 486e5b75505Sopenharmony_ci } 487e5b75505Sopenharmony_ci if (os_strlen(pin) > buflen) 488e5b75505Sopenharmony_ci return -1; 489e5b75505Sopenharmony_ci if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 490e5b75505Sopenharmony_ci return -1; 491e5b75505Sopenharmony_ci return os_snprintf(buf, buflen, "%s", pin); 492e5b75505Sopenharmony_ci } 493e5b75505Sopenharmony_ci 494e5b75505Sopenharmony_ci return -1; 495e5b75505Sopenharmony_ci} 496e5b75505Sopenharmony_ci 497e5b75505Sopenharmony_ci 498e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 499e5b75505Sopenharmony_ci{ 500e5b75505Sopenharmony_ci char *pos; 501e5b75505Sopenharmony_ci char *ssid, *auth, *encr = NULL, *key = NULL; 502e5b75505Sopenharmony_ci 503e5b75505Sopenharmony_ci ssid = txt; 504e5b75505Sopenharmony_ci pos = os_strchr(txt, ' '); 505e5b75505Sopenharmony_ci if (!pos) 506e5b75505Sopenharmony_ci return -1; 507e5b75505Sopenharmony_ci *pos++ = '\0'; 508e5b75505Sopenharmony_ci 509e5b75505Sopenharmony_ci auth = pos; 510e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 511e5b75505Sopenharmony_ci if (pos) { 512e5b75505Sopenharmony_ci *pos++ = '\0'; 513e5b75505Sopenharmony_ci encr = pos; 514e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 515e5b75505Sopenharmony_ci if (pos) { 516e5b75505Sopenharmony_ci *pos++ = '\0'; 517e5b75505Sopenharmony_ci key = pos; 518e5b75505Sopenharmony_ci } 519e5b75505Sopenharmony_ci } 520e5b75505Sopenharmony_ci 521e5b75505Sopenharmony_ci return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 522e5b75505Sopenharmony_ci} 523e5b75505Sopenharmony_ci 524e5b75505Sopenharmony_ci 525e5b75505Sopenharmony_cistatic const char * pbc_status_str(enum pbc_status status) 526e5b75505Sopenharmony_ci{ 527e5b75505Sopenharmony_ci switch (status) { 528e5b75505Sopenharmony_ci case WPS_PBC_STATUS_DISABLE: 529e5b75505Sopenharmony_ci return "Disabled"; 530e5b75505Sopenharmony_ci case WPS_PBC_STATUS_ACTIVE: 531e5b75505Sopenharmony_ci return "Active"; 532e5b75505Sopenharmony_ci case WPS_PBC_STATUS_TIMEOUT: 533e5b75505Sopenharmony_ci return "Timed-out"; 534e5b75505Sopenharmony_ci case WPS_PBC_STATUS_OVERLAP: 535e5b75505Sopenharmony_ci return "Overlap"; 536e5b75505Sopenharmony_ci default: 537e5b75505Sopenharmony_ci return "Unknown"; 538e5b75505Sopenharmony_ci } 539e5b75505Sopenharmony_ci} 540e5b75505Sopenharmony_ci 541e5b75505Sopenharmony_ci 542e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, 543e5b75505Sopenharmony_ci char *buf, size_t buflen) 544e5b75505Sopenharmony_ci{ 545e5b75505Sopenharmony_ci int ret; 546e5b75505Sopenharmony_ci char *pos, *end; 547e5b75505Sopenharmony_ci 548e5b75505Sopenharmony_ci pos = buf; 549e5b75505Sopenharmony_ci end = buf + buflen; 550e5b75505Sopenharmony_ci 551e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "PBC Status: %s\n", 552e5b75505Sopenharmony_ci pbc_status_str(hapd->wps_stats.pbc_status)); 553e5b75505Sopenharmony_ci 554e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 555e5b75505Sopenharmony_ci return pos - buf; 556e5b75505Sopenharmony_ci pos += ret; 557e5b75505Sopenharmony_ci 558e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n", 559e5b75505Sopenharmony_ci (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? 560e5b75505Sopenharmony_ci "Success": 561e5b75505Sopenharmony_ci (hapd->wps_stats.status == WPS_STATUS_FAILURE ? 562e5b75505Sopenharmony_ci "Failed" : "None"))); 563e5b75505Sopenharmony_ci 564e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 565e5b75505Sopenharmony_ci return pos - buf; 566e5b75505Sopenharmony_ci pos += ret; 567e5b75505Sopenharmony_ci 568e5b75505Sopenharmony_ci /* If status == Failure - Add possible Reasons */ 569e5b75505Sopenharmony_ci if(hapd->wps_stats.status == WPS_STATUS_FAILURE && 570e5b75505Sopenharmony_ci hapd->wps_stats.failure_reason > 0) { 571e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, 572e5b75505Sopenharmony_ci "Failure Reason: %s\n", 573e5b75505Sopenharmony_ci wps_ei_str(hapd->wps_stats.failure_reason)); 574e5b75505Sopenharmony_ci 575e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 576e5b75505Sopenharmony_ci return pos - buf; 577e5b75505Sopenharmony_ci pos += ret; 578e5b75505Sopenharmony_ci } 579e5b75505Sopenharmony_ci 580e5b75505Sopenharmony_ci if (hapd->wps_stats.status) { 581e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", 582e5b75505Sopenharmony_ci MAC2STR(hapd->wps_stats.peer_addr)); 583e5b75505Sopenharmony_ci 584e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 585e5b75505Sopenharmony_ci return pos - buf; 586e5b75505Sopenharmony_ci pos += ret; 587e5b75505Sopenharmony_ci } 588e5b75505Sopenharmony_ci 589e5b75505Sopenharmony_ci return pos - buf; 590e5b75505Sopenharmony_ci} 591e5b75505Sopenharmony_ci 592e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 593e5b75505Sopenharmony_ci 594e5b75505Sopenharmony_ci#ifdef CONFIG_HS20 595e5b75505Sopenharmony_ci 596e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd, 597e5b75505Sopenharmony_ci const char *cmd) 598e5b75505Sopenharmony_ci{ 599e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 600e5b75505Sopenharmony_ci const char *url; 601e5b75505Sopenharmony_ci 602e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 603e5b75505Sopenharmony_ci return -1; 604e5b75505Sopenharmony_ci url = cmd + 17; 605e5b75505Sopenharmony_ci if (*url == '\0') { 606e5b75505Sopenharmony_ci url = NULL; 607e5b75505Sopenharmony_ci } else { 608e5b75505Sopenharmony_ci if (*url != ' ') 609e5b75505Sopenharmony_ci return -1; 610e5b75505Sopenharmony_ci url++; 611e5b75505Sopenharmony_ci if (*url == '\0') 612e5b75505Sopenharmony_ci url = NULL; 613e5b75505Sopenharmony_ci } 614e5b75505Sopenharmony_ci 615e5b75505Sopenharmony_ci return hs20_send_wnm_notification(hapd, addr, 1, url); 616e5b75505Sopenharmony_ci} 617e5b75505Sopenharmony_ci 618e5b75505Sopenharmony_ci 619e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd, 620e5b75505Sopenharmony_ci const char *cmd) 621e5b75505Sopenharmony_ci{ 622e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 623e5b75505Sopenharmony_ci int code, reauth_delay, ret; 624e5b75505Sopenharmony_ci const char *pos; 625e5b75505Sopenharmony_ci size_t url_len; 626e5b75505Sopenharmony_ci struct wpabuf *req; 627e5b75505Sopenharmony_ci 628e5b75505Sopenharmony_ci /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */ 629e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 630e5b75505Sopenharmony_ci return -1; 631e5b75505Sopenharmony_ci 632e5b75505Sopenharmony_ci pos = os_strchr(cmd, ' '); 633e5b75505Sopenharmony_ci if (pos == NULL) 634e5b75505Sopenharmony_ci return -1; 635e5b75505Sopenharmony_ci pos++; 636e5b75505Sopenharmony_ci code = atoi(pos); 637e5b75505Sopenharmony_ci 638e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 639e5b75505Sopenharmony_ci if (pos == NULL) 640e5b75505Sopenharmony_ci return -1; 641e5b75505Sopenharmony_ci pos++; 642e5b75505Sopenharmony_ci reauth_delay = atoi(pos); 643e5b75505Sopenharmony_ci 644e5b75505Sopenharmony_ci url_len = 0; 645e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 646e5b75505Sopenharmony_ci if (pos) { 647e5b75505Sopenharmony_ci pos++; 648e5b75505Sopenharmony_ci url_len = os_strlen(pos); 649e5b75505Sopenharmony_ci } 650e5b75505Sopenharmony_ci 651e5b75505Sopenharmony_ci req = wpabuf_alloc(4 + url_len); 652e5b75505Sopenharmony_ci if (req == NULL) 653e5b75505Sopenharmony_ci return -1; 654e5b75505Sopenharmony_ci wpabuf_put_u8(req, code); 655e5b75505Sopenharmony_ci wpabuf_put_le16(req, reauth_delay); 656e5b75505Sopenharmony_ci wpabuf_put_u8(req, url_len); 657e5b75505Sopenharmony_ci if (pos) 658e5b75505Sopenharmony_ci wpabuf_put_data(req, pos, url_len); 659e5b75505Sopenharmony_ci 660e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR 661e5b75505Sopenharmony_ci " to indicate imminent deauthentication (code=%d " 662e5b75505Sopenharmony_ci "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay); 663e5b75505Sopenharmony_ci ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req); 664e5b75505Sopenharmony_ci wpabuf_free(req); 665e5b75505Sopenharmony_ci return ret; 666e5b75505Sopenharmony_ci} 667e5b75505Sopenharmony_ci 668e5b75505Sopenharmony_ci#endif /* CONFIG_HS20 */ 669e5b75505Sopenharmony_ci 670e5b75505Sopenharmony_ci 671e5b75505Sopenharmony_ci#ifdef CONFIG_INTERWORKING 672e5b75505Sopenharmony_ci 673e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd, 674e5b75505Sopenharmony_ci const char *cmd) 675e5b75505Sopenharmony_ci{ 676e5b75505Sopenharmony_ci u8 qos_map_set[16 + 2 * 21], count = 0; 677e5b75505Sopenharmony_ci const char *pos = cmd; 678e5b75505Sopenharmony_ci int val, ret; 679e5b75505Sopenharmony_ci 680e5b75505Sopenharmony_ci for (;;) { 681e5b75505Sopenharmony_ci if (count == sizeof(qos_map_set)) { 682e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Too many qos_map_set parameters"); 683e5b75505Sopenharmony_ci return -1; 684e5b75505Sopenharmony_ci } 685e5b75505Sopenharmony_ci 686e5b75505Sopenharmony_ci val = atoi(pos); 687e5b75505Sopenharmony_ci if (val < 0 || val > 255) { 688e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 689e5b75505Sopenharmony_ci return -1; 690e5b75505Sopenharmony_ci } 691e5b75505Sopenharmony_ci 692e5b75505Sopenharmony_ci qos_map_set[count++] = val; 693e5b75505Sopenharmony_ci pos = os_strchr(pos, ','); 694e5b75505Sopenharmony_ci if (!pos) 695e5b75505Sopenharmony_ci break; 696e5b75505Sopenharmony_ci pos++; 697e5b75505Sopenharmony_ci } 698e5b75505Sopenharmony_ci 699e5b75505Sopenharmony_ci if (count < 16 || count & 1) { 700e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 701e5b75505Sopenharmony_ci return -1; 702e5b75505Sopenharmony_ci } 703e5b75505Sopenharmony_ci 704e5b75505Sopenharmony_ci ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count); 705e5b75505Sopenharmony_ci if (ret) { 706e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Failed to set QoS Map Set"); 707e5b75505Sopenharmony_ci return -1; 708e5b75505Sopenharmony_ci } 709e5b75505Sopenharmony_ci 710e5b75505Sopenharmony_ci os_memcpy(hapd->conf->qos_map_set, qos_map_set, count); 711e5b75505Sopenharmony_ci hapd->conf->qos_map_set_len = count; 712e5b75505Sopenharmony_ci 713e5b75505Sopenharmony_ci return 0; 714e5b75505Sopenharmony_ci} 715e5b75505Sopenharmony_ci 716e5b75505Sopenharmony_ci 717e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, 718e5b75505Sopenharmony_ci const char *cmd) 719e5b75505Sopenharmony_ci{ 720e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 721e5b75505Sopenharmony_ci struct sta_info *sta; 722e5b75505Sopenharmony_ci struct wpabuf *buf; 723e5b75505Sopenharmony_ci u8 *qos_map_set = hapd->conf->qos_map_set; 724e5b75505Sopenharmony_ci u8 qos_map_set_len = hapd->conf->qos_map_set_len; 725e5b75505Sopenharmony_ci int ret; 726e5b75505Sopenharmony_ci 727e5b75505Sopenharmony_ci if (!qos_map_set_len) { 728e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "QoS Map Set is not set"); 729e5b75505Sopenharmony_ci return -1; 730e5b75505Sopenharmony_ci } 731e5b75505Sopenharmony_ci 732e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 733e5b75505Sopenharmony_ci return -1; 734e5b75505Sopenharmony_ci 735e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 736e5b75505Sopenharmony_ci if (sta == NULL) { 737e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 738e5b75505Sopenharmony_ci "for QoS Map Configuration message", 739e5b75505Sopenharmony_ci MAC2STR(addr)); 740e5b75505Sopenharmony_ci return -1; 741e5b75505Sopenharmony_ci } 742e5b75505Sopenharmony_ci 743e5b75505Sopenharmony_ci if (!sta->qos_map_enabled) { 744e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate " 745e5b75505Sopenharmony_ci "support for QoS Map", MAC2STR(addr)); 746e5b75505Sopenharmony_ci return -1; 747e5b75505Sopenharmony_ci } 748e5b75505Sopenharmony_ci 749e5b75505Sopenharmony_ci buf = wpabuf_alloc(2 + 2 + qos_map_set_len); 750e5b75505Sopenharmony_ci if (buf == NULL) 751e5b75505Sopenharmony_ci return -1; 752e5b75505Sopenharmony_ci 753e5b75505Sopenharmony_ci wpabuf_put_u8(buf, WLAN_ACTION_QOS); 754e5b75505Sopenharmony_ci wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG); 755e5b75505Sopenharmony_ci 756e5b75505Sopenharmony_ci /* QoS Map Set Element */ 757e5b75505Sopenharmony_ci wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET); 758e5b75505Sopenharmony_ci wpabuf_put_u8(buf, qos_map_set_len); 759e5b75505Sopenharmony_ci wpabuf_put_data(buf, qos_map_set, qos_map_set_len); 760e5b75505Sopenharmony_ci 761e5b75505Sopenharmony_ci ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 762e5b75505Sopenharmony_ci wpabuf_head(buf), wpabuf_len(buf)); 763e5b75505Sopenharmony_ci wpabuf_free(buf); 764e5b75505Sopenharmony_ci 765e5b75505Sopenharmony_ci return ret; 766e5b75505Sopenharmony_ci} 767e5b75505Sopenharmony_ci 768e5b75505Sopenharmony_ci#endif /* CONFIG_INTERWORKING */ 769e5b75505Sopenharmony_ci 770e5b75505Sopenharmony_ci 771e5b75505Sopenharmony_ci#ifdef CONFIG_WNM_AP 772e5b75505Sopenharmony_ci 773e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, 774e5b75505Sopenharmony_ci const char *cmd) 775e5b75505Sopenharmony_ci{ 776e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 777e5b75505Sopenharmony_ci int disassoc_timer; 778e5b75505Sopenharmony_ci struct sta_info *sta; 779e5b75505Sopenharmony_ci 780e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 781e5b75505Sopenharmony_ci return -1; 782e5b75505Sopenharmony_ci if (cmd[17] != ' ') 783e5b75505Sopenharmony_ci return -1; 784e5b75505Sopenharmony_ci disassoc_timer = atoi(cmd + 17); 785e5b75505Sopenharmony_ci 786e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 787e5b75505Sopenharmony_ci if (sta == NULL) { 788e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Station " MACSTR 789e5b75505Sopenharmony_ci " not found for disassociation imminent message", 790e5b75505Sopenharmony_ci MAC2STR(addr)); 791e5b75505Sopenharmony_ci return -1; 792e5b75505Sopenharmony_ci } 793e5b75505Sopenharmony_ci 794e5b75505Sopenharmony_ci return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); 795e5b75505Sopenharmony_ci} 796e5b75505Sopenharmony_ci 797e5b75505Sopenharmony_ci 798e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 799e5b75505Sopenharmony_ci const char *cmd) 800e5b75505Sopenharmony_ci{ 801e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 802e5b75505Sopenharmony_ci const char *url, *timerstr; 803e5b75505Sopenharmony_ci int disassoc_timer; 804e5b75505Sopenharmony_ci struct sta_info *sta; 805e5b75505Sopenharmony_ci 806e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 807e5b75505Sopenharmony_ci return -1; 808e5b75505Sopenharmony_ci 809e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 810e5b75505Sopenharmony_ci if (sta == NULL) { 811e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Station " MACSTR 812e5b75505Sopenharmony_ci " not found for ESS disassociation imminent message", 813e5b75505Sopenharmony_ci MAC2STR(addr)); 814e5b75505Sopenharmony_ci return -1; 815e5b75505Sopenharmony_ci } 816e5b75505Sopenharmony_ci 817e5b75505Sopenharmony_ci timerstr = cmd + 17; 818e5b75505Sopenharmony_ci if (*timerstr != ' ') 819e5b75505Sopenharmony_ci return -1; 820e5b75505Sopenharmony_ci timerstr++; 821e5b75505Sopenharmony_ci disassoc_timer = atoi(timerstr); 822e5b75505Sopenharmony_ci if (disassoc_timer < 0 || disassoc_timer > 65535) 823e5b75505Sopenharmony_ci return -1; 824e5b75505Sopenharmony_ci 825e5b75505Sopenharmony_ci url = os_strchr(timerstr, ' '); 826e5b75505Sopenharmony_ci if (url == NULL) 827e5b75505Sopenharmony_ci return -1; 828e5b75505Sopenharmony_ci url++; 829e5b75505Sopenharmony_ci 830e5b75505Sopenharmony_ci return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); 831e5b75505Sopenharmony_ci} 832e5b75505Sopenharmony_ci 833e5b75505Sopenharmony_ci 834e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, 835e5b75505Sopenharmony_ci const char *cmd) 836e5b75505Sopenharmony_ci{ 837e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 838e5b75505Sopenharmony_ci const char *pos, *end; 839e5b75505Sopenharmony_ci int disassoc_timer = 0; 840e5b75505Sopenharmony_ci struct sta_info *sta; 841e5b75505Sopenharmony_ci u8 req_mode = 0, valid_int = 0x01; 842e5b75505Sopenharmony_ci u8 bss_term_dur[12]; 843e5b75505Sopenharmony_ci char *url = NULL; 844e5b75505Sopenharmony_ci int ret; 845e5b75505Sopenharmony_ci u8 nei_rep[1000]; 846e5b75505Sopenharmony_ci int nei_len; 847e5b75505Sopenharmony_ci u8 mbo[10]; 848e5b75505Sopenharmony_ci size_t mbo_len = 0; 849e5b75505Sopenharmony_ci 850e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) { 851e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); 852e5b75505Sopenharmony_ci return -1; 853e5b75505Sopenharmony_ci } 854e5b75505Sopenharmony_ci 855e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 856e5b75505Sopenharmony_ci if (sta == NULL) { 857e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Station " MACSTR 858e5b75505Sopenharmony_ci " not found for BSS TM Request message", 859e5b75505Sopenharmony_ci MAC2STR(addr)); 860e5b75505Sopenharmony_ci return -1; 861e5b75505Sopenharmony_ci } 862e5b75505Sopenharmony_ci 863e5b75505Sopenharmony_ci pos = os_strstr(cmd, " disassoc_timer="); 864e5b75505Sopenharmony_ci if (pos) { 865e5b75505Sopenharmony_ci pos += 16; 866e5b75505Sopenharmony_ci disassoc_timer = atoi(pos); 867e5b75505Sopenharmony_ci if (disassoc_timer < 0 || disassoc_timer > 65535) { 868e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Invalid disassoc_timer"); 869e5b75505Sopenharmony_ci return -1; 870e5b75505Sopenharmony_ci } 871e5b75505Sopenharmony_ci } 872e5b75505Sopenharmony_ci 873e5b75505Sopenharmony_ci pos = os_strstr(cmd, " valid_int="); 874e5b75505Sopenharmony_ci if (pos) { 875e5b75505Sopenharmony_ci pos += 11; 876e5b75505Sopenharmony_ci valid_int = atoi(pos); 877e5b75505Sopenharmony_ci } 878e5b75505Sopenharmony_ci 879e5b75505Sopenharmony_ci pos = os_strstr(cmd, " bss_term="); 880e5b75505Sopenharmony_ci if (pos) { 881e5b75505Sopenharmony_ci pos += 10; 882e5b75505Sopenharmony_ci req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; 883e5b75505Sopenharmony_ci /* TODO: TSF configurable/learnable */ 884e5b75505Sopenharmony_ci bss_term_dur[0] = 4; /* Subelement ID */ 885e5b75505Sopenharmony_ci bss_term_dur[1] = 10; /* Length */ 886e5b75505Sopenharmony_ci os_memset(&bss_term_dur[2], 0, 8); 887e5b75505Sopenharmony_ci end = os_strchr(pos, ','); 888e5b75505Sopenharmony_ci if (end == NULL) { 889e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Invalid bss_term data"); 890e5b75505Sopenharmony_ci return -1; 891e5b75505Sopenharmony_ci } 892e5b75505Sopenharmony_ci end++; 893e5b75505Sopenharmony_ci WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); 894e5b75505Sopenharmony_ci } 895e5b75505Sopenharmony_ci 896e5b75505Sopenharmony_ci nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep, 897e5b75505Sopenharmony_ci sizeof(nei_rep)); 898e5b75505Sopenharmony_ci if (nei_len < 0) 899e5b75505Sopenharmony_ci return -1; 900e5b75505Sopenharmony_ci 901e5b75505Sopenharmony_ci pos = os_strstr(cmd, " url="); 902e5b75505Sopenharmony_ci if (pos) { 903e5b75505Sopenharmony_ci size_t len; 904e5b75505Sopenharmony_ci pos += 5; 905e5b75505Sopenharmony_ci end = os_strchr(pos, ' '); 906e5b75505Sopenharmony_ci if (end) 907e5b75505Sopenharmony_ci len = end - pos; 908e5b75505Sopenharmony_ci else 909e5b75505Sopenharmony_ci len = os_strlen(pos); 910e5b75505Sopenharmony_ci url = os_malloc(len + 1); 911e5b75505Sopenharmony_ci if (url == NULL) 912e5b75505Sopenharmony_ci return -1; 913e5b75505Sopenharmony_ci os_memcpy(url, pos, len); 914e5b75505Sopenharmony_ci url[len] = '\0'; 915e5b75505Sopenharmony_ci req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 916e5b75505Sopenharmony_ci } 917e5b75505Sopenharmony_ci 918e5b75505Sopenharmony_ci if (os_strstr(cmd, " pref=1")) 919e5b75505Sopenharmony_ci req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; 920e5b75505Sopenharmony_ci if (os_strstr(cmd, " abridged=1")) 921e5b75505Sopenharmony_ci req_mode |= WNM_BSS_TM_REQ_ABRIDGED; 922e5b75505Sopenharmony_ci if (os_strstr(cmd, " disassoc_imminent=1")) 923e5b75505Sopenharmony_ci req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; 924e5b75505Sopenharmony_ci 925e5b75505Sopenharmony_ci#ifdef CONFIG_MBO 926e5b75505Sopenharmony_ci pos = os_strstr(cmd, "mbo="); 927e5b75505Sopenharmony_ci if (pos) { 928e5b75505Sopenharmony_ci unsigned int mbo_reason, cell_pref, reassoc_delay; 929e5b75505Sopenharmony_ci u8 *mbo_pos = mbo; 930e5b75505Sopenharmony_ci 931e5b75505Sopenharmony_ci ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason, 932e5b75505Sopenharmony_ci &reassoc_delay, &cell_pref); 933e5b75505Sopenharmony_ci if (ret != 3) { 934e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 935e5b75505Sopenharmony_ci "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>"); 936e5b75505Sopenharmony_ci ret = -1; 937e5b75505Sopenharmony_ci goto fail; 938e5b75505Sopenharmony_ci } 939e5b75505Sopenharmony_ci 940e5b75505Sopenharmony_ci if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) { 941e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 942e5b75505Sopenharmony_ci "Invalid MBO transition reason code %u", 943e5b75505Sopenharmony_ci mbo_reason); 944e5b75505Sopenharmony_ci ret = -1; 945e5b75505Sopenharmony_ci goto fail; 946e5b75505Sopenharmony_ci } 947e5b75505Sopenharmony_ci 948e5b75505Sopenharmony_ci /* Valid values for Cellular preference are: 0, 1, 255 */ 949e5b75505Sopenharmony_ci if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) { 950e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 951e5b75505Sopenharmony_ci "Invalid MBO cellular capability %u", 952e5b75505Sopenharmony_ci cell_pref); 953e5b75505Sopenharmony_ci ret = -1; 954e5b75505Sopenharmony_ci goto fail; 955e5b75505Sopenharmony_ci } 956e5b75505Sopenharmony_ci 957e5b75505Sopenharmony_ci if (reassoc_delay > 65535 || 958e5b75505Sopenharmony_ci (reassoc_delay && 959e5b75505Sopenharmony_ci !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) { 960e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 961e5b75505Sopenharmony_ci "MBO: Assoc retry delay is only valid in disassoc imminent mode"); 962e5b75505Sopenharmony_ci ret = -1; 963e5b75505Sopenharmony_ci goto fail; 964e5b75505Sopenharmony_ci } 965e5b75505Sopenharmony_ci 966e5b75505Sopenharmony_ci *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON; 967e5b75505Sopenharmony_ci *mbo_pos++ = 1; 968e5b75505Sopenharmony_ci *mbo_pos++ = mbo_reason; 969e5b75505Sopenharmony_ci *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF; 970e5b75505Sopenharmony_ci *mbo_pos++ = 1; 971e5b75505Sopenharmony_ci *mbo_pos++ = cell_pref; 972e5b75505Sopenharmony_ci 973e5b75505Sopenharmony_ci if (reassoc_delay) { 974e5b75505Sopenharmony_ci *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY; 975e5b75505Sopenharmony_ci *mbo_pos++ = 2; 976e5b75505Sopenharmony_ci WPA_PUT_LE16(mbo_pos, reassoc_delay); 977e5b75505Sopenharmony_ci mbo_pos += 2; 978e5b75505Sopenharmony_ci } 979e5b75505Sopenharmony_ci 980e5b75505Sopenharmony_ci mbo_len = mbo_pos - mbo; 981e5b75505Sopenharmony_ci } 982e5b75505Sopenharmony_ci#endif /* CONFIG_MBO */ 983e5b75505Sopenharmony_ci 984e5b75505Sopenharmony_ci ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, 985e5b75505Sopenharmony_ci valid_int, bss_term_dur, url, 986e5b75505Sopenharmony_ci nei_len ? nei_rep : NULL, nei_len, 987e5b75505Sopenharmony_ci mbo_len ? mbo : NULL, mbo_len); 988e5b75505Sopenharmony_ci#ifdef CONFIG_MBO 989e5b75505Sopenharmony_cifail: 990e5b75505Sopenharmony_ci#endif /* CONFIG_MBO */ 991e5b75505Sopenharmony_ci os_free(url); 992e5b75505Sopenharmony_ci return ret; 993e5b75505Sopenharmony_ci} 994e5b75505Sopenharmony_ci 995e5b75505Sopenharmony_ci 996e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd, 997e5b75505Sopenharmony_ci const char *cmd) 998e5b75505Sopenharmony_ci{ 999e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 1000e5b75505Sopenharmony_ci struct sta_info *sta; 1001e5b75505Sopenharmony_ci const char *pos; 1002e5b75505Sopenharmony_ci unsigned int auto_report, timeout; 1003e5b75505Sopenharmony_ci 1004e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) { 1005e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); 1006e5b75505Sopenharmony_ci return -1; 1007e5b75505Sopenharmony_ci } 1008e5b75505Sopenharmony_ci 1009e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 1010e5b75505Sopenharmony_ci if (!sta) { 1011e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Station " MACSTR 1012e5b75505Sopenharmony_ci " not found for Collocated Interference Request", 1013e5b75505Sopenharmony_ci MAC2STR(addr)); 1014e5b75505Sopenharmony_ci return -1; 1015e5b75505Sopenharmony_ci } 1016e5b75505Sopenharmony_ci 1017e5b75505Sopenharmony_ci pos = cmd + 17; 1018e5b75505Sopenharmony_ci if (*pos != ' ') 1019e5b75505Sopenharmony_ci return -1; 1020e5b75505Sopenharmony_ci pos++; 1021e5b75505Sopenharmony_ci auto_report = atoi(pos); 1022e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 1023e5b75505Sopenharmony_ci if (!pos) 1024e5b75505Sopenharmony_ci return -1; 1025e5b75505Sopenharmony_ci pos++; 1026e5b75505Sopenharmony_ci timeout = atoi(pos); 1027e5b75505Sopenharmony_ci 1028e5b75505Sopenharmony_ci return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout); 1029e5b75505Sopenharmony_ci} 1030e5b75505Sopenharmony_ci 1031e5b75505Sopenharmony_ci#endif /* CONFIG_WNM_AP */ 1032e5b75505Sopenharmony_ci 1033e5b75505Sopenharmony_ci 1034e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, 1035e5b75505Sopenharmony_ci char *buf, size_t buflen) 1036e5b75505Sopenharmony_ci{ 1037e5b75505Sopenharmony_ci int ret = 0; 1038e5b75505Sopenharmony_ci char *pos, *end; 1039e5b75505Sopenharmony_ci 1040e5b75505Sopenharmony_ci pos = buf; 1041e5b75505Sopenharmony_ci end = buf + buflen; 1042e5b75505Sopenharmony_ci 1043e5b75505Sopenharmony_ci WPA_ASSERT(hapd->conf->wpa_key_mgmt); 1044e5b75505Sopenharmony_ci 1045e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 1046e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "WPA-PSK "); 1047e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1048e5b75505Sopenharmony_ci return pos - buf; 1049e5b75505Sopenharmony_ci pos += ret; 1050e5b75505Sopenharmony_ci } 1051e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1052e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "WPA-EAP "); 1053e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1054e5b75505Sopenharmony_ci return pos - buf; 1055e5b75505Sopenharmony_ci pos += ret; 1056e5b75505Sopenharmony_ci } 1057e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211R_AP 1058e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1059e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FT-PSK "); 1060e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1061e5b75505Sopenharmony_ci return pos - buf; 1062e5b75505Sopenharmony_ci pos += ret; 1063e5b75505Sopenharmony_ci } 1064e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1065e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FT-EAP "); 1066e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1067e5b75505Sopenharmony_ci return pos - buf; 1068e5b75505Sopenharmony_ci pos += ret; 1069e5b75505Sopenharmony_ci } 1070e5b75505Sopenharmony_ci#ifdef CONFIG_SHA384 1071e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { 1072e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FT-EAP-SHA384 "); 1073e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1074e5b75505Sopenharmony_ci return pos - buf; 1075e5b75505Sopenharmony_ci pos += ret; 1076e5b75505Sopenharmony_ci } 1077e5b75505Sopenharmony_ci#endif /* CONFIG_SHA384 */ 1078e5b75505Sopenharmony_ci#ifdef CONFIG_SAE 1079e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 1080e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FT-SAE "); 1081e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1082e5b75505Sopenharmony_ci return pos - buf; 1083e5b75505Sopenharmony_ci pos += ret; 1084e5b75505Sopenharmony_ci } 1085e5b75505Sopenharmony_ci#endif /* CONFIG_SAE */ 1086e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 1087e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { 1088e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 "); 1089e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1090e5b75505Sopenharmony_ci return pos - buf; 1091e5b75505Sopenharmony_ci pos += ret; 1092e5b75505Sopenharmony_ci } 1093e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { 1094e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 "); 1095e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1096e5b75505Sopenharmony_ci return pos - buf; 1097e5b75505Sopenharmony_ci pos += ret; 1098e5b75505Sopenharmony_ci } 1099e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 1100e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211R_AP */ 1101e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 1102e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1103e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 1104e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1105e5b75505Sopenharmony_ci return pos - buf; 1106e5b75505Sopenharmony_ci pos += ret; 1107e5b75505Sopenharmony_ci } 1108e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1109e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 1110e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1111e5b75505Sopenharmony_ci return pos - buf; 1112e5b75505Sopenharmony_ci pos += ret; 1113e5b75505Sopenharmony_ci } 1114e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 1115e5b75505Sopenharmony_ci#ifdef CONFIG_SAE 1116e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 1117e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "SAE "); 1118e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1119e5b75505Sopenharmony_ci return pos - buf; 1120e5b75505Sopenharmony_ci pos += ret; 1121e5b75505Sopenharmony_ci } 1122e5b75505Sopenharmony_ci#endif /* CONFIG_SAE */ 1123e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 1124e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B "); 1125e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1126e5b75505Sopenharmony_ci return pos - buf; 1127e5b75505Sopenharmony_ci pos += ret; 1128e5b75505Sopenharmony_ci } 1129e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & 1130e5b75505Sopenharmony_ci WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 1131e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, 1132e5b75505Sopenharmony_ci "WPA-EAP-SUITE-B-192 "); 1133e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1134e5b75505Sopenharmony_ci return pos - buf; 1135e5b75505Sopenharmony_ci pos += ret; 1136e5b75505Sopenharmony_ci } 1137e5b75505Sopenharmony_ci#ifdef CONFIG_FILS 1138e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { 1139e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FILS-SHA256 "); 1140e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1141e5b75505Sopenharmony_ci return pos - buf; 1142e5b75505Sopenharmony_ci pos += ret; 1143e5b75505Sopenharmony_ci } 1144e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { 1145e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "FILS-SHA384 "); 1146e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1147e5b75505Sopenharmony_ci return pos - buf; 1148e5b75505Sopenharmony_ci pos += ret; 1149e5b75505Sopenharmony_ci } 1150e5b75505Sopenharmony_ci#endif /* CONFIG_FILS */ 1151e5b75505Sopenharmony_ci 1152e5b75505Sopenharmony_ci#ifdef CONFIG_OWE 1153e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) { 1154e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "OWE "); 1155e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1156e5b75505Sopenharmony_ci return pos - buf; 1157e5b75505Sopenharmony_ci pos += ret; 1158e5b75505Sopenharmony_ci } 1159e5b75505Sopenharmony_ci#endif /* CONFIG_OWE */ 1160e5b75505Sopenharmony_ci 1161e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 1162e5b75505Sopenharmony_ci if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) { 1163e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "DPP "); 1164e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1165e5b75505Sopenharmony_ci return pos - buf; 1166e5b75505Sopenharmony_ci pos += ret; 1167e5b75505Sopenharmony_ci } 1168e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 1169e5b75505Sopenharmony_ci 1170e5b75505Sopenharmony_ci if (pos > buf && *(pos - 1) == ' ') { 1171e5b75505Sopenharmony_ci *(pos - 1) = '\0'; 1172e5b75505Sopenharmony_ci pos--; 1173e5b75505Sopenharmony_ci } 1174e5b75505Sopenharmony_ci 1175e5b75505Sopenharmony_ci return pos - buf; 1176e5b75505Sopenharmony_ci} 1177e5b75505Sopenharmony_ci 1178e5b75505Sopenharmony_ci 1179e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 1180e5b75505Sopenharmony_ci char *buf, size_t buflen) 1181e5b75505Sopenharmony_ci{ 1182e5b75505Sopenharmony_ci int ret; 1183e5b75505Sopenharmony_ci char *pos, *end; 1184e5b75505Sopenharmony_ci 1185e5b75505Sopenharmony_ci pos = buf; 1186e5b75505Sopenharmony_ci end = buf + buflen; 1187e5b75505Sopenharmony_ci 1188e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 1189e5b75505Sopenharmony_ci "ssid=%s\n", 1190e5b75505Sopenharmony_ci MAC2STR(hapd->own_addr), 1191e5b75505Sopenharmony_ci wpa_ssid_txt(hapd->conf->ssid.ssid, 1192e5b75505Sopenharmony_ci hapd->conf->ssid.ssid_len)); 1193e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1194e5b75505Sopenharmony_ci return pos - buf; 1195e5b75505Sopenharmony_ci pos += ret; 1196e5b75505Sopenharmony_ci 1197e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 1198e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 1199e5b75505Sopenharmony_ci hapd->conf->wps_state == 0 ? "disabled" : 1200e5b75505Sopenharmony_ci (hapd->conf->wps_state == 1 ? "not configured" : 1201e5b75505Sopenharmony_ci "configured")); 1202e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1203e5b75505Sopenharmony_ci return pos - buf; 1204e5b75505Sopenharmony_ci pos += ret; 1205e5b75505Sopenharmony_ci 1206e5b75505Sopenharmony_ci if (hapd->conf->wps_state && hapd->conf->wpa && 1207e5b75505Sopenharmony_ci hapd->conf->ssid.wpa_passphrase) { 1208e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 1209e5b75505Sopenharmony_ci hapd->conf->ssid.wpa_passphrase); 1210e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1211e5b75505Sopenharmony_ci return pos - buf; 1212e5b75505Sopenharmony_ci pos += ret; 1213e5b75505Sopenharmony_ci } 1214e5b75505Sopenharmony_ci 1215e5b75505Sopenharmony_ci if (hapd->conf->wps_state && hapd->conf->wpa && 1216e5b75505Sopenharmony_ci hapd->conf->ssid.wpa_psk && 1217e5b75505Sopenharmony_ci hapd->conf->ssid.wpa_psk->group) { 1218e5b75505Sopenharmony_ci char hex[PMK_LEN * 2 + 1]; 1219e5b75505Sopenharmony_ci wpa_snprintf_hex(hex, sizeof(hex), 1220e5b75505Sopenharmony_ci hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 1221e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 1222e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1223e5b75505Sopenharmony_ci return pos - buf; 1224e5b75505Sopenharmony_ci pos += ret; 1225e5b75505Sopenharmony_ci } 1226e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 1227e5b75505Sopenharmony_ci 1228e5b75505Sopenharmony_ci if (hapd->conf->wpa) { 1229e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa); 1230e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1231e5b75505Sopenharmony_ci return pos - buf; 1232e5b75505Sopenharmony_ci pos += ret; 1233e5b75505Sopenharmony_ci } 1234e5b75505Sopenharmony_ci 1235e5b75505Sopenharmony_ci if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 1236e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "key_mgmt="); 1237e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1238e5b75505Sopenharmony_ci return pos - buf; 1239e5b75505Sopenharmony_ci pos += ret; 1240e5b75505Sopenharmony_ci 1241e5b75505Sopenharmony_ci pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos); 1242e5b75505Sopenharmony_ci 1243e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "\n"); 1244e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1245e5b75505Sopenharmony_ci return pos - buf; 1246e5b75505Sopenharmony_ci pos += ret; 1247e5b75505Sopenharmony_ci } 1248e5b75505Sopenharmony_ci 1249e5b75505Sopenharmony_ci if (hapd->conf->wpa) { 1250e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 1251e5b75505Sopenharmony_ci wpa_cipher_txt(hapd->conf->wpa_group)); 1252e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1253e5b75505Sopenharmony_ci return pos - buf; 1254e5b75505Sopenharmony_ci pos += ret; 1255e5b75505Sopenharmony_ci } 1256e5b75505Sopenharmony_ci 1257e5b75505Sopenharmony_ci if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 1258e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 1259e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1260e5b75505Sopenharmony_ci return pos - buf; 1261e5b75505Sopenharmony_ci pos += ret; 1262e5b75505Sopenharmony_ci 1263e5b75505Sopenharmony_ci ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 1264e5b75505Sopenharmony_ci " "); 1265e5b75505Sopenharmony_ci if (ret < 0) 1266e5b75505Sopenharmony_ci return pos - buf; 1267e5b75505Sopenharmony_ci pos += ret; 1268e5b75505Sopenharmony_ci 1269e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "\n"); 1270e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1271e5b75505Sopenharmony_ci return pos - buf; 1272e5b75505Sopenharmony_ci pos += ret; 1273e5b75505Sopenharmony_ci } 1274e5b75505Sopenharmony_ci 1275e5b75505Sopenharmony_ci if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 1276e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 1277e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1278e5b75505Sopenharmony_ci return pos - buf; 1279e5b75505Sopenharmony_ci pos += ret; 1280e5b75505Sopenharmony_ci 1281e5b75505Sopenharmony_ci ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise, 1282e5b75505Sopenharmony_ci " "); 1283e5b75505Sopenharmony_ci if (ret < 0) 1284e5b75505Sopenharmony_ci return pos - buf; 1285e5b75505Sopenharmony_ci pos += ret; 1286e5b75505Sopenharmony_ci 1287e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "\n"); 1288e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 1289e5b75505Sopenharmony_ci return pos - buf; 1290e5b75505Sopenharmony_ci pos += ret; 1291e5b75505Sopenharmony_ci } 1292e5b75505Sopenharmony_ci 1293e5b75505Sopenharmony_ci return pos - buf; 1294e5b75505Sopenharmony_ci} 1295e5b75505Sopenharmony_ci 1296e5b75505Sopenharmony_ci 1297e5b75505Sopenharmony_cistatic void hostapd_disassoc_accept_mac(struct hostapd_data *hapd) 1298e5b75505Sopenharmony_ci{ 1299e5b75505Sopenharmony_ci struct sta_info *sta; 1300e5b75505Sopenharmony_ci struct vlan_description vlan_id; 1301e5b75505Sopenharmony_ci 1302e5b75505Sopenharmony_ci if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED) 1303e5b75505Sopenharmony_ci return; 1304e5b75505Sopenharmony_ci 1305e5b75505Sopenharmony_ci for (sta = hapd->sta_list; sta; sta = sta->next) { 1306e5b75505Sopenharmony_ci if (!hostapd_maclist_found(hapd->conf->accept_mac, 1307e5b75505Sopenharmony_ci hapd->conf->num_accept_mac, 1308e5b75505Sopenharmony_ci sta->addr, &vlan_id) || 1309e5b75505Sopenharmony_ci (vlan_id.notempty && 1310e5b75505Sopenharmony_ci vlan_compare(&vlan_id, sta->vlan_desc))) 1311e5b75505Sopenharmony_ci ap_sta_disconnect(hapd, sta, sta->addr, 1312e5b75505Sopenharmony_ci WLAN_REASON_UNSPECIFIED); 1313e5b75505Sopenharmony_ci } 1314e5b75505Sopenharmony_ci} 1315e5b75505Sopenharmony_ci 1316e5b75505Sopenharmony_ci 1317e5b75505Sopenharmony_cistatic void hostapd_disassoc_deny_mac(struct hostapd_data *hapd) 1318e5b75505Sopenharmony_ci{ 1319e5b75505Sopenharmony_ci struct sta_info *sta; 1320e5b75505Sopenharmony_ci struct vlan_description vlan_id; 1321e5b75505Sopenharmony_ci 1322e5b75505Sopenharmony_ci for (sta = hapd->sta_list; sta; sta = sta->next) { 1323e5b75505Sopenharmony_ci if (hostapd_maclist_found(hapd->conf->deny_mac, 1324e5b75505Sopenharmony_ci hapd->conf->num_deny_mac, sta->addr, 1325e5b75505Sopenharmony_ci &vlan_id) && 1326e5b75505Sopenharmony_ci (!vlan_id.notempty || 1327e5b75505Sopenharmony_ci !vlan_compare(&vlan_id, sta->vlan_desc))) 1328e5b75505Sopenharmony_ci ap_sta_disconnect(hapd, sta, sta->addr, 1329e5b75505Sopenharmony_ci WLAN_REASON_UNSPECIFIED); 1330e5b75505Sopenharmony_ci } 1331e5b75505Sopenharmony_ci} 1332e5b75505Sopenharmony_ci 1333e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 1334e5b75505Sopenharmony_ci{ 1335e5b75505Sopenharmony_ci char *value; 1336e5b75505Sopenharmony_ci int ret = 0; 1337e5b75505Sopenharmony_ci 1338e5b75505Sopenharmony_ci value = os_strchr(cmd, ' '); 1339e5b75505Sopenharmony_ci if (value == NULL) 1340e5b75505Sopenharmony_ci return -1; 1341e5b75505Sopenharmony_ci *value++ = '\0'; 1342e5b75505Sopenharmony_ci 1343e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 1344e5b75505Sopenharmony_ci if (0) { 1345e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_TESTING 1346e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 1347e5b75505Sopenharmony_ci long int val; 1348e5b75505Sopenharmony_ci val = strtol(value, NULL, 0); 1349e5b75505Sopenharmony_ci if (val < 0 || val > 0xff) { 1350e5b75505Sopenharmony_ci ret = -1; 1351e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Invalid " 1352e5b75505Sopenharmony_ci "wps_version_number %ld", val); 1353e5b75505Sopenharmony_ci } else { 1354e5b75505Sopenharmony_ci wps_version_number = val; 1355e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 1356e5b75505Sopenharmony_ci "version %u.%u", 1357e5b75505Sopenharmony_ci (wps_version_number & 0xf0) >> 4, 1358e5b75505Sopenharmony_ci wps_version_number & 0x0f); 1359e5b75505Sopenharmony_ci hostapd_wps_update_ie(hapd); 1360e5b75505Sopenharmony_ci } 1361e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 1362e5b75505Sopenharmony_ci wps_testing_dummy_cred = atoi(value); 1363e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 1364e5b75505Sopenharmony_ci wps_testing_dummy_cred); 1365e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 1366e5b75505Sopenharmony_ci wps_corrupt_pkhash = atoi(value); 1367e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 1368e5b75505Sopenharmony_ci wps_corrupt_pkhash); 1369e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_TESTING */ 1370e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 1371e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 1372e5b75505Sopenharmony_ci hapd->ext_mgmt_frame_handling = atoi(value); 1373e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 1374e5b75505Sopenharmony_ci hapd->ext_eapol_frame_io = atoi(value); 1375e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 1376e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { 1377e5b75505Sopenharmony_ci os_free(hapd->dpp_config_obj_override); 1378e5b75505Sopenharmony_ci hapd->dpp_config_obj_override = os_strdup(value); 1379e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) { 1380e5b75505Sopenharmony_ci os_free(hapd->dpp_discovery_override); 1381e5b75505Sopenharmony_ci hapd->dpp_discovery_override = os_strdup(value); 1382e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) { 1383e5b75505Sopenharmony_ci os_free(hapd->dpp_groups_override); 1384e5b75505Sopenharmony_ci hapd->dpp_groups_override = os_strdup(value); 1385e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, 1386e5b75505Sopenharmony_ci "dpp_ignore_netaccesskey_mismatch") == 0) { 1387e5b75505Sopenharmony_ci hapd->dpp_ignore_netaccesskey_mismatch = atoi(value); 1388e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "dpp_test") == 0) { 1389e5b75505Sopenharmony_ci dpp_test = atoi(value); 1390e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 1391e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 1392e5b75505Sopenharmony_ci#ifdef CONFIG_MBO 1393e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) { 1394e5b75505Sopenharmony_ci int val; 1395e5b75505Sopenharmony_ci 1396e5b75505Sopenharmony_ci if (!hapd->conf->mbo_enabled) 1397e5b75505Sopenharmony_ci return -1; 1398e5b75505Sopenharmony_ci 1399e5b75505Sopenharmony_ci val = atoi(value); 1400e5b75505Sopenharmony_ci if (val < 0 || val > 1) 1401e5b75505Sopenharmony_ci return -1; 1402e5b75505Sopenharmony_ci 1403e5b75505Sopenharmony_ci hapd->mbo_assoc_disallow = val; 1404e5b75505Sopenharmony_ci ieee802_11_update_beacons(hapd->iface); 1405e5b75505Sopenharmony_ci 1406e5b75505Sopenharmony_ci /* 1407e5b75505Sopenharmony_ci * TODO: Need to configure drivers that do AP MLME offload with 1408e5b75505Sopenharmony_ci * disallowing station logic. 1409e5b75505Sopenharmony_ci */ 1410e5b75505Sopenharmony_ci#endif /* CONFIG_MBO */ 1411e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 1412e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { 1413e5b75505Sopenharmony_ci os_free(hapd->dpp_configurator_params); 1414e5b75505Sopenharmony_ci hapd->dpp_configurator_params = os_strdup(value); 1415e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 1416e5b75505Sopenharmony_ci } else { 1417e5b75505Sopenharmony_ci ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 1418e5b75505Sopenharmony_ci if (ret) 1419e5b75505Sopenharmony_ci return ret; 1420e5b75505Sopenharmony_ci 1421e5b75505Sopenharmony_ci if (os_strcasecmp(cmd, "deny_mac_file") == 0) { 1422e5b75505Sopenharmony_ci hostapd_disassoc_deny_mac(hapd); 1423e5b75505Sopenharmony_ci } else if (os_strcasecmp(cmd, "accept_mac_file") == 0) { 1424e5b75505Sopenharmony_ci hostapd_disassoc_accept_mac(hapd); 1425e5b75505Sopenharmony_ci } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 || 1426e5b75505Sopenharmony_ci os_strncmp(cmd, "wmm_ac_", 7) == 0) { 1427e5b75505Sopenharmony_ci hapd->parameter_set_count++; 1428e5b75505Sopenharmony_ci if (ieee802_11_update_beacons(hapd->iface)) 1429e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1430e5b75505Sopenharmony_ci "Failed to update beacons with WMM parameters"); 1431e5b75505Sopenharmony_ci } 1432e5b75505Sopenharmony_ci } 1433e5b75505Sopenharmony_ci 1434e5b75505Sopenharmony_ci return ret; 1435e5b75505Sopenharmony_ci} 1436e5b75505Sopenharmony_ci 1437e5b75505Sopenharmony_ci 1438e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 1439e5b75505Sopenharmony_ci char *buf, size_t buflen) 1440e5b75505Sopenharmony_ci{ 1441e5b75505Sopenharmony_ci int res; 1442e5b75505Sopenharmony_ci 1443e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 1444e5b75505Sopenharmony_ci 1445e5b75505Sopenharmony_ci if (os_strcmp(cmd, "version") == 0) { 1446e5b75505Sopenharmony_ci res = os_snprintf(buf, buflen, "%s", VERSION_STR); 1447e5b75505Sopenharmony_ci if (os_snprintf_error(buflen, res)) 1448e5b75505Sopenharmony_ci return -1; 1449e5b75505Sopenharmony_ci return res; 1450e5b75505Sopenharmony_ci } else if (os_strcmp(cmd, "tls_library") == 0) { 1451e5b75505Sopenharmony_ci res = tls_get_library_version(buf, buflen); 1452e5b75505Sopenharmony_ci if (os_snprintf_error(buflen, res)) 1453e5b75505Sopenharmony_ci return -1; 1454e5b75505Sopenharmony_ci return res; 1455e5b75505Sopenharmony_ci } 1456e5b75505Sopenharmony_ci 1457e5b75505Sopenharmony_ci return -1; 1458e5b75505Sopenharmony_ci} 1459e5b75505Sopenharmony_ci 1460e5b75505Sopenharmony_ci 1461e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 1462e5b75505Sopenharmony_ci{ 1463e5b75505Sopenharmony_ci if (hostapd_enable_iface(iface) < 0) { 1464e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Enabling of interface failed"); 1465e5b75505Sopenharmony_ci return -1; 1466e5b75505Sopenharmony_ci } 1467e5b75505Sopenharmony_ci return 0; 1468e5b75505Sopenharmony_ci} 1469e5b75505Sopenharmony_ci 1470e5b75505Sopenharmony_ci 1471e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 1472e5b75505Sopenharmony_ci{ 1473e5b75505Sopenharmony_ci if (hostapd_reload_iface(iface) < 0) { 1474e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Reloading of interface failed"); 1475e5b75505Sopenharmony_ci return -1; 1476e5b75505Sopenharmony_ci } 1477e5b75505Sopenharmony_ci return 0; 1478e5b75505Sopenharmony_ci} 1479e5b75505Sopenharmony_ci 1480e5b75505Sopenharmony_ci 1481e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 1482e5b75505Sopenharmony_ci{ 1483e5b75505Sopenharmony_ci if (hostapd_disable_iface(iface) < 0) { 1484e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Disabling of interface failed"); 1485e5b75505Sopenharmony_ci return -1; 1486e5b75505Sopenharmony_ci } 1487e5b75505Sopenharmony_ci return 0; 1488e5b75505Sopenharmony_ci} 1489e5b75505Sopenharmony_ci 1490e5b75505Sopenharmony_ci 1491e5b75505Sopenharmony_cistatic int 1492e5b75505Sopenharmony_cihostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd, 1493e5b75505Sopenharmony_ci struct sta_info *sta, void *ctx) 1494e5b75505Sopenharmony_ci{ 1495e5b75505Sopenharmony_ci struct hostapd_wpa_psk *psk; 1496e5b75505Sopenharmony_ci const u8 *pmk; 1497e5b75505Sopenharmony_ci int pmk_len; 1498e5b75505Sopenharmony_ci int pmk_match; 1499e5b75505Sopenharmony_ci int sta_match; 1500e5b75505Sopenharmony_ci int bss_match; 1501e5b75505Sopenharmony_ci int reason; 1502e5b75505Sopenharmony_ci 1503e5b75505Sopenharmony_ci pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); 1504e5b75505Sopenharmony_ci 1505e5b75505Sopenharmony_ci for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) { 1506e5b75505Sopenharmony_ci pmk_match = PMK_LEN == pmk_len && 1507e5b75505Sopenharmony_ci os_memcmp(psk->psk, pmk, pmk_len) == 0; 1508e5b75505Sopenharmony_ci sta_match = psk->group == 0 && 1509e5b75505Sopenharmony_ci os_memcmp(sta->addr, psk->addr, ETH_ALEN) == 0; 1510e5b75505Sopenharmony_ci bss_match = psk->group == 1; 1511e5b75505Sopenharmony_ci 1512e5b75505Sopenharmony_ci if (pmk_match && (sta_match || bss_match)) 1513e5b75505Sopenharmony_ci return 0; 1514e5b75505Sopenharmony_ci } 1515e5b75505Sopenharmony_ci 1516e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "STA " MACSTR 1517e5b75505Sopenharmony_ci " PSK/passphrase no longer valid - disconnect", 1518e5b75505Sopenharmony_ci MAC2STR(sta->addr)); 1519e5b75505Sopenharmony_ci reason = WLAN_REASON_PREV_AUTH_NOT_VALID; 1520e5b75505Sopenharmony_ci hostapd_drv_sta_deauth(hapd, sta->addr, reason); 1521e5b75505Sopenharmony_ci ap_sta_deauthenticate(hapd, sta, reason); 1522e5b75505Sopenharmony_ci 1523e5b75505Sopenharmony_ci return 0; 1524e5b75505Sopenharmony_ci} 1525e5b75505Sopenharmony_ci 1526e5b75505Sopenharmony_ci 1527e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd) 1528e5b75505Sopenharmony_ci{ 1529e5b75505Sopenharmony_ci struct hostapd_bss_config *conf = hapd->conf; 1530e5b75505Sopenharmony_ci int err; 1531e5b75505Sopenharmony_ci 1532e5b75505Sopenharmony_ci hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); 1533e5b75505Sopenharmony_ci 1534e5b75505Sopenharmony_ci err = hostapd_setup_wpa_psk(conf); 1535e5b75505Sopenharmony_ci if (err < 0) { 1536e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d", 1537e5b75505Sopenharmony_ci err); 1538e5b75505Sopenharmony_ci return -1; 1539e5b75505Sopenharmony_ci } 1540e5b75505Sopenharmony_ci 1541e5b75505Sopenharmony_ci ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter, 1542e5b75505Sopenharmony_ci NULL); 1543e5b75505Sopenharmony_ci 1544e5b75505Sopenharmony_ci return 0; 1545e5b75505Sopenharmony_ci} 1546e5b75505Sopenharmony_ci 1547e5b75505Sopenharmony_ci 1548e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 1549e5b75505Sopenharmony_ci 1550e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) 1551e5b75505Sopenharmony_ci{ 1552e5b75505Sopenharmony_ci union wpa_event_data data; 1553e5b75505Sopenharmony_ci char *pos, *param; 1554e5b75505Sopenharmony_ci enum wpa_event_type event; 1555e5b75505Sopenharmony_ci 1556e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd); 1557e5b75505Sopenharmony_ci 1558e5b75505Sopenharmony_ci os_memset(&data, 0, sizeof(data)); 1559e5b75505Sopenharmony_ci 1560e5b75505Sopenharmony_ci param = os_strchr(cmd, ' '); 1561e5b75505Sopenharmony_ci if (param == NULL) 1562e5b75505Sopenharmony_ci return -1; 1563e5b75505Sopenharmony_ci *param++ = '\0'; 1564e5b75505Sopenharmony_ci 1565e5b75505Sopenharmony_ci if (os_strcmp(cmd, "DETECTED") == 0) 1566e5b75505Sopenharmony_ci event = EVENT_DFS_RADAR_DETECTED; 1567e5b75505Sopenharmony_ci else if (os_strcmp(cmd, "CAC-FINISHED") == 0) 1568e5b75505Sopenharmony_ci event = EVENT_DFS_CAC_FINISHED; 1569e5b75505Sopenharmony_ci else if (os_strcmp(cmd, "CAC-ABORTED") == 0) 1570e5b75505Sopenharmony_ci event = EVENT_DFS_CAC_ABORTED; 1571e5b75505Sopenharmony_ci else if (os_strcmp(cmd, "NOP-FINISHED") == 0) 1572e5b75505Sopenharmony_ci event = EVENT_DFS_NOP_FINISHED; 1573e5b75505Sopenharmony_ci else { 1574e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s", 1575e5b75505Sopenharmony_ci cmd); 1576e5b75505Sopenharmony_ci return -1; 1577e5b75505Sopenharmony_ci } 1578e5b75505Sopenharmony_ci 1579e5b75505Sopenharmony_ci pos = os_strstr(param, "freq="); 1580e5b75505Sopenharmony_ci if (pos) 1581e5b75505Sopenharmony_ci data.dfs_event.freq = atoi(pos + 5); 1582e5b75505Sopenharmony_ci 1583e5b75505Sopenharmony_ci pos = os_strstr(param, "ht_enabled=1"); 1584e5b75505Sopenharmony_ci if (pos) 1585e5b75505Sopenharmony_ci data.dfs_event.ht_enabled = 1; 1586e5b75505Sopenharmony_ci 1587e5b75505Sopenharmony_ci pos = os_strstr(param, "chan_offset="); 1588e5b75505Sopenharmony_ci if (pos) 1589e5b75505Sopenharmony_ci data.dfs_event.chan_offset = atoi(pos + 12); 1590e5b75505Sopenharmony_ci 1591e5b75505Sopenharmony_ci pos = os_strstr(param, "chan_width="); 1592e5b75505Sopenharmony_ci if (pos) 1593e5b75505Sopenharmony_ci data.dfs_event.chan_width = atoi(pos + 11); 1594e5b75505Sopenharmony_ci 1595e5b75505Sopenharmony_ci pos = os_strstr(param, "cf1="); 1596e5b75505Sopenharmony_ci if (pos) 1597e5b75505Sopenharmony_ci data.dfs_event.cf1 = atoi(pos + 4); 1598e5b75505Sopenharmony_ci 1599e5b75505Sopenharmony_ci pos = os_strstr(param, "cf2="); 1600e5b75505Sopenharmony_ci if (pos) 1601e5b75505Sopenharmony_ci data.dfs_event.cf2 = atoi(pos + 4); 1602e5b75505Sopenharmony_ci 1603e5b75505Sopenharmony_ci wpa_supplicant_event(hapd, event, &data); 1604e5b75505Sopenharmony_ci 1605e5b75505Sopenharmony_ci return 0; 1606e5b75505Sopenharmony_ci} 1607e5b75505Sopenharmony_ci 1608e5b75505Sopenharmony_ci 1609e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 1610e5b75505Sopenharmony_ci{ 1611e5b75505Sopenharmony_ci size_t len; 1612e5b75505Sopenharmony_ci u8 *buf; 1613e5b75505Sopenharmony_ci int res; 1614e5b75505Sopenharmony_ci 1615e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 1616e5b75505Sopenharmony_ci 1617e5b75505Sopenharmony_ci len = os_strlen(cmd); 1618e5b75505Sopenharmony_ci if (len & 1) 1619e5b75505Sopenharmony_ci return -1; 1620e5b75505Sopenharmony_ci len /= 2; 1621e5b75505Sopenharmony_ci 1622e5b75505Sopenharmony_ci buf = os_malloc(len); 1623e5b75505Sopenharmony_ci if (buf == NULL) 1624e5b75505Sopenharmony_ci return -1; 1625e5b75505Sopenharmony_ci 1626e5b75505Sopenharmony_ci if (hexstr2bin(cmd, buf, len) < 0) { 1627e5b75505Sopenharmony_ci os_free(buf); 1628e5b75505Sopenharmony_ci return -1; 1629e5b75505Sopenharmony_ci } 1630e5b75505Sopenharmony_ci 1631e5b75505Sopenharmony_ci res = hostapd_drv_send_mlme(hapd, buf, len, 0); 1632e5b75505Sopenharmony_ci os_free(buf); 1633e5b75505Sopenharmony_ci return res; 1634e5b75505Sopenharmony_ci} 1635e5b75505Sopenharmony_ci 1636e5b75505Sopenharmony_ci 1637e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data *hapd, 1638e5b75505Sopenharmony_ci char *cmd) 1639e5b75505Sopenharmony_ci{ 1640e5b75505Sopenharmony_ci char *pos, *param; 1641e5b75505Sopenharmony_ci size_t len; 1642e5b75505Sopenharmony_ci u8 *buf; 1643e5b75505Sopenharmony_ci int stype = 0, ok = 0; 1644e5b75505Sopenharmony_ci union wpa_event_data event; 1645e5b75505Sopenharmony_ci 1646e5b75505Sopenharmony_ci if (!hapd->ext_mgmt_frame_handling) 1647e5b75505Sopenharmony_ci return -1; 1648e5b75505Sopenharmony_ci 1649e5b75505Sopenharmony_ci /* stype=<val> ok=<0/1> buf=<frame hexdump> */ 1650e5b75505Sopenharmony_ci 1651e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "External MGMT TX status process: %s", cmd); 1652e5b75505Sopenharmony_ci 1653e5b75505Sopenharmony_ci pos = cmd; 1654e5b75505Sopenharmony_ci param = os_strstr(pos, "stype="); 1655e5b75505Sopenharmony_ci if (param) { 1656e5b75505Sopenharmony_ci param += 6; 1657e5b75505Sopenharmony_ci stype = atoi(param); 1658e5b75505Sopenharmony_ci } 1659e5b75505Sopenharmony_ci 1660e5b75505Sopenharmony_ci param = os_strstr(pos, " ok="); 1661e5b75505Sopenharmony_ci if (param) { 1662e5b75505Sopenharmony_ci param += 4; 1663e5b75505Sopenharmony_ci ok = atoi(param); 1664e5b75505Sopenharmony_ci } 1665e5b75505Sopenharmony_ci 1666e5b75505Sopenharmony_ci param = os_strstr(pos, " buf="); 1667e5b75505Sopenharmony_ci if (!param) 1668e5b75505Sopenharmony_ci return -1; 1669e5b75505Sopenharmony_ci param += 5; 1670e5b75505Sopenharmony_ci 1671e5b75505Sopenharmony_ci len = os_strlen(param); 1672e5b75505Sopenharmony_ci if (len & 1) 1673e5b75505Sopenharmony_ci return -1; 1674e5b75505Sopenharmony_ci len /= 2; 1675e5b75505Sopenharmony_ci 1676e5b75505Sopenharmony_ci buf = os_malloc(len); 1677e5b75505Sopenharmony_ci if (!buf || hexstr2bin(param, buf, len) < 0) { 1678e5b75505Sopenharmony_ci os_free(buf); 1679e5b75505Sopenharmony_ci return -1; 1680e5b75505Sopenharmony_ci } 1681e5b75505Sopenharmony_ci 1682e5b75505Sopenharmony_ci os_memset(&event, 0, sizeof(event)); 1683e5b75505Sopenharmony_ci event.tx_status.type = WLAN_FC_TYPE_MGMT; 1684e5b75505Sopenharmony_ci event.tx_status.data = buf; 1685e5b75505Sopenharmony_ci event.tx_status.data_len = len; 1686e5b75505Sopenharmony_ci event.tx_status.stype = stype; 1687e5b75505Sopenharmony_ci event.tx_status.ack = ok; 1688e5b75505Sopenharmony_ci hapd->ext_mgmt_frame_handling = 0; 1689e5b75505Sopenharmony_ci wpa_supplicant_event(hapd, EVENT_TX_STATUS, &event); 1690e5b75505Sopenharmony_ci hapd->ext_mgmt_frame_handling = 1; 1691e5b75505Sopenharmony_ci 1692e5b75505Sopenharmony_ci os_free(buf); 1693e5b75505Sopenharmony_ci 1694e5b75505Sopenharmony_ci return 0; 1695e5b75505Sopenharmony_ci} 1696e5b75505Sopenharmony_ci 1697e5b75505Sopenharmony_ci 1698e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd, 1699e5b75505Sopenharmony_ci char *cmd) 1700e5b75505Sopenharmony_ci{ 1701e5b75505Sopenharmony_ci char *pos, *param; 1702e5b75505Sopenharmony_ci size_t len; 1703e5b75505Sopenharmony_ci u8 *buf; 1704e5b75505Sopenharmony_ci int freq = 0, datarate = 0, ssi_signal = 0; 1705e5b75505Sopenharmony_ci union wpa_event_data event; 1706e5b75505Sopenharmony_ci 1707e5b75505Sopenharmony_ci if (!hapd->ext_mgmt_frame_handling) 1708e5b75505Sopenharmony_ci return -1; 1709e5b75505Sopenharmony_ci 1710e5b75505Sopenharmony_ci /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 1711e5b75505Sopenharmony_ci 1712e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 1713e5b75505Sopenharmony_ci 1714e5b75505Sopenharmony_ci pos = cmd; 1715e5b75505Sopenharmony_ci param = os_strstr(pos, "freq="); 1716e5b75505Sopenharmony_ci if (param) { 1717e5b75505Sopenharmony_ci param += 5; 1718e5b75505Sopenharmony_ci freq = atoi(param); 1719e5b75505Sopenharmony_ci } 1720e5b75505Sopenharmony_ci 1721e5b75505Sopenharmony_ci param = os_strstr(pos, " datarate="); 1722e5b75505Sopenharmony_ci if (param) { 1723e5b75505Sopenharmony_ci param += 10; 1724e5b75505Sopenharmony_ci datarate = atoi(param); 1725e5b75505Sopenharmony_ci } 1726e5b75505Sopenharmony_ci 1727e5b75505Sopenharmony_ci param = os_strstr(pos, " ssi_signal="); 1728e5b75505Sopenharmony_ci if (param) { 1729e5b75505Sopenharmony_ci param += 12; 1730e5b75505Sopenharmony_ci ssi_signal = atoi(param); 1731e5b75505Sopenharmony_ci } 1732e5b75505Sopenharmony_ci 1733e5b75505Sopenharmony_ci param = os_strstr(pos, " frame="); 1734e5b75505Sopenharmony_ci if (param == NULL) 1735e5b75505Sopenharmony_ci return -1; 1736e5b75505Sopenharmony_ci param += 7; 1737e5b75505Sopenharmony_ci 1738e5b75505Sopenharmony_ci len = os_strlen(param); 1739e5b75505Sopenharmony_ci if (len & 1) 1740e5b75505Sopenharmony_ci return -1; 1741e5b75505Sopenharmony_ci len /= 2; 1742e5b75505Sopenharmony_ci 1743e5b75505Sopenharmony_ci buf = os_malloc(len); 1744e5b75505Sopenharmony_ci if (buf == NULL) 1745e5b75505Sopenharmony_ci return -1; 1746e5b75505Sopenharmony_ci 1747e5b75505Sopenharmony_ci if (hexstr2bin(param, buf, len) < 0) { 1748e5b75505Sopenharmony_ci os_free(buf); 1749e5b75505Sopenharmony_ci return -1; 1750e5b75505Sopenharmony_ci } 1751e5b75505Sopenharmony_ci 1752e5b75505Sopenharmony_ci os_memset(&event, 0, sizeof(event)); 1753e5b75505Sopenharmony_ci event.rx_mgmt.freq = freq; 1754e5b75505Sopenharmony_ci event.rx_mgmt.frame = buf; 1755e5b75505Sopenharmony_ci event.rx_mgmt.frame_len = len; 1756e5b75505Sopenharmony_ci event.rx_mgmt.ssi_signal = ssi_signal; 1757e5b75505Sopenharmony_ci event.rx_mgmt.datarate = datarate; 1758e5b75505Sopenharmony_ci hapd->ext_mgmt_frame_handling = 0; 1759e5b75505Sopenharmony_ci wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event); 1760e5b75505Sopenharmony_ci hapd->ext_mgmt_frame_handling = 1; 1761e5b75505Sopenharmony_ci 1762e5b75505Sopenharmony_ci os_free(buf); 1763e5b75505Sopenharmony_ci 1764e5b75505Sopenharmony_ci return 0; 1765e5b75505Sopenharmony_ci} 1766e5b75505Sopenharmony_ci 1767e5b75505Sopenharmony_ci 1768e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd) 1769e5b75505Sopenharmony_ci{ 1770e5b75505Sopenharmony_ci char *pos; 1771e5b75505Sopenharmony_ci u8 src[ETH_ALEN], *buf; 1772e5b75505Sopenharmony_ci int used; 1773e5b75505Sopenharmony_ci size_t len; 1774e5b75505Sopenharmony_ci 1775e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 1776e5b75505Sopenharmony_ci 1777e5b75505Sopenharmony_ci pos = cmd; 1778e5b75505Sopenharmony_ci used = hwaddr_aton2(pos, src); 1779e5b75505Sopenharmony_ci if (used < 0) 1780e5b75505Sopenharmony_ci return -1; 1781e5b75505Sopenharmony_ci pos += used; 1782e5b75505Sopenharmony_ci while (*pos == ' ') 1783e5b75505Sopenharmony_ci pos++; 1784e5b75505Sopenharmony_ci 1785e5b75505Sopenharmony_ci len = os_strlen(pos); 1786e5b75505Sopenharmony_ci if (len & 1) 1787e5b75505Sopenharmony_ci return -1; 1788e5b75505Sopenharmony_ci len /= 2; 1789e5b75505Sopenharmony_ci 1790e5b75505Sopenharmony_ci buf = os_malloc(len); 1791e5b75505Sopenharmony_ci if (buf == NULL) 1792e5b75505Sopenharmony_ci return -1; 1793e5b75505Sopenharmony_ci 1794e5b75505Sopenharmony_ci if (hexstr2bin(pos, buf, len) < 0) { 1795e5b75505Sopenharmony_ci os_free(buf); 1796e5b75505Sopenharmony_ci return -1; 1797e5b75505Sopenharmony_ci } 1798e5b75505Sopenharmony_ci 1799e5b75505Sopenharmony_ci ieee802_1x_receive(hapd, src, buf, len); 1800e5b75505Sopenharmony_ci os_free(buf); 1801e5b75505Sopenharmony_ci 1802e5b75505Sopenharmony_ci return 0; 1803e5b75505Sopenharmony_ci} 1804e5b75505Sopenharmony_ci 1805e5b75505Sopenharmony_ci 1806e5b75505Sopenharmony_cistatic u16 ipv4_hdr_checksum(const void *buf, size_t len) 1807e5b75505Sopenharmony_ci{ 1808e5b75505Sopenharmony_ci size_t i; 1809e5b75505Sopenharmony_ci u32 sum = 0; 1810e5b75505Sopenharmony_ci const u16 *pos = buf; 1811e5b75505Sopenharmony_ci 1812e5b75505Sopenharmony_ci for (i = 0; i < len / 2; i++) 1813e5b75505Sopenharmony_ci sum += *pos++; 1814e5b75505Sopenharmony_ci 1815e5b75505Sopenharmony_ci while (sum >> 16) 1816e5b75505Sopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 1817e5b75505Sopenharmony_ci 1818e5b75505Sopenharmony_ci return sum ^ 0xffff; 1819e5b75505Sopenharmony_ci} 1820e5b75505Sopenharmony_ci 1821e5b75505Sopenharmony_ci 1822e5b75505Sopenharmony_ci#define HWSIM_PACKETLEN 1500 1823e5b75505Sopenharmony_ci#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 1824e5b75505Sopenharmony_ci 1825e5b75505Sopenharmony_cistatic void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 1826e5b75505Sopenharmony_ci size_t len) 1827e5b75505Sopenharmony_ci{ 1828e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 1829e5b75505Sopenharmony_ci const struct ether_header *eth; 1830e5b75505Sopenharmony_ci struct iphdr ip; 1831e5b75505Sopenharmony_ci const u8 *pos; 1832e5b75505Sopenharmony_ci unsigned int i; 1833e5b75505Sopenharmony_ci char extra[30]; 1834e5b75505Sopenharmony_ci 1835e5b75505Sopenharmony_ci if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { 1836e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1837e5b75505Sopenharmony_ci "test data: RX - ignore unexpected length %d", 1838e5b75505Sopenharmony_ci (int) len); 1839e5b75505Sopenharmony_ci return; 1840e5b75505Sopenharmony_ci } 1841e5b75505Sopenharmony_ci 1842e5b75505Sopenharmony_ci eth = (const struct ether_header *) buf; 1843e5b75505Sopenharmony_ci os_memcpy(&ip, eth + 1, sizeof(ip)); 1844e5b75505Sopenharmony_ci pos = &buf[sizeof(*eth) + sizeof(ip)]; 1845e5b75505Sopenharmony_ci 1846e5b75505Sopenharmony_ci if (ip.ihl != 5 || ip.version != 4 || 1847e5b75505Sopenharmony_ci ntohs(ip.tot_len) > HWSIM_IP_LEN) { 1848e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1849e5b75505Sopenharmony_ci "test data: RX - ignore unexpect IP header"); 1850e5b75505Sopenharmony_ci return; 1851e5b75505Sopenharmony_ci } 1852e5b75505Sopenharmony_ci 1853e5b75505Sopenharmony_ci for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) { 1854e5b75505Sopenharmony_ci if (*pos != (u8) i) { 1855e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1856e5b75505Sopenharmony_ci "test data: RX - ignore mismatching payload"); 1857e5b75505Sopenharmony_ci return; 1858e5b75505Sopenharmony_ci } 1859e5b75505Sopenharmony_ci pos++; 1860e5b75505Sopenharmony_ci } 1861e5b75505Sopenharmony_ci 1862e5b75505Sopenharmony_ci extra[0] = '\0'; 1863e5b75505Sopenharmony_ci if (ntohs(ip.tot_len) != HWSIM_IP_LEN) 1864e5b75505Sopenharmony_ci os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len)); 1865e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", 1866e5b75505Sopenharmony_ci MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); 1867e5b75505Sopenharmony_ci} 1868e5b75505Sopenharmony_ci 1869e5b75505Sopenharmony_ci 1870e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd, 1871e5b75505Sopenharmony_ci char *cmd) 1872e5b75505Sopenharmony_ci{ 1873e5b75505Sopenharmony_ci int enabled = atoi(cmd); 1874e5b75505Sopenharmony_ci char *pos; 1875e5b75505Sopenharmony_ci const char *ifname; 1876e5b75505Sopenharmony_ci 1877e5b75505Sopenharmony_ci if (!enabled) { 1878e5b75505Sopenharmony_ci if (hapd->l2_test) { 1879e5b75505Sopenharmony_ci l2_packet_deinit(hapd->l2_test); 1880e5b75505Sopenharmony_ci hapd->l2_test = NULL; 1881e5b75505Sopenharmony_ci wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 1882e5b75505Sopenharmony_ci "test data: Disabled"); 1883e5b75505Sopenharmony_ci } 1884e5b75505Sopenharmony_ci return 0; 1885e5b75505Sopenharmony_ci } 1886e5b75505Sopenharmony_ci 1887e5b75505Sopenharmony_ci if (hapd->l2_test) 1888e5b75505Sopenharmony_ci return 0; 1889e5b75505Sopenharmony_ci 1890e5b75505Sopenharmony_ci pos = os_strstr(cmd, " ifname="); 1891e5b75505Sopenharmony_ci if (pos) 1892e5b75505Sopenharmony_ci ifname = pos + 8; 1893e5b75505Sopenharmony_ci else 1894e5b75505Sopenharmony_ci ifname = hapd->conf->iface; 1895e5b75505Sopenharmony_ci 1896e5b75505Sopenharmony_ci hapd->l2_test = l2_packet_init(ifname, hapd->own_addr, 1897e5b75505Sopenharmony_ci ETHERTYPE_IP, hostapd_data_test_rx, 1898e5b75505Sopenharmony_ci hapd, 1); 1899e5b75505Sopenharmony_ci if (hapd->l2_test == NULL) 1900e5b75505Sopenharmony_ci return -1; 1901e5b75505Sopenharmony_ci 1902e5b75505Sopenharmony_ci wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled"); 1903e5b75505Sopenharmony_ci 1904e5b75505Sopenharmony_ci return 0; 1905e5b75505Sopenharmony_ci} 1906e5b75505Sopenharmony_ci 1907e5b75505Sopenharmony_ci 1908e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) 1909e5b75505Sopenharmony_ci{ 1910e5b75505Sopenharmony_ci u8 dst[ETH_ALEN], src[ETH_ALEN]; 1911e5b75505Sopenharmony_ci char *pos, *pos2; 1912e5b75505Sopenharmony_ci int used; 1913e5b75505Sopenharmony_ci long int val; 1914e5b75505Sopenharmony_ci u8 tos; 1915e5b75505Sopenharmony_ci u8 buf[2 + HWSIM_PACKETLEN]; 1916e5b75505Sopenharmony_ci struct ether_header *eth; 1917e5b75505Sopenharmony_ci struct iphdr *ip; 1918e5b75505Sopenharmony_ci u8 *dpos; 1919e5b75505Sopenharmony_ci unsigned int i; 1920e5b75505Sopenharmony_ci size_t send_len = HWSIM_IP_LEN; 1921e5b75505Sopenharmony_ci 1922e5b75505Sopenharmony_ci if (hapd->l2_test == NULL) 1923e5b75505Sopenharmony_ci return -1; 1924e5b75505Sopenharmony_ci 1925e5b75505Sopenharmony_ci /* format: <dst> <src> <tos> [len=<length>] */ 1926e5b75505Sopenharmony_ci 1927e5b75505Sopenharmony_ci pos = cmd; 1928e5b75505Sopenharmony_ci used = hwaddr_aton2(pos, dst); 1929e5b75505Sopenharmony_ci if (used < 0) 1930e5b75505Sopenharmony_ci return -1; 1931e5b75505Sopenharmony_ci pos += used; 1932e5b75505Sopenharmony_ci while (*pos == ' ') 1933e5b75505Sopenharmony_ci pos++; 1934e5b75505Sopenharmony_ci used = hwaddr_aton2(pos, src); 1935e5b75505Sopenharmony_ci if (used < 0) 1936e5b75505Sopenharmony_ci return -1; 1937e5b75505Sopenharmony_ci pos += used; 1938e5b75505Sopenharmony_ci 1939e5b75505Sopenharmony_ci val = strtol(pos, &pos2, 0); 1940e5b75505Sopenharmony_ci if (val < 0 || val > 0xff) 1941e5b75505Sopenharmony_ci return -1; 1942e5b75505Sopenharmony_ci tos = val; 1943e5b75505Sopenharmony_ci 1944e5b75505Sopenharmony_ci pos = os_strstr(pos2, " len="); 1945e5b75505Sopenharmony_ci if (pos) { 1946e5b75505Sopenharmony_ci i = atoi(pos + 5); 1947e5b75505Sopenharmony_ci if (i < sizeof(*ip) || i > HWSIM_IP_LEN) 1948e5b75505Sopenharmony_ci return -1; 1949e5b75505Sopenharmony_ci send_len = i; 1950e5b75505Sopenharmony_ci } 1951e5b75505Sopenharmony_ci 1952e5b75505Sopenharmony_ci eth = (struct ether_header *) &buf[2]; 1953e5b75505Sopenharmony_ci os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 1954e5b75505Sopenharmony_ci os_memcpy(eth->ether_shost, src, ETH_ALEN); 1955e5b75505Sopenharmony_ci eth->ether_type = htons(ETHERTYPE_IP); 1956e5b75505Sopenharmony_ci ip = (struct iphdr *) (eth + 1); 1957e5b75505Sopenharmony_ci os_memset(ip, 0, sizeof(*ip)); 1958e5b75505Sopenharmony_ci ip->ihl = 5; 1959e5b75505Sopenharmony_ci ip->version = 4; 1960e5b75505Sopenharmony_ci ip->ttl = 64; 1961e5b75505Sopenharmony_ci ip->tos = tos; 1962e5b75505Sopenharmony_ci ip->tot_len = htons(send_len); 1963e5b75505Sopenharmony_ci ip->protocol = 1; 1964e5b75505Sopenharmony_ci ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 1965e5b75505Sopenharmony_ci ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 1966e5b75505Sopenharmony_ci ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); 1967e5b75505Sopenharmony_ci dpos = (u8 *) (ip + 1); 1968e5b75505Sopenharmony_ci for (i = 0; i < send_len - sizeof(*ip); i++) 1969e5b75505Sopenharmony_ci *dpos++ = i; 1970e5b75505Sopenharmony_ci 1971e5b75505Sopenharmony_ci if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2], 1972e5b75505Sopenharmony_ci sizeof(struct ether_header) + send_len) < 0) 1973e5b75505Sopenharmony_ci return -1; 1974e5b75505Sopenharmony_ci 1975e5b75505Sopenharmony_ci wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR 1976e5b75505Sopenharmony_ci " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 1977e5b75505Sopenharmony_ci 1978e5b75505Sopenharmony_ci return 0; 1979e5b75505Sopenharmony_ci} 1980e5b75505Sopenharmony_ci 1981e5b75505Sopenharmony_ci 1982e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd, 1983e5b75505Sopenharmony_ci char *cmd) 1984e5b75505Sopenharmony_ci{ 1985e5b75505Sopenharmony_ci u8 *buf; 1986e5b75505Sopenharmony_ci struct ether_header *eth; 1987e5b75505Sopenharmony_ci struct l2_packet_data *l2 = NULL; 1988e5b75505Sopenharmony_ci size_t len; 1989e5b75505Sopenharmony_ci u16 ethertype; 1990e5b75505Sopenharmony_ci int res = -1; 1991e5b75505Sopenharmony_ci const char *ifname = hapd->conf->iface; 1992e5b75505Sopenharmony_ci 1993e5b75505Sopenharmony_ci if (os_strncmp(cmd, "ifname=", 7) == 0) { 1994e5b75505Sopenharmony_ci cmd += 7; 1995e5b75505Sopenharmony_ci ifname = cmd; 1996e5b75505Sopenharmony_ci cmd = os_strchr(cmd, ' '); 1997e5b75505Sopenharmony_ci if (cmd == NULL) 1998e5b75505Sopenharmony_ci return -1; 1999e5b75505Sopenharmony_ci *cmd++ = '\0'; 2000e5b75505Sopenharmony_ci } 2001e5b75505Sopenharmony_ci 2002e5b75505Sopenharmony_ci len = os_strlen(cmd); 2003e5b75505Sopenharmony_ci if (len & 1 || len < ETH_HLEN * 2) 2004e5b75505Sopenharmony_ci return -1; 2005e5b75505Sopenharmony_ci len /= 2; 2006e5b75505Sopenharmony_ci 2007e5b75505Sopenharmony_ci buf = os_malloc(len); 2008e5b75505Sopenharmony_ci if (buf == NULL) 2009e5b75505Sopenharmony_ci return -1; 2010e5b75505Sopenharmony_ci 2011e5b75505Sopenharmony_ci if (hexstr2bin(cmd, buf, len) < 0) 2012e5b75505Sopenharmony_ci goto done; 2013e5b75505Sopenharmony_ci 2014e5b75505Sopenharmony_ci eth = (struct ether_header *) buf; 2015e5b75505Sopenharmony_ci ethertype = ntohs(eth->ether_type); 2016e5b75505Sopenharmony_ci 2017e5b75505Sopenharmony_ci l2 = l2_packet_init(ifname, hapd->own_addr, ethertype, 2018e5b75505Sopenharmony_ci hostapd_data_test_rx, hapd, 1); 2019e5b75505Sopenharmony_ci if (l2 == NULL) 2020e5b75505Sopenharmony_ci goto done; 2021e5b75505Sopenharmony_ci 2022e5b75505Sopenharmony_ci res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 2023e5b75505Sopenharmony_ci wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res); 2024e5b75505Sopenharmony_cidone: 2025e5b75505Sopenharmony_ci if (l2) 2026e5b75505Sopenharmony_ci l2_packet_deinit(l2); 2027e5b75505Sopenharmony_ci os_free(buf); 2028e5b75505Sopenharmony_ci 2029e5b75505Sopenharmony_ci return res < 0 ? -1 : 0; 2030e5b75505Sopenharmony_ci} 2031e5b75505Sopenharmony_ci 2032e5b75505Sopenharmony_ci 2033e5b75505Sopenharmony_cistatic int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd) 2034e5b75505Sopenharmony_ci{ 2035e5b75505Sopenharmony_ci#ifdef WPA_TRACE_BFD 2036e5b75505Sopenharmony_ci char *pos; 2037e5b75505Sopenharmony_ci 2038e5b75505Sopenharmony_ci wpa_trace_fail_after = atoi(cmd); 2039e5b75505Sopenharmony_ci pos = os_strchr(cmd, ':'); 2040e5b75505Sopenharmony_ci if (pos) { 2041e5b75505Sopenharmony_ci pos++; 2042e5b75505Sopenharmony_ci os_strlcpy(wpa_trace_fail_func, pos, 2043e5b75505Sopenharmony_ci sizeof(wpa_trace_fail_func)); 2044e5b75505Sopenharmony_ci } else { 2045e5b75505Sopenharmony_ci wpa_trace_fail_after = 0; 2046e5b75505Sopenharmony_ci } 2047e5b75505Sopenharmony_ci 2048e5b75505Sopenharmony_ci return 0; 2049e5b75505Sopenharmony_ci#else /* WPA_TRACE_BFD */ 2050e5b75505Sopenharmony_ci return -1; 2051e5b75505Sopenharmony_ci#endif /* WPA_TRACE_BFD */ 2052e5b75505Sopenharmony_ci} 2053e5b75505Sopenharmony_ci 2054e5b75505Sopenharmony_ci 2055e5b75505Sopenharmony_cistatic int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd, 2056e5b75505Sopenharmony_ci char *buf, size_t buflen) 2057e5b75505Sopenharmony_ci{ 2058e5b75505Sopenharmony_ci#ifdef WPA_TRACE_BFD 2059e5b75505Sopenharmony_ci return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after, 2060e5b75505Sopenharmony_ci wpa_trace_fail_func); 2061e5b75505Sopenharmony_ci#else /* WPA_TRACE_BFD */ 2062e5b75505Sopenharmony_ci return -1; 2063e5b75505Sopenharmony_ci#endif /* WPA_TRACE_BFD */ 2064e5b75505Sopenharmony_ci} 2065e5b75505Sopenharmony_ci 2066e5b75505Sopenharmony_ci 2067e5b75505Sopenharmony_cistatic int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd) 2068e5b75505Sopenharmony_ci{ 2069e5b75505Sopenharmony_ci#ifdef WPA_TRACE_BFD 2070e5b75505Sopenharmony_ci char *pos; 2071e5b75505Sopenharmony_ci 2072e5b75505Sopenharmony_ci wpa_trace_test_fail_after = atoi(cmd); 2073e5b75505Sopenharmony_ci pos = os_strchr(cmd, ':'); 2074e5b75505Sopenharmony_ci if (pos) { 2075e5b75505Sopenharmony_ci pos++; 2076e5b75505Sopenharmony_ci os_strlcpy(wpa_trace_test_fail_func, pos, 2077e5b75505Sopenharmony_ci sizeof(wpa_trace_test_fail_func)); 2078e5b75505Sopenharmony_ci } else { 2079e5b75505Sopenharmony_ci wpa_trace_test_fail_after = 0; 2080e5b75505Sopenharmony_ci } 2081e5b75505Sopenharmony_ci 2082e5b75505Sopenharmony_ci return 0; 2083e5b75505Sopenharmony_ci#else /* WPA_TRACE_BFD */ 2084e5b75505Sopenharmony_ci return -1; 2085e5b75505Sopenharmony_ci#endif /* WPA_TRACE_BFD */ 2086e5b75505Sopenharmony_ci} 2087e5b75505Sopenharmony_ci 2088e5b75505Sopenharmony_ci 2089e5b75505Sopenharmony_cistatic int hostapd_ctrl_get_fail(struct hostapd_data *hapd, 2090e5b75505Sopenharmony_ci char *buf, size_t buflen) 2091e5b75505Sopenharmony_ci{ 2092e5b75505Sopenharmony_ci#ifdef WPA_TRACE_BFD 2093e5b75505Sopenharmony_ci return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after, 2094e5b75505Sopenharmony_ci wpa_trace_test_fail_func); 2095e5b75505Sopenharmony_ci#else /* WPA_TRACE_BFD */ 2096e5b75505Sopenharmony_ci return -1; 2097e5b75505Sopenharmony_ci#endif /* WPA_TRACE_BFD */ 2098e5b75505Sopenharmony_ci} 2099e5b75505Sopenharmony_ci 2100e5b75505Sopenharmony_ci 2101e5b75505Sopenharmony_cistatic int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) 2102e5b75505Sopenharmony_ci{ 2103e5b75505Sopenharmony_ci struct sta_info *sta; 2104e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2105e5b75505Sopenharmony_ci u8 zero[WPA_TK_MAX_LEN]; 2106e5b75505Sopenharmony_ci 2107e5b75505Sopenharmony_ci os_memset(zero, 0, sizeof(zero)); 2108e5b75505Sopenharmony_ci 2109e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2110e5b75505Sopenharmony_ci return -1; 2111e5b75505Sopenharmony_ci 2112e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 2113e5b75505Sopenharmony_ci if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) { 2114e5b75505Sopenharmony_ci if (hapd->last_igtk_alg == WPA_ALG_NONE) 2115e5b75505Sopenharmony_ci return -1; 2116e5b75505Sopenharmony_ci 2117e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK"); 2118e5b75505Sopenharmony_ci 2119e5b75505Sopenharmony_ci /* First, use a zero key to avoid any possible duplicate key 2120e5b75505Sopenharmony_ci * avoidance in the driver. */ 2121e5b75505Sopenharmony_ci if (hostapd_drv_set_key(hapd->conf->iface, hapd, 2122e5b75505Sopenharmony_ci hapd->last_igtk_alg, 2123e5b75505Sopenharmony_ci broadcast_ether_addr, 2124e5b75505Sopenharmony_ci hapd->last_igtk_key_idx, 1, NULL, 0, 2125e5b75505Sopenharmony_ci zero, hapd->last_igtk_len) < 0) 2126e5b75505Sopenharmony_ci return -1; 2127e5b75505Sopenharmony_ci 2128e5b75505Sopenharmony_ci /* Set the previously configured key to reset its TSC */ 2129e5b75505Sopenharmony_ci return hostapd_drv_set_key(hapd->conf->iface, hapd, 2130e5b75505Sopenharmony_ci hapd->last_igtk_alg, 2131e5b75505Sopenharmony_ci broadcast_ether_addr, 2132e5b75505Sopenharmony_ci hapd->last_igtk_key_idx, 1, NULL, 0, 2133e5b75505Sopenharmony_ci hapd->last_igtk, 2134e5b75505Sopenharmony_ci hapd->last_igtk_len); 2135e5b75505Sopenharmony_ci } 2136e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 2137e5b75505Sopenharmony_ci 2138e5b75505Sopenharmony_ci if (is_broadcast_ether_addr(addr)) { 2139e5b75505Sopenharmony_ci if (hapd->last_gtk_alg == WPA_ALG_NONE) 2140e5b75505Sopenharmony_ci return -1; 2141e5b75505Sopenharmony_ci 2142e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK"); 2143e5b75505Sopenharmony_ci 2144e5b75505Sopenharmony_ci /* First, use a zero key to avoid any possible duplicate key 2145e5b75505Sopenharmony_ci * avoidance in the driver. */ 2146e5b75505Sopenharmony_ci if (hostapd_drv_set_key(hapd->conf->iface, hapd, 2147e5b75505Sopenharmony_ci hapd->last_gtk_alg, 2148e5b75505Sopenharmony_ci broadcast_ether_addr, 2149e5b75505Sopenharmony_ci hapd->last_gtk_key_idx, 1, NULL, 0, 2150e5b75505Sopenharmony_ci zero, hapd->last_gtk_len) < 0) 2151e5b75505Sopenharmony_ci return -1; 2152e5b75505Sopenharmony_ci 2153e5b75505Sopenharmony_ci /* Set the previously configured key to reset its TSC */ 2154e5b75505Sopenharmony_ci return hostapd_drv_set_key(hapd->conf->iface, hapd, 2155e5b75505Sopenharmony_ci hapd->last_gtk_alg, 2156e5b75505Sopenharmony_ci broadcast_ether_addr, 2157e5b75505Sopenharmony_ci hapd->last_gtk_key_idx, 1, NULL, 0, 2158e5b75505Sopenharmony_ci hapd->last_gtk, hapd->last_gtk_len); 2159e5b75505Sopenharmony_ci } 2160e5b75505Sopenharmony_ci 2161e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 2162e5b75505Sopenharmony_ci if (!sta) 2163e5b75505Sopenharmony_ci return -1; 2164e5b75505Sopenharmony_ci 2165e5b75505Sopenharmony_ci if (sta->last_tk_alg == WPA_ALG_NONE) 2166e5b75505Sopenharmony_ci return -1; 2167e5b75505Sopenharmony_ci 2168e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR, 2169e5b75505Sopenharmony_ci MAC2STR(sta->addr)); 2170e5b75505Sopenharmony_ci 2171e5b75505Sopenharmony_ci /* First, use a zero key to avoid any possible duplicate key avoidance 2172e5b75505Sopenharmony_ci * in the driver. */ 2173e5b75505Sopenharmony_ci if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg, 2174e5b75505Sopenharmony_ci sta->addr, sta->last_tk_key_idx, 1, NULL, 0, 2175e5b75505Sopenharmony_ci zero, sta->last_tk_len) < 0) 2176e5b75505Sopenharmony_ci return -1; 2177e5b75505Sopenharmony_ci 2178e5b75505Sopenharmony_ci /* Set the previously configured key to reset its TSC/RSC */ 2179e5b75505Sopenharmony_ci return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg, 2180e5b75505Sopenharmony_ci sta->addr, sta->last_tk_key_idx, 1, NULL, 0, 2181e5b75505Sopenharmony_ci sta->last_tk, sta->last_tk_len); 2182e5b75505Sopenharmony_ci} 2183e5b75505Sopenharmony_ci 2184e5b75505Sopenharmony_ci 2185e5b75505Sopenharmony_cistatic int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd) 2186e5b75505Sopenharmony_ci{ 2187e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2188e5b75505Sopenharmony_ci const char *pos = cmd; 2189e5b75505Sopenharmony_ci enum wpa_alg alg; 2190e5b75505Sopenharmony_ci int idx, set_tx; 2191e5b75505Sopenharmony_ci u8 seq[6], key[WPA_TK_MAX_LEN]; 2192e5b75505Sopenharmony_ci size_t key_len; 2193e5b75505Sopenharmony_ci 2194e5b75505Sopenharmony_ci /* parameters: alg addr idx set_tx seq key */ 2195e5b75505Sopenharmony_ci 2196e5b75505Sopenharmony_ci alg = atoi(pos); 2197e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 2198e5b75505Sopenharmony_ci if (!pos) 2199e5b75505Sopenharmony_ci return -1; 2200e5b75505Sopenharmony_ci pos++; 2201e5b75505Sopenharmony_ci if (hwaddr_aton(pos, addr)) 2202e5b75505Sopenharmony_ci return -1; 2203e5b75505Sopenharmony_ci pos += 17; 2204e5b75505Sopenharmony_ci if (*pos != ' ') 2205e5b75505Sopenharmony_ci return -1; 2206e5b75505Sopenharmony_ci pos++; 2207e5b75505Sopenharmony_ci idx = atoi(pos); 2208e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 2209e5b75505Sopenharmony_ci if (!pos) 2210e5b75505Sopenharmony_ci return -1; 2211e5b75505Sopenharmony_ci pos++; 2212e5b75505Sopenharmony_ci set_tx = atoi(pos); 2213e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 2214e5b75505Sopenharmony_ci if (!pos) 2215e5b75505Sopenharmony_ci return -1; 2216e5b75505Sopenharmony_ci pos++; 2217e5b75505Sopenharmony_ci if (hexstr2bin(pos, seq, sizeof(seq)) < 0) 2218e5b75505Sopenharmony_ci return -1; 2219e5b75505Sopenharmony_ci pos += 2 * 6; 2220e5b75505Sopenharmony_ci if (*pos != ' ') 2221e5b75505Sopenharmony_ci return -1; 2222e5b75505Sopenharmony_ci pos++; 2223e5b75505Sopenharmony_ci key_len = os_strlen(pos) / 2; 2224e5b75505Sopenharmony_ci if (hexstr2bin(pos, key, key_len) < 0) 2225e5b75505Sopenharmony_ci return -1; 2226e5b75505Sopenharmony_ci 2227e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Set key"); 2228e5b75505Sopenharmony_ci return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx, 2229e5b75505Sopenharmony_ci set_tx, seq, 6, key, key_len); 2230e5b75505Sopenharmony_ci} 2231e5b75505Sopenharmony_ci 2232e5b75505Sopenharmony_ci 2233e5b75505Sopenharmony_cistatic void restore_tk(void *ctx1, void *ctx2) 2234e5b75505Sopenharmony_ci{ 2235e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx1; 2236e5b75505Sopenharmony_ci struct sta_info *sta = ctx2; 2237e5b75505Sopenharmony_ci 2238e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR, 2239e5b75505Sopenharmony_ci MAC2STR(sta->addr)); 2240e5b75505Sopenharmony_ci /* This does not really restore the TSC properly, so this will result 2241e5b75505Sopenharmony_ci * in replay protection issues for now since there is no clean way of 2242e5b75505Sopenharmony_ci * preventing encryption of a single EAPOL frame. */ 2243e5b75505Sopenharmony_ci hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg, 2244e5b75505Sopenharmony_ci sta->addr, sta->last_tk_key_idx, 1, NULL, 0, 2245e5b75505Sopenharmony_ci sta->last_tk, sta->last_tk_len); 2246e5b75505Sopenharmony_ci} 2247e5b75505Sopenharmony_ci 2248e5b75505Sopenharmony_ci 2249e5b75505Sopenharmony_cistatic int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd) 2250e5b75505Sopenharmony_ci{ 2251e5b75505Sopenharmony_ci struct sta_info *sta; 2252e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2253e5b75505Sopenharmony_ci int plain = os_strstr(cmd, "plaintext") != NULL; 2254e5b75505Sopenharmony_ci 2255e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2256e5b75505Sopenharmony_ci return -1; 2257e5b75505Sopenharmony_ci 2258e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 2259e5b75505Sopenharmony_ci if (!sta || !sta->wpa_sm) 2260e5b75505Sopenharmony_ci return -1; 2261e5b75505Sopenharmony_ci 2262e5b75505Sopenharmony_ci if (plain && sta->last_tk_alg == WPA_ALG_NONE) 2263e5b75505Sopenharmony_ci plain = 0; /* no need for special processing */ 2264e5b75505Sopenharmony_ci if (plain) { 2265e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR, 2266e5b75505Sopenharmony_ci MAC2STR(sta->addr)); 2267e5b75505Sopenharmony_ci hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, 2268e5b75505Sopenharmony_ci sta->addr, sta->last_tk_key_idx, 0, NULL, 0, 2269e5b75505Sopenharmony_ci NULL, 0); 2270e5b75505Sopenharmony_ci } 2271e5b75505Sopenharmony_ci 2272e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr)); 2273e5b75505Sopenharmony_ci return wpa_auth_resend_m1(sta->wpa_sm, 2274e5b75505Sopenharmony_ci os_strstr(cmd, "change-anonce") != NULL, 2275e5b75505Sopenharmony_ci plain ? restore_tk : NULL, hapd, sta); 2276e5b75505Sopenharmony_ci} 2277e5b75505Sopenharmony_ci 2278e5b75505Sopenharmony_ci 2279e5b75505Sopenharmony_cistatic int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd) 2280e5b75505Sopenharmony_ci{ 2281e5b75505Sopenharmony_ci struct sta_info *sta; 2282e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2283e5b75505Sopenharmony_ci int plain = os_strstr(cmd, "plaintext") != NULL; 2284e5b75505Sopenharmony_ci 2285e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2286e5b75505Sopenharmony_ci return -1; 2287e5b75505Sopenharmony_ci 2288e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 2289e5b75505Sopenharmony_ci if (!sta || !sta->wpa_sm) 2290e5b75505Sopenharmony_ci return -1; 2291e5b75505Sopenharmony_ci 2292e5b75505Sopenharmony_ci if (plain && sta->last_tk_alg == WPA_ALG_NONE) 2293e5b75505Sopenharmony_ci plain = 0; /* no need for special processing */ 2294e5b75505Sopenharmony_ci if (plain) { 2295e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR, 2296e5b75505Sopenharmony_ci MAC2STR(sta->addr)); 2297e5b75505Sopenharmony_ci hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, 2298e5b75505Sopenharmony_ci sta->addr, sta->last_tk_key_idx, 0, NULL, 0, 2299e5b75505Sopenharmony_ci NULL, 0); 2300e5b75505Sopenharmony_ci } 2301e5b75505Sopenharmony_ci 2302e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr)); 2303e5b75505Sopenharmony_ci return wpa_auth_resend_m3(sta->wpa_sm, 2304e5b75505Sopenharmony_ci plain ? restore_tk : NULL, hapd, sta); 2305e5b75505Sopenharmony_ci} 2306e5b75505Sopenharmony_ci 2307e5b75505Sopenharmony_ci 2308e5b75505Sopenharmony_cistatic int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd, 2309e5b75505Sopenharmony_ci const char *cmd) 2310e5b75505Sopenharmony_ci{ 2311e5b75505Sopenharmony_ci struct sta_info *sta; 2312e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2313e5b75505Sopenharmony_ci int plain = os_strstr(cmd, "plaintext") != NULL; 2314e5b75505Sopenharmony_ci 2315e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2316e5b75505Sopenharmony_ci return -1; 2317e5b75505Sopenharmony_ci 2318e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 2319e5b75505Sopenharmony_ci if (!sta || !sta->wpa_sm) 2320e5b75505Sopenharmony_ci return -1; 2321e5b75505Sopenharmony_ci 2322e5b75505Sopenharmony_ci if (plain && sta->last_tk_alg == WPA_ALG_NONE) 2323e5b75505Sopenharmony_ci plain = 0; /* no need for special processing */ 2324e5b75505Sopenharmony_ci if (plain) { 2325e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR, 2326e5b75505Sopenharmony_ci MAC2STR(sta->addr)); 2327e5b75505Sopenharmony_ci hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, 2328e5b75505Sopenharmony_ci sta->addr, sta->last_tk_key_idx, 0, NULL, 0, 2329e5b75505Sopenharmony_ci NULL, 0); 2330e5b75505Sopenharmony_ci } 2331e5b75505Sopenharmony_ci 2332e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 2333e5b75505Sopenharmony_ci "TESTING: Send group M1 for the same GTK and zero RSC to " 2334e5b75505Sopenharmony_ci MACSTR, MAC2STR(sta->addr)); 2335e5b75505Sopenharmony_ci return wpa_auth_resend_group_m1(sta->wpa_sm, 2336e5b75505Sopenharmony_ci plain ? restore_tk : NULL, hapd, sta); 2337e5b75505Sopenharmony_ci} 2338e5b75505Sopenharmony_ci 2339e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 2340e5b75505Sopenharmony_ci 2341e5b75505Sopenharmony_ci 2342e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, 2343e5b75505Sopenharmony_ci char *pos) 2344e5b75505Sopenharmony_ci{ 2345e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 2346e5b75505Sopenharmony_ci struct csa_settings settings; 2347e5b75505Sopenharmony_ci int ret; 2348e5b75505Sopenharmony_ci unsigned int i; 2349e5b75505Sopenharmony_ci 2350e5b75505Sopenharmony_ci ret = hostapd_parse_csa_settings(pos, &settings); 2351e5b75505Sopenharmony_ci if (ret) 2352e5b75505Sopenharmony_ci return ret; 2353e5b75505Sopenharmony_ci 2354e5b75505Sopenharmony_ci for (i = 0; i < iface->num_bss; i++) { 2355e5b75505Sopenharmony_ci 2356e5b75505Sopenharmony_ci /* Save CHAN_SWITCH VHT config */ 2357e5b75505Sopenharmony_ci hostapd_chan_switch_vht_config( 2358e5b75505Sopenharmony_ci iface->bss[i], settings.freq_params.vht_enabled); 2359e5b75505Sopenharmony_ci 2360e5b75505Sopenharmony_ci ret = hostapd_switch_channel(iface->bss[i], &settings); 2361e5b75505Sopenharmony_ci if (ret) { 2362e5b75505Sopenharmony_ci /* FIX: What do we do if CSA fails in the middle of 2363e5b75505Sopenharmony_ci * submitting multi-BSS CSA requests? */ 2364e5b75505Sopenharmony_ci return ret; 2365e5b75505Sopenharmony_ci } 2366e5b75505Sopenharmony_ci } 2367e5b75505Sopenharmony_ci 2368e5b75505Sopenharmony_ci return 0; 2369e5b75505Sopenharmony_ci#else /* NEED_AP_MLME */ 2370e5b75505Sopenharmony_ci return -1; 2371e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 2372e5b75505Sopenharmony_ci} 2373e5b75505Sopenharmony_ci 2374e5b75505Sopenharmony_ci 2375e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, 2376e5b75505Sopenharmony_ci int reply_size, const char *param) 2377e5b75505Sopenharmony_ci{ 2378e5b75505Sopenharmony_ci#ifdef RADIUS_SERVER 2379e5b75505Sopenharmony_ci if (os_strcmp(param, "radius_server") == 0) { 2380e5b75505Sopenharmony_ci return radius_server_get_mib(hapd->radius_srv, reply, 2381e5b75505Sopenharmony_ci reply_size); 2382e5b75505Sopenharmony_ci } 2383e5b75505Sopenharmony_ci#endif /* RADIUS_SERVER */ 2384e5b75505Sopenharmony_ci return -1; 2385e5b75505Sopenharmony_ci} 2386e5b75505Sopenharmony_ci 2387e5b75505Sopenharmony_ci 2388e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, 2389e5b75505Sopenharmony_ci char *buf, size_t buflen) 2390e5b75505Sopenharmony_ci{ 2391e5b75505Sopenharmony_ci int ret; 2392e5b75505Sopenharmony_ci char *pos; 2393e5b75505Sopenharmony_ci u8 *data = NULL; 2394e5b75505Sopenharmony_ci unsigned int vendor_id, subcmd; 2395e5b75505Sopenharmony_ci struct wpabuf *reply; 2396e5b75505Sopenharmony_ci size_t data_len = 0; 2397e5b75505Sopenharmony_ci 2398e5b75505Sopenharmony_ci /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 2399e5b75505Sopenharmony_ci vendor_id = strtoul(cmd, &pos, 16); 2400e5b75505Sopenharmony_ci if (!isblank((unsigned char) *pos)) 2401e5b75505Sopenharmony_ci return -EINVAL; 2402e5b75505Sopenharmony_ci 2403e5b75505Sopenharmony_ci subcmd = strtoul(pos, &pos, 10); 2404e5b75505Sopenharmony_ci 2405e5b75505Sopenharmony_ci if (*pos != '\0') { 2406e5b75505Sopenharmony_ci if (!isblank((unsigned char) *pos++)) 2407e5b75505Sopenharmony_ci return -EINVAL; 2408e5b75505Sopenharmony_ci data_len = os_strlen(pos); 2409e5b75505Sopenharmony_ci } 2410e5b75505Sopenharmony_ci 2411e5b75505Sopenharmony_ci if (data_len) { 2412e5b75505Sopenharmony_ci data_len /= 2; 2413e5b75505Sopenharmony_ci data = os_malloc(data_len); 2414e5b75505Sopenharmony_ci if (!data) 2415e5b75505Sopenharmony_ci return -ENOBUFS; 2416e5b75505Sopenharmony_ci 2417e5b75505Sopenharmony_ci if (hexstr2bin(pos, data, data_len)) { 2418e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 2419e5b75505Sopenharmony_ci "Vendor command: wrong parameter format"); 2420e5b75505Sopenharmony_ci os_free(data); 2421e5b75505Sopenharmony_ci return -EINVAL; 2422e5b75505Sopenharmony_ci } 2423e5b75505Sopenharmony_ci } 2424e5b75505Sopenharmony_ci 2425e5b75505Sopenharmony_ci reply = wpabuf_alloc((buflen - 1) / 2); 2426e5b75505Sopenharmony_ci if (!reply) { 2427e5b75505Sopenharmony_ci os_free(data); 2428e5b75505Sopenharmony_ci return -ENOBUFS; 2429e5b75505Sopenharmony_ci } 2430e5b75505Sopenharmony_ci 2431e5b75505Sopenharmony_ci ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, 2432e5b75505Sopenharmony_ci reply); 2433e5b75505Sopenharmony_ci 2434e5b75505Sopenharmony_ci if (ret == 0) 2435e5b75505Sopenharmony_ci ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 2436e5b75505Sopenharmony_ci wpabuf_len(reply)); 2437e5b75505Sopenharmony_ci 2438e5b75505Sopenharmony_ci wpabuf_free(reply); 2439e5b75505Sopenharmony_ci os_free(data); 2440e5b75505Sopenharmony_ci 2441e5b75505Sopenharmony_ci return ret; 2442e5b75505Sopenharmony_ci} 2443e5b75505Sopenharmony_ci 2444e5b75505Sopenharmony_ci 2445e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd, 2446e5b75505Sopenharmony_ci const char *cmd) 2447e5b75505Sopenharmony_ci{ 2448e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2449e5b75505Sopenharmony_ci struct sta_info *sta; 2450e5b75505Sopenharmony_ci 2451e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2452e5b75505Sopenharmony_ci return -1; 2453e5b75505Sopenharmony_ci 2454e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 2455e5b75505Sopenharmony_ci if (!sta || !sta->eapol_sm) 2456e5b75505Sopenharmony_ci return -1; 2457e5b75505Sopenharmony_ci 2458e5b75505Sopenharmony_ci eapol_auth_reauthenticate(sta->eapol_sm); 2459e5b75505Sopenharmony_ci return 0; 2460e5b75505Sopenharmony_ci} 2461e5b75505Sopenharmony_ci 2462e5b75505Sopenharmony_ci 2463e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd) 2464e5b75505Sopenharmony_ci{ 2465e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2466e5b75505Sopenharmony_ci struct sta_info *sta; 2467e5b75505Sopenharmony_ci char *pos = cmd, *param; 2468e5b75505Sopenharmony_ci 2469e5b75505Sopenharmony_ci if (hwaddr_aton(pos, addr) || pos[17] != ' ') 2470e5b75505Sopenharmony_ci return -1; 2471e5b75505Sopenharmony_ci pos += 18; 2472e5b75505Sopenharmony_ci param = pos; 2473e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 2474e5b75505Sopenharmony_ci if (!pos) 2475e5b75505Sopenharmony_ci return -1; 2476e5b75505Sopenharmony_ci *pos++ = '\0'; 2477e5b75505Sopenharmony_ci 2478e5b75505Sopenharmony_ci sta = ap_get_sta(hapd, addr); 2479e5b75505Sopenharmony_ci if (!sta || !sta->eapol_sm) 2480e5b75505Sopenharmony_ci return -1; 2481e5b75505Sopenharmony_ci 2482e5b75505Sopenharmony_ci return eapol_auth_set_conf(sta->eapol_sm, param, pos); 2483e5b75505Sopenharmony_ci} 2484e5b75505Sopenharmony_ci 2485e5b75505Sopenharmony_ci 2486e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd, 2487e5b75505Sopenharmony_ci char *buf, size_t buflen) 2488e5b75505Sopenharmony_ci{ 2489e5b75505Sopenharmony_ci char *pos, *end, *stamp; 2490e5b75505Sopenharmony_ci int ret; 2491e5b75505Sopenharmony_ci 2492e5b75505Sopenharmony_ci /* cmd: "LOG_LEVEL [<level>]" */ 2493e5b75505Sopenharmony_ci if (*cmd == '\0') { 2494e5b75505Sopenharmony_ci pos = buf; 2495e5b75505Sopenharmony_ci end = buf + buflen; 2496e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "Current level: %s\n" 2497e5b75505Sopenharmony_ci "Timestamp: %d\n", 2498e5b75505Sopenharmony_ci debug_level_str(wpa_debug_level), 2499e5b75505Sopenharmony_ci wpa_debug_timestamp); 2500e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 2501e5b75505Sopenharmony_ci ret = 0; 2502e5b75505Sopenharmony_ci 2503e5b75505Sopenharmony_ci return ret; 2504e5b75505Sopenharmony_ci } 2505e5b75505Sopenharmony_ci 2506e5b75505Sopenharmony_ci while (*cmd == ' ') 2507e5b75505Sopenharmony_ci cmd++; 2508e5b75505Sopenharmony_ci 2509e5b75505Sopenharmony_ci stamp = os_strchr(cmd, ' '); 2510e5b75505Sopenharmony_ci if (stamp) { 2511e5b75505Sopenharmony_ci *stamp++ = '\0'; 2512e5b75505Sopenharmony_ci while (*stamp == ' ') { 2513e5b75505Sopenharmony_ci stamp++; 2514e5b75505Sopenharmony_ci } 2515e5b75505Sopenharmony_ci } 2516e5b75505Sopenharmony_ci 2517e5b75505Sopenharmony_ci if (os_strlen(cmd)) { 2518e5b75505Sopenharmony_ci int level = str_to_debug_level(cmd); 2519e5b75505Sopenharmony_ci if (level < 0) 2520e5b75505Sopenharmony_ci return -1; 2521e5b75505Sopenharmony_ci wpa_debug_level = level; 2522e5b75505Sopenharmony_ci } 2523e5b75505Sopenharmony_ci 2524e5b75505Sopenharmony_ci if (stamp && os_strlen(stamp)) 2525e5b75505Sopenharmony_ci wpa_debug_timestamp = atoi(stamp); 2526e5b75505Sopenharmony_ci 2527e5b75505Sopenharmony_ci os_memcpy(buf, "OK\n", 3); 2528e5b75505Sopenharmony_ci return 3; 2529e5b75505Sopenharmony_ci} 2530e5b75505Sopenharmony_ci 2531e5b75505Sopenharmony_ci 2532e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 2533e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd, 2534e5b75505Sopenharmony_ci char *buf, size_t buflen) 2535e5b75505Sopenharmony_ci{ 2536e5b75505Sopenharmony_ci struct hostapd_iface *iface = hapd->iface; 2537e5b75505Sopenharmony_ci char *pos, *end; 2538e5b75505Sopenharmony_ci struct hostapd_sta_info *info; 2539e5b75505Sopenharmony_ci struct os_reltime now; 2540e5b75505Sopenharmony_ci 2541e5b75505Sopenharmony_ci if (!iface->num_sta_seen) 2542e5b75505Sopenharmony_ci return 0; 2543e5b75505Sopenharmony_ci 2544e5b75505Sopenharmony_ci sta_track_expire(iface, 0); 2545e5b75505Sopenharmony_ci 2546e5b75505Sopenharmony_ci pos = buf; 2547e5b75505Sopenharmony_ci end = buf + buflen; 2548e5b75505Sopenharmony_ci 2549e5b75505Sopenharmony_ci os_get_reltime(&now); 2550e5b75505Sopenharmony_ci dl_list_for_each_reverse(info, &iface->sta_seen, 2551e5b75505Sopenharmony_ci struct hostapd_sta_info, list) { 2552e5b75505Sopenharmony_ci struct os_reltime age; 2553e5b75505Sopenharmony_ci int ret; 2554e5b75505Sopenharmony_ci 2555e5b75505Sopenharmony_ci os_reltime_sub(&now, &info->last_seen, &age); 2556e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n", 2557e5b75505Sopenharmony_ci MAC2STR(info->addr), (unsigned int) age.sec, 2558e5b75505Sopenharmony_ci info->ssi_signal); 2559e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 2560e5b75505Sopenharmony_ci break; 2561e5b75505Sopenharmony_ci pos += ret; 2562e5b75505Sopenharmony_ci } 2563e5b75505Sopenharmony_ci 2564e5b75505Sopenharmony_ci return pos - buf; 2565e5b75505Sopenharmony_ci} 2566e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 2567e5b75505Sopenharmony_ci 2568e5b75505Sopenharmony_ci 2569e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd, 2570e5b75505Sopenharmony_ci const char *cmd) 2571e5b75505Sopenharmony_ci{ 2572e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2573e5b75505Sopenharmony_ci 2574e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) { 2575e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address"); 2576e5b75505Sopenharmony_ci return -1; 2577e5b75505Sopenharmony_ci } 2578e5b75505Sopenharmony_ci 2579e5b75505Sopenharmony_ci return hostapd_send_lci_req(hapd, addr); 2580e5b75505Sopenharmony_ci} 2581e5b75505Sopenharmony_ci 2582e5b75505Sopenharmony_ci 2583e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd) 2584e5b75505Sopenharmony_ci{ 2585e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2586e5b75505Sopenharmony_ci char *token, *context = NULL; 2587e5b75505Sopenharmony_ci int random_interval, min_ap; 2588e5b75505Sopenharmony_ci u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS]; 2589e5b75505Sopenharmony_ci unsigned int n_responders; 2590e5b75505Sopenharmony_ci 2591e5b75505Sopenharmony_ci token = str_token(cmd, " ", &context); 2592e5b75505Sopenharmony_ci if (!token || hwaddr_aton(token, addr)) { 2593e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 2594e5b75505Sopenharmony_ci "CTRL: REQ_RANGE - Bad destination address"); 2595e5b75505Sopenharmony_ci return -1; 2596e5b75505Sopenharmony_ci } 2597e5b75505Sopenharmony_ci 2598e5b75505Sopenharmony_ci token = str_token(cmd, " ", &context); 2599e5b75505Sopenharmony_ci if (!token) 2600e5b75505Sopenharmony_ci return -1; 2601e5b75505Sopenharmony_ci 2602e5b75505Sopenharmony_ci random_interval = atoi(token); 2603e5b75505Sopenharmony_ci if (random_interval < 0 || random_interval > 0xffff) 2604e5b75505Sopenharmony_ci return -1; 2605e5b75505Sopenharmony_ci 2606e5b75505Sopenharmony_ci token = str_token(cmd, " ", &context); 2607e5b75505Sopenharmony_ci if (!token) 2608e5b75505Sopenharmony_ci return -1; 2609e5b75505Sopenharmony_ci 2610e5b75505Sopenharmony_ci min_ap = atoi(token); 2611e5b75505Sopenharmony_ci if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP) 2612e5b75505Sopenharmony_ci return -1; 2613e5b75505Sopenharmony_ci 2614e5b75505Sopenharmony_ci n_responders = 0; 2615e5b75505Sopenharmony_ci while ((token = str_token(cmd, " ", &context))) { 2616e5b75505Sopenharmony_ci if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) { 2617e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 2618e5b75505Sopenharmony_ci "CTRL: REQ_RANGE: Too many responders"); 2619e5b75505Sopenharmony_ci return -1; 2620e5b75505Sopenharmony_ci } 2621e5b75505Sopenharmony_ci 2622e5b75505Sopenharmony_ci if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) { 2623e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 2624e5b75505Sopenharmony_ci "CTRL: REQ_RANGE: Bad responder address"); 2625e5b75505Sopenharmony_ci return -1; 2626e5b75505Sopenharmony_ci } 2627e5b75505Sopenharmony_ci 2628e5b75505Sopenharmony_ci n_responders++; 2629e5b75505Sopenharmony_ci } 2630e5b75505Sopenharmony_ci 2631e5b75505Sopenharmony_ci if (!n_responders) { 2632e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 2633e5b75505Sopenharmony_ci "CTRL: REQ_RANGE - No FTM responder address"); 2634e5b75505Sopenharmony_ci return -1; 2635e5b75505Sopenharmony_ci } 2636e5b75505Sopenharmony_ci 2637e5b75505Sopenharmony_ci return hostapd_send_range_req(hapd, addr, random_interval, min_ap, 2638e5b75505Sopenharmony_ci responders, n_responders); 2639e5b75505Sopenharmony_ci} 2640e5b75505Sopenharmony_ci 2641e5b75505Sopenharmony_ci 2642e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd, 2643e5b75505Sopenharmony_ci const char *cmd, char *reply, 2644e5b75505Sopenharmony_ci size_t reply_size) 2645e5b75505Sopenharmony_ci{ 2646e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2647e5b75505Sopenharmony_ci const char *pos; 2648e5b75505Sopenharmony_ci struct wpabuf *req; 2649e5b75505Sopenharmony_ci int ret; 2650e5b75505Sopenharmony_ci u8 req_mode = 0; 2651e5b75505Sopenharmony_ci 2652e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2653e5b75505Sopenharmony_ci return -1; 2654e5b75505Sopenharmony_ci pos = os_strchr(cmd, ' '); 2655e5b75505Sopenharmony_ci if (!pos) 2656e5b75505Sopenharmony_ci return -1; 2657e5b75505Sopenharmony_ci pos++; 2658e5b75505Sopenharmony_ci if (os_strncmp(pos, "req_mode=", 9) == 0) { 2659e5b75505Sopenharmony_ci int val = hex2byte(pos + 9); 2660e5b75505Sopenharmony_ci 2661e5b75505Sopenharmony_ci if (val < 0) 2662e5b75505Sopenharmony_ci return -1; 2663e5b75505Sopenharmony_ci req_mode = val; 2664e5b75505Sopenharmony_ci pos += 11; 2665e5b75505Sopenharmony_ci pos = os_strchr(pos, ' '); 2666e5b75505Sopenharmony_ci if (!pos) 2667e5b75505Sopenharmony_ci return -1; 2668e5b75505Sopenharmony_ci pos++; 2669e5b75505Sopenharmony_ci } 2670e5b75505Sopenharmony_ci req = wpabuf_parse_bin(pos); 2671e5b75505Sopenharmony_ci if (!req) 2672e5b75505Sopenharmony_ci return -1; 2673e5b75505Sopenharmony_ci 2674e5b75505Sopenharmony_ci ret = hostapd_send_beacon_req(hapd, addr, req_mode, req); 2675e5b75505Sopenharmony_ci wpabuf_free(req); 2676e5b75505Sopenharmony_ci if (ret >= 0) 2677e5b75505Sopenharmony_ci ret = os_snprintf(reply, reply_size, "%d", ret); 2678e5b75505Sopenharmony_ci return ret; 2679e5b75505Sopenharmony_ci} 2680e5b75505Sopenharmony_ci 2681e5b75505Sopenharmony_ci 2682e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf) 2683e5b75505Sopenharmony_ci{ 2684e5b75505Sopenharmony_ci struct wpa_ssid_value ssid; 2685e5b75505Sopenharmony_ci u8 bssid[ETH_ALEN]; 2686e5b75505Sopenharmony_ci struct wpabuf *nr, *lci = NULL, *civic = NULL; 2687e5b75505Sopenharmony_ci int stationary = 0; 2688e5b75505Sopenharmony_ci char *tmp; 2689e5b75505Sopenharmony_ci int ret; 2690e5b75505Sopenharmony_ci 2691e5b75505Sopenharmony_ci if (!(hapd->conf->radio_measurements[0] & 2692e5b75505Sopenharmony_ci WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { 2693e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2694e5b75505Sopenharmony_ci "CTRL: SET_NEIGHBOR: Neighbor report is not enabled"); 2695e5b75505Sopenharmony_ci return -1; 2696e5b75505Sopenharmony_ci } 2697e5b75505Sopenharmony_ci 2698e5b75505Sopenharmony_ci if (hwaddr_aton(buf, bssid)) { 2699e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID"); 2700e5b75505Sopenharmony_ci return -1; 2701e5b75505Sopenharmony_ci } 2702e5b75505Sopenharmony_ci 2703e5b75505Sopenharmony_ci tmp = os_strstr(buf, "ssid="); 2704e5b75505Sopenharmony_ci if (!tmp || ssid_parse(tmp + 5, &ssid)) { 2705e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2706e5b75505Sopenharmony_ci "CTRL: SET_NEIGHBOR: Bad or missing SSID"); 2707e5b75505Sopenharmony_ci return -1; 2708e5b75505Sopenharmony_ci } 2709e5b75505Sopenharmony_ci buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' '); 2710e5b75505Sopenharmony_ci if (!buf) 2711e5b75505Sopenharmony_ci return -1; 2712e5b75505Sopenharmony_ci 2713e5b75505Sopenharmony_ci tmp = os_strstr(buf, "nr="); 2714e5b75505Sopenharmony_ci if (!tmp) { 2715e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2716e5b75505Sopenharmony_ci "CTRL: SET_NEIGHBOR: Missing Neighbor Report element"); 2717e5b75505Sopenharmony_ci return -1; 2718e5b75505Sopenharmony_ci } 2719e5b75505Sopenharmony_ci 2720e5b75505Sopenharmony_ci buf = os_strchr(tmp, ' '); 2721e5b75505Sopenharmony_ci if (buf) 2722e5b75505Sopenharmony_ci *buf++ = '\0'; 2723e5b75505Sopenharmony_ci 2724e5b75505Sopenharmony_ci nr = wpabuf_parse_bin(tmp + 3); 2725e5b75505Sopenharmony_ci if (!nr) { 2726e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2727e5b75505Sopenharmony_ci "CTRL: SET_NEIGHBOR: Bad Neighbor Report element"); 2728e5b75505Sopenharmony_ci return -1; 2729e5b75505Sopenharmony_ci } 2730e5b75505Sopenharmony_ci 2731e5b75505Sopenharmony_ci if (!buf) 2732e5b75505Sopenharmony_ci goto set; 2733e5b75505Sopenharmony_ci 2734e5b75505Sopenharmony_ci tmp = os_strstr(buf, "lci="); 2735e5b75505Sopenharmony_ci if (tmp) { 2736e5b75505Sopenharmony_ci buf = os_strchr(tmp, ' '); 2737e5b75505Sopenharmony_ci if (buf) 2738e5b75505Sopenharmony_ci *buf++ = '\0'; 2739e5b75505Sopenharmony_ci lci = wpabuf_parse_bin(tmp + 4); 2740e5b75505Sopenharmony_ci if (!lci) { 2741e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2742e5b75505Sopenharmony_ci "CTRL: SET_NEIGHBOR: Bad LCI subelement"); 2743e5b75505Sopenharmony_ci wpabuf_free(nr); 2744e5b75505Sopenharmony_ci return -1; 2745e5b75505Sopenharmony_ci } 2746e5b75505Sopenharmony_ci } 2747e5b75505Sopenharmony_ci 2748e5b75505Sopenharmony_ci if (!buf) 2749e5b75505Sopenharmony_ci goto set; 2750e5b75505Sopenharmony_ci 2751e5b75505Sopenharmony_ci tmp = os_strstr(buf, "civic="); 2752e5b75505Sopenharmony_ci if (tmp) { 2753e5b75505Sopenharmony_ci buf = os_strchr(tmp, ' '); 2754e5b75505Sopenharmony_ci if (buf) 2755e5b75505Sopenharmony_ci *buf++ = '\0'; 2756e5b75505Sopenharmony_ci civic = wpabuf_parse_bin(tmp + 6); 2757e5b75505Sopenharmony_ci if (!civic) { 2758e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2759e5b75505Sopenharmony_ci "CTRL: SET_NEIGHBOR: Bad civic subelement"); 2760e5b75505Sopenharmony_ci wpabuf_free(nr); 2761e5b75505Sopenharmony_ci wpabuf_free(lci); 2762e5b75505Sopenharmony_ci return -1; 2763e5b75505Sopenharmony_ci } 2764e5b75505Sopenharmony_ci } 2765e5b75505Sopenharmony_ci 2766e5b75505Sopenharmony_ci if (!buf) 2767e5b75505Sopenharmony_ci goto set; 2768e5b75505Sopenharmony_ci 2769e5b75505Sopenharmony_ci if (os_strstr(buf, "stat")) 2770e5b75505Sopenharmony_ci stationary = 1; 2771e5b75505Sopenharmony_ci 2772e5b75505Sopenharmony_ciset: 2773e5b75505Sopenharmony_ci ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic, 2774e5b75505Sopenharmony_ci stationary); 2775e5b75505Sopenharmony_ci 2776e5b75505Sopenharmony_ci wpabuf_free(nr); 2777e5b75505Sopenharmony_ci wpabuf_free(lci); 2778e5b75505Sopenharmony_ci wpabuf_free(civic); 2779e5b75505Sopenharmony_ci 2780e5b75505Sopenharmony_ci return ret; 2781e5b75505Sopenharmony_ci} 2782e5b75505Sopenharmony_ci 2783e5b75505Sopenharmony_ci 2784e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, 2785e5b75505Sopenharmony_ci char *buf) 2786e5b75505Sopenharmony_ci{ 2787e5b75505Sopenharmony_ci struct wpa_ssid_value ssid; 2788e5b75505Sopenharmony_ci u8 bssid[ETH_ALEN]; 2789e5b75505Sopenharmony_ci char *tmp; 2790e5b75505Sopenharmony_ci 2791e5b75505Sopenharmony_ci if (hwaddr_aton(buf, bssid)) { 2792e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID"); 2793e5b75505Sopenharmony_ci return -1; 2794e5b75505Sopenharmony_ci } 2795e5b75505Sopenharmony_ci 2796e5b75505Sopenharmony_ci tmp = os_strstr(buf, "ssid="); 2797e5b75505Sopenharmony_ci if (!tmp || ssid_parse(tmp + 5, &ssid)) { 2798e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 2799e5b75505Sopenharmony_ci "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID"); 2800e5b75505Sopenharmony_ci return -1; 2801e5b75505Sopenharmony_ci } 2802e5b75505Sopenharmony_ci 2803e5b75505Sopenharmony_ci return hostapd_neighbor_remove(hapd, bssid, &ssid); 2804e5b75505Sopenharmony_ci} 2805e5b75505Sopenharmony_ci 2806e5b75505Sopenharmony_ci 2807e5b75505Sopenharmony_cistatic int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, 2808e5b75505Sopenharmony_ci size_t buflen) 2809e5b75505Sopenharmony_ci{ 2810e5b75505Sopenharmony_ci int ret, i; 2811e5b75505Sopenharmony_ci char *pos, *end; 2812e5b75505Sopenharmony_ci 2813e5b75505Sopenharmony_ci ret = os_snprintf(buf, buflen, "%016llX:\n", 2814e5b75505Sopenharmony_ci (long long unsigned) iface->drv_flags); 2815e5b75505Sopenharmony_ci if (os_snprintf_error(buflen, ret)) 2816e5b75505Sopenharmony_ci return -1; 2817e5b75505Sopenharmony_ci 2818e5b75505Sopenharmony_ci pos = buf + ret; 2819e5b75505Sopenharmony_ci end = buf + buflen; 2820e5b75505Sopenharmony_ci 2821e5b75505Sopenharmony_ci for (i = 0; i < 64; i++) { 2822e5b75505Sopenharmony_ci if (iface->drv_flags & (1LLU << i)) { 2823e5b75505Sopenharmony_ci ret = os_snprintf(pos, end - pos, "%s\n", 2824e5b75505Sopenharmony_ci driver_flag_to_string(1LLU << i)); 2825e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, ret)) 2826e5b75505Sopenharmony_ci return -1; 2827e5b75505Sopenharmony_ci pos += ret; 2828e5b75505Sopenharmony_ci } 2829e5b75505Sopenharmony_ci } 2830e5b75505Sopenharmony_ci 2831e5b75505Sopenharmony_ci return pos - buf; 2832e5b75505Sopenharmony_ci} 2833e5b75505Sopenharmony_ci 2834e5b75505Sopenharmony_ci 2835e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, 2836e5b75505Sopenharmony_ci const char *txtaddr) 2837e5b75505Sopenharmony_ci{ 2838e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2839e5b75505Sopenharmony_ci struct vlan_description vlan_id; 2840e5b75505Sopenharmony_ci 2841e5b75505Sopenharmony_ci if (!(*num)) 2842e5b75505Sopenharmony_ci return 0; 2843e5b75505Sopenharmony_ci 2844e5b75505Sopenharmony_ci if (hwaddr_aton(txtaddr, addr)) 2845e5b75505Sopenharmony_ci return -1; 2846e5b75505Sopenharmony_ci 2847e5b75505Sopenharmony_ci if (hostapd_maclist_found(*acl, *num, addr, &vlan_id)) 2848e5b75505Sopenharmony_ci hostapd_remove_acl_mac(acl, num, addr); 2849e5b75505Sopenharmony_ci 2850e5b75505Sopenharmony_ci return 0; 2851e5b75505Sopenharmony_ci} 2852e5b75505Sopenharmony_ci 2853e5b75505Sopenharmony_ci 2854e5b75505Sopenharmony_cistatic void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, 2855e5b75505Sopenharmony_ci int *num) 2856e5b75505Sopenharmony_ci{ 2857e5b75505Sopenharmony_ci while (*num) 2858e5b75505Sopenharmony_ci hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); 2859e5b75505Sopenharmony_ci} 2860e5b75505Sopenharmony_ci 2861e5b75505Sopenharmony_ci 2862e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, 2863e5b75505Sopenharmony_ci char *buf, size_t buflen) 2864e5b75505Sopenharmony_ci{ 2865e5b75505Sopenharmony_ci int i = 0, len = 0, ret = 0; 2866e5b75505Sopenharmony_ci 2867e5b75505Sopenharmony_ci if (!acl) 2868e5b75505Sopenharmony_ci return 0; 2869e5b75505Sopenharmony_ci 2870e5b75505Sopenharmony_ci while (i < num) { 2871e5b75505Sopenharmony_ci ret = os_snprintf(buf + len, buflen - len, 2872e5b75505Sopenharmony_ci MACSTR " VLAN_ID=%d\n", 2873e5b75505Sopenharmony_ci MAC2STR(acl[i].addr), 2874e5b75505Sopenharmony_ci acl[i].vlan_id.untagged); 2875e5b75505Sopenharmony_ci if (ret < 0 || (size_t) ret >= buflen - len) 2876e5b75505Sopenharmony_ci return len; 2877e5b75505Sopenharmony_ci i++; 2878e5b75505Sopenharmony_ci len += ret; 2879e5b75505Sopenharmony_ci } 2880e5b75505Sopenharmony_ci return len; 2881e5b75505Sopenharmony_ci} 2882e5b75505Sopenharmony_ci 2883e5b75505Sopenharmony_ci 2884e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, 2885e5b75505Sopenharmony_ci const char *cmd) 2886e5b75505Sopenharmony_ci{ 2887e5b75505Sopenharmony_ci u8 addr[ETH_ALEN]; 2888e5b75505Sopenharmony_ci struct vlan_description vlan_id; 2889e5b75505Sopenharmony_ci int ret = 0, vlanid = 0; 2890e5b75505Sopenharmony_ci const char *pos; 2891e5b75505Sopenharmony_ci 2892e5b75505Sopenharmony_ci if (hwaddr_aton(cmd, addr)) 2893e5b75505Sopenharmony_ci return -1; 2894e5b75505Sopenharmony_ci 2895e5b75505Sopenharmony_ci pos = os_strstr(cmd, "VLAN_ID="); 2896e5b75505Sopenharmony_ci if (pos) 2897e5b75505Sopenharmony_ci vlanid = atoi(pos + 8); 2898e5b75505Sopenharmony_ci 2899e5b75505Sopenharmony_ci if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) { 2900e5b75505Sopenharmony_ci ret = hostapd_add_acl_maclist(acl, num, vlanid, addr); 2901e5b75505Sopenharmony_ci if (ret != -1 && *acl) 2902e5b75505Sopenharmony_ci qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); 2903e5b75505Sopenharmony_ci } 2904e5b75505Sopenharmony_ci 2905e5b75505Sopenharmony_ci return ret < 0 ? -1 : 0; 2906e5b75505Sopenharmony_ci} 2907e5b75505Sopenharmony_ci 2908e5b75505Sopenharmony_ci 2909e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd, 2910e5b75505Sopenharmony_ci const char *field, char *buf, 2911e5b75505Sopenharmony_ci size_t buflen) 2912e5b75505Sopenharmony_ci{ 2913e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field); 2914e5b75505Sopenharmony_ci 2915e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 2916e5b75505Sopenharmony_ci if (os_strcmp(field, "dpp") == 0) { 2917e5b75505Sopenharmony_ci int res; 2918e5b75505Sopenharmony_ci 2919e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 2920e5b75505Sopenharmony_ci res = os_snprintf(buf, buflen, "DPP=2"); 2921e5b75505Sopenharmony_ci#else /* CONFIG_DPP2 */ 2922e5b75505Sopenharmony_ci res = os_snprintf(buf, buflen, "DPP=1"); 2923e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 2924e5b75505Sopenharmony_ci if (os_snprintf_error(buflen, res)) 2925e5b75505Sopenharmony_ci return -1; 2926e5b75505Sopenharmony_ci return res; 2927e5b75505Sopenharmony_ci } 2928e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 2929e5b75505Sopenharmony_ci 2930e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 2931e5b75505Sopenharmony_ci field); 2932e5b75505Sopenharmony_ci 2933e5b75505Sopenharmony_ci return -1; 2934e5b75505Sopenharmony_ci} 2935e5b75505Sopenharmony_ci 2936e5b75505Sopenharmony_ci 2937e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, 2938e5b75505Sopenharmony_ci char *buf, char *reply, 2939e5b75505Sopenharmony_ci int reply_size, 2940e5b75505Sopenharmony_ci struct sockaddr_storage *from, 2941e5b75505Sopenharmony_ci socklen_t fromlen) 2942e5b75505Sopenharmony_ci{ 2943e5b75505Sopenharmony_ci int reply_len, res; 2944e5b75505Sopenharmony_ci 2945e5b75505Sopenharmony_ci os_memcpy(reply, "OK\n", 3); 2946e5b75505Sopenharmony_ci reply_len = 3; 2947e5b75505Sopenharmony_ci 2948e5b75505Sopenharmony_ci if (os_strcmp(buf, "PING") == 0) { 2949e5b75505Sopenharmony_ci os_memcpy(reply, "PONG\n", 5); 2950e5b75505Sopenharmony_ci reply_len = 5; 2951e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RELOG", 5) == 0) { 2952e5b75505Sopenharmony_ci if (wpa_debug_reopen_file() < 0) 2953e5b75505Sopenharmony_ci reply_len = -1; 2954e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 2955e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 2956e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "STATUS") == 0) { 2957e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_status(hapd, reply, 2958e5b75505Sopenharmony_ci reply_size); 2959e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { 2960e5b75505Sopenharmony_ci reply_len = hostapd_drv_status(hapd, reply, reply_size); 2961e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "MIB") == 0) { 2962e5b75505Sopenharmony_ci reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 2963e5b75505Sopenharmony_ci if (reply_len >= 0) { 2964e5b75505Sopenharmony_ci res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 2965e5b75505Sopenharmony_ci reply_size - reply_len); 2966e5b75505Sopenharmony_ci if (res < 0) 2967e5b75505Sopenharmony_ci reply_len = -1; 2968e5b75505Sopenharmony_ci else 2969e5b75505Sopenharmony_ci reply_len += res; 2970e5b75505Sopenharmony_ci } 2971e5b75505Sopenharmony_ci if (reply_len >= 0) { 2972e5b75505Sopenharmony_ci res = ieee802_1x_get_mib(hapd, reply + reply_len, 2973e5b75505Sopenharmony_ci reply_size - reply_len); 2974e5b75505Sopenharmony_ci if (res < 0) 2975e5b75505Sopenharmony_ci reply_len = -1; 2976e5b75505Sopenharmony_ci else 2977e5b75505Sopenharmony_ci reply_len += res; 2978e5b75505Sopenharmony_ci } 2979e5b75505Sopenharmony_ci#ifndef CONFIG_NO_RADIUS 2980e5b75505Sopenharmony_ci if (reply_len >= 0) { 2981e5b75505Sopenharmony_ci res = radius_client_get_mib(hapd->radius, 2982e5b75505Sopenharmony_ci reply + reply_len, 2983e5b75505Sopenharmony_ci reply_size - reply_len); 2984e5b75505Sopenharmony_ci if (res < 0) 2985e5b75505Sopenharmony_ci reply_len = -1; 2986e5b75505Sopenharmony_ci else 2987e5b75505Sopenharmony_ci reply_len += res; 2988e5b75505Sopenharmony_ci } 2989e5b75505Sopenharmony_ci#endif /* CONFIG_NO_RADIUS */ 2990e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "MIB ", 4) == 0) { 2991e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size, 2992e5b75505Sopenharmony_ci buf + 4); 2993e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "STA-FIRST") == 0) { 2994e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 2995e5b75505Sopenharmony_ci reply_size); 2996e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "STA ", 4) == 0) { 2997e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 2998e5b75505Sopenharmony_ci reply_size); 2999e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 3000e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 3001e5b75505Sopenharmony_ci reply_size); 3002e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "ATTACH") == 0) { 3003e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL)) 3004e5b75505Sopenharmony_ci reply_len = -1; 3005e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "ATTACH ", 7) == 0) { 3006e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_attach(hapd, from, fromlen, buf + 7)) 3007e5b75505Sopenharmony_ci reply_len = -1; 3008e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "DETACH") == 0) { 3009e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_detach(hapd, from, fromlen)) 3010e5b75505Sopenharmony_ci reply_len = -1; 3011e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 3012e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_level(hapd, from, fromlen, 3013e5b75505Sopenharmony_ci buf + 6)) 3014e5b75505Sopenharmony_ci reply_len = -1; 3015e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 3016e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 3017e5b75505Sopenharmony_ci reply_len = -1; 3018e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 3019e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 3020e5b75505Sopenharmony_ci reply_len = -1; 3021e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 3022e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 3023e5b75505Sopenharmony_ci reply_len = -1; 3024e5b75505Sopenharmony_ci#ifdef CONFIG_TAXONOMY 3025e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) { 3026e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10, 3027e5b75505Sopenharmony_ci reply, reply_size); 3028e5b75505Sopenharmony_ci#endif /* CONFIG_TAXONOMY */ 3029e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) { 3030e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9)) 3031e5b75505Sopenharmony_ci reply_len = -1; 3032e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "STOP_AP") == 0) { 3033e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_stop_ap(hapd)) 3034e5b75505Sopenharmony_ci reply_len = -1; 3035e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211W 3036e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 3037e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 3038e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 3039e5b75505Sopenharmony_ci reply_len = -1; 3040e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 3041e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211W */ 3042e5b75505Sopenharmony_ci#ifdef CONFIG_WPS 3043e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 3044e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 3045e5b75505Sopenharmony_ci reply_len = -1; 3046e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 3047e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_wps_check_pin( 3048e5b75505Sopenharmony_ci hapd, buf + 14, reply, reply_size); 3049e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "WPS_PBC") == 0) { 3050e5b75505Sopenharmony_ci if (hostapd_wps_button_pushed(hapd, NULL)) 3051e5b75505Sopenharmony_ci reply_len = -1; 3052e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 3053e5b75505Sopenharmony_ci if (hostapd_wps_cancel(hapd)) 3054e5b75505Sopenharmony_ci reply_len = -1; 3055e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 3056e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 3057e5b75505Sopenharmony_ci reply, reply_size); 3058e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 3059e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 3060e5b75505Sopenharmony_ci reply_len = -1; 3061e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 3062e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 3063e5b75505Sopenharmony_ci reply_size); 3064e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_NFC 3065e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 3066e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 3067e5b75505Sopenharmony_ci reply_len = -1; 3068e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 3069e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 3070e5b75505Sopenharmony_ci hapd, buf + 21, reply, reply_size); 3071e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 3072e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_wps_nfc_token( 3073e5b75505Sopenharmony_ci hapd, buf + 14, reply, reply_size); 3074e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 3075e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 3076e5b75505Sopenharmony_ci hapd, buf + 21, reply, reply_size); 3077e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 3078e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 3079e5b75505Sopenharmony_ci reply_len = -1; 3080e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_NFC */ 3081e5b75505Sopenharmony_ci#endif /* CONFIG_WPS */ 3082e5b75505Sopenharmony_ci#ifdef CONFIG_INTERWORKING 3083e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) { 3084e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16)) 3085e5b75505Sopenharmony_ci reply_len = -1; 3086e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) { 3087e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18)) 3088e5b75505Sopenharmony_ci reply_len = -1; 3089e5b75505Sopenharmony_ci#endif /* CONFIG_INTERWORKING */ 3090e5b75505Sopenharmony_ci#ifdef CONFIG_HS20 3091e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) { 3092e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15)) 3093e5b75505Sopenharmony_ci reply_len = -1; 3094e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) { 3095e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16)) 3096e5b75505Sopenharmony_ci reply_len = -1; 3097e5b75505Sopenharmony_ci#endif /* CONFIG_HS20 */ 3098e5b75505Sopenharmony_ci#ifdef CONFIG_WNM_AP 3099e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 3100e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 3101e5b75505Sopenharmony_ci reply_len = -1; 3102e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 3103e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 3104e5b75505Sopenharmony_ci reply_len = -1; 3105e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 3106e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11)) 3107e5b75505Sopenharmony_ci reply_len = -1; 3108e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) { 3109e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15)) 3110e5b75505Sopenharmony_ci reply_len = -1; 3111e5b75505Sopenharmony_ci#endif /* CONFIG_WNM_AP */ 3112e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 3113e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 3114e5b75505Sopenharmony_ci reply_size); 3115e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SET ", 4) == 0) { 3116e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_set(hapd, buf + 4)) 3117e5b75505Sopenharmony_ci reply_len = -1; 3118e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "GET ", 4) == 0) { 3119e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 3120e5b75505Sopenharmony_ci reply_size); 3121e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 3122e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_enable(hapd->iface)) 3123e5b75505Sopenharmony_ci reply_len = -1; 3124e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) { 3125e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_reload_wpa_psk(hapd)) 3126e5b75505Sopenharmony_ci reply_len = -1; 3127e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 3128e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_reload(hapd->iface)) 3129e5b75505Sopenharmony_ci reply_len = -1; 3130e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 3131e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_disable(hapd->iface)) 3132e5b75505Sopenharmony_ci reply_len = -1; 3133e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { 3134e5b75505Sopenharmony_ci if (ieee802_11_set_beacon(hapd)) 3135e5b75505Sopenharmony_ci reply_len = -1; 3136e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 3137e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RADAR ", 6) == 0) { 3138e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_radar(hapd, buf + 6)) 3139e5b75505Sopenharmony_ci reply_len = -1; 3140e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 3141e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8)) 3142e5b75505Sopenharmony_ci reply_len = -1; 3143e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "MGMT_TX_STATUS_PROCESS ", 23) == 0) { 3144e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_mgmt_tx_status_process(hapd, 3145e5b75505Sopenharmony_ci buf + 23) < 0) 3146e5b75505Sopenharmony_ci reply_len = -1; 3147e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 3148e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0) 3149e5b75505Sopenharmony_ci reply_len = -1; 3150e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 3151e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0) 3152e5b75505Sopenharmony_ci reply_len = -1; 3153e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 3154e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0) 3155e5b75505Sopenharmony_ci reply_len = -1; 3156e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 3157e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0) 3158e5b75505Sopenharmony_ci reply_len = -1; 3159e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 3160e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0) 3161e5b75505Sopenharmony_ci reply_len = -1; 3162e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 3163e5b75505Sopenharmony_ci if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0) 3164e5b75505Sopenharmony_ci reply_len = -1; 3165e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 3166e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply, 3167e5b75505Sopenharmony_ci reply_size); 3168e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 3169e5b75505Sopenharmony_ci if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0) 3170e5b75505Sopenharmony_ci reply_len = -1; 3171e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "GET_FAIL") == 0) { 3172e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size); 3173e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RESET_PN ", 9) == 0) { 3174e5b75505Sopenharmony_ci if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0) 3175e5b75505Sopenharmony_ci reply_len = -1; 3176e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SET_KEY ", 8) == 0) { 3177e5b75505Sopenharmony_ci if (hostapd_ctrl_set_key(hapd, buf + 8) < 0) 3178e5b75505Sopenharmony_ci reply_len = -1; 3179e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RESEND_M1 ", 10) == 0) { 3180e5b75505Sopenharmony_ci if (hostapd_ctrl_resend_m1(hapd, buf + 10) < 0) 3181e5b75505Sopenharmony_ci reply_len = -1; 3182e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RESEND_M3 ", 10) == 0) { 3183e5b75505Sopenharmony_ci if (hostapd_ctrl_resend_m3(hapd, buf + 10) < 0) 3184e5b75505Sopenharmony_ci reply_len = -1; 3185e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) { 3186e5b75505Sopenharmony_ci if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0) 3187e5b75505Sopenharmony_ci reply_len = -1; 3188e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "REKEY_GTK") == 0) { 3189e5b75505Sopenharmony_ci if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0) 3190e5b75505Sopenharmony_ci reply_len = -1; 3191e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 3192e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 3193e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) 3194e5b75505Sopenharmony_ci reply_len = -1; 3195e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 3196e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, 3197e5b75505Sopenharmony_ci reply_size); 3198e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 3199e5b75505Sopenharmony_ci ieee802_1x_erp_flush(hapd); 3200e5b75505Sopenharmony_ci#ifdef RADIUS_SERVER 3201e5b75505Sopenharmony_ci radius_server_erp_flush(hapd->radius_srv); 3202e5b75505Sopenharmony_ci#endif /* RADIUS_SERVER */ 3203e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) { 3204e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13)) 3205e5b75505Sopenharmony_ci reply_len = -1; 3206e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) { 3207e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10)) 3208e5b75505Sopenharmony_ci reply_len = -1; 3209e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 3210e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_log_level( 3211e5b75505Sopenharmony_ci hapd, buf + 9, reply, reply_size); 3212e5b75505Sopenharmony_ci#ifdef NEED_AP_MLME 3213e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) { 3214e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_track_sta_list( 3215e5b75505Sopenharmony_ci hapd, reply, reply_size); 3216e5b75505Sopenharmony_ci#endif /* NEED_AP_MLME */ 3217e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "PMKSA") == 0) { 3218e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply, 3219e5b75505Sopenharmony_ci reply_size); 3220e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 3221e5b75505Sopenharmony_ci hostapd_ctrl_iface_pmksa_flush(hapd); 3222e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { 3223e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_pmksa_add(hapd, buf + 10) < 0) 3224e5b75505Sopenharmony_ci reply_len = -1; 3225e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) { 3226e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13)) 3227e5b75505Sopenharmony_ci reply_len = -1; 3228e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) { 3229e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16)) 3230e5b75505Sopenharmony_ci reply_len = -1; 3231e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) { 3232e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_req_lci(hapd, buf + 8)) 3233e5b75505Sopenharmony_ci reply_len = -1; 3234e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) { 3235e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_req_range(hapd, buf + 10)) 3236e5b75505Sopenharmony_ci reply_len = -1; 3237e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) { 3238e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11, 3239e5b75505Sopenharmony_ci reply, reply_size); 3240e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 3241e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply, 3242e5b75505Sopenharmony_ci reply_size); 3243e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "TERMINATE") == 0) { 3244e5b75505Sopenharmony_ci eloop_terminate(); 3245e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { 3246e5b75505Sopenharmony_ci if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { 3247e5b75505Sopenharmony_ci if (!hostapd_ctrl_iface_acl_add_mac( 3248e5b75505Sopenharmony_ci &hapd->conf->accept_mac, 3249e5b75505Sopenharmony_ci &hapd->conf->num_accept_mac, buf + 19)) 3250e5b75505Sopenharmony_ci hostapd_disassoc_accept_mac(hapd); 3251e5b75505Sopenharmony_ci else 3252e5b75505Sopenharmony_ci reply_len = -1; 3253e5b75505Sopenharmony_ci } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { 3254e5b75505Sopenharmony_ci hostapd_ctrl_iface_acl_del_mac( 3255e5b75505Sopenharmony_ci &hapd->conf->accept_mac, 3256e5b75505Sopenharmony_ci &hapd->conf->num_accept_mac, buf + 19); 3257e5b75505Sopenharmony_ci } else if (os_strcmp(buf + 11, "SHOW") == 0) { 3258e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_acl_show_mac( 3259e5b75505Sopenharmony_ci hapd->conf->accept_mac, 3260e5b75505Sopenharmony_ci hapd->conf->num_accept_mac, reply, reply_size); 3261e5b75505Sopenharmony_ci } else if (os_strcmp(buf + 11, "CLEAR") == 0) { 3262e5b75505Sopenharmony_ci hostapd_ctrl_iface_acl_clear_list( 3263e5b75505Sopenharmony_ci &hapd->conf->accept_mac, 3264e5b75505Sopenharmony_ci &hapd->conf->num_accept_mac); 3265e5b75505Sopenharmony_ci } 3266e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { 3267e5b75505Sopenharmony_ci if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { 3268e5b75505Sopenharmony_ci if (!hostapd_ctrl_iface_acl_add_mac( 3269e5b75505Sopenharmony_ci &hapd->conf->deny_mac, 3270e5b75505Sopenharmony_ci &hapd->conf->num_deny_mac, buf + 17)) 3271e5b75505Sopenharmony_ci hostapd_disassoc_deny_mac(hapd); 3272e5b75505Sopenharmony_ci } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { 3273e5b75505Sopenharmony_ci hostapd_ctrl_iface_acl_del_mac( 3274e5b75505Sopenharmony_ci &hapd->conf->deny_mac, 3275e5b75505Sopenharmony_ci &hapd->conf->num_deny_mac, buf + 17); 3276e5b75505Sopenharmony_ci } else if (os_strcmp(buf + 9, "SHOW") == 0) { 3277e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_acl_show_mac( 3278e5b75505Sopenharmony_ci hapd->conf->deny_mac, 3279e5b75505Sopenharmony_ci hapd->conf->num_deny_mac, reply, reply_size); 3280e5b75505Sopenharmony_ci } else if (os_strcmp(buf + 9, "CLEAR") == 0) { 3281e5b75505Sopenharmony_ci hostapd_ctrl_iface_acl_clear_list( 3282e5b75505Sopenharmony_ci &hapd->conf->deny_mac, 3283e5b75505Sopenharmony_ci &hapd->conf->num_deny_mac); 3284e5b75505Sopenharmony_ci } 3285e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 3286e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { 3287e5b75505Sopenharmony_ci res = hostapd_dpp_qr_code(hapd, buf + 12); 3288e5b75505Sopenharmony_ci if (res < 0) { 3289e5b75505Sopenharmony_ci reply_len = -1; 3290e5b75505Sopenharmony_ci } else { 3291e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "%d", res); 3292e5b75505Sopenharmony_ci if (os_snprintf_error(reply_size, reply_len)) 3293e5b75505Sopenharmony_ci reply_len = -1; 3294e5b75505Sopenharmony_ci } 3295e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { 3296e5b75505Sopenharmony_ci res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18); 3297e5b75505Sopenharmony_ci if (res < 0) { 3298e5b75505Sopenharmony_ci reply_len = -1; 3299e5b75505Sopenharmony_ci } else { 3300e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "%d", res); 3301e5b75505Sopenharmony_ci if (os_snprintf_error(reply_size, reply_len)) 3302e5b75505Sopenharmony_ci reply_len = -1; 3303e5b75505Sopenharmony_ci } 3304e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { 3305e5b75505Sopenharmony_ci if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp, 3306e5b75505Sopenharmony_ci buf + 21) < 0) 3307e5b75505Sopenharmony_ci reply_len = -1; 3308e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 3309e5b75505Sopenharmony_ci const char *uri; 3310e5b75505Sopenharmony_ci 3311e5b75505Sopenharmony_ci uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp, 3312e5b75505Sopenharmony_ci atoi(buf + 22)); 3313e5b75505Sopenharmony_ci if (!uri) { 3314e5b75505Sopenharmony_ci reply_len = -1; 3315e5b75505Sopenharmony_ci } else { 3316e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "%s", uri); 3317e5b75505Sopenharmony_ci if (os_snprintf_error(reply_size, reply_len)) 3318e5b75505Sopenharmony_ci reply_len = -1; 3319e5b75505Sopenharmony_ci } 3320e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { 3321e5b75505Sopenharmony_ci reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp, 3322e5b75505Sopenharmony_ci atoi(buf + 19), 3323e5b75505Sopenharmony_ci reply, reply_size); 3324e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { 3325e5b75505Sopenharmony_ci if (hostapd_dpp_auth_init(hapd, buf + 13) < 0) 3326e5b75505Sopenharmony_ci reply_len = -1; 3327e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { 3328e5b75505Sopenharmony_ci if (hostapd_dpp_listen(hapd, buf + 11) < 0) 3329e5b75505Sopenharmony_ci reply_len = -1; 3330e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { 3331e5b75505Sopenharmony_ci hostapd_dpp_stop(hapd); 3332e5b75505Sopenharmony_ci hostapd_dpp_listen_stop(hapd); 3333e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { 3334e5b75505Sopenharmony_ci res = dpp_configurator_add(hapd->iface->interfaces->dpp, 3335e5b75505Sopenharmony_ci buf + 20); 3336e5b75505Sopenharmony_ci if (res < 0) { 3337e5b75505Sopenharmony_ci reply_len = -1; 3338e5b75505Sopenharmony_ci } else { 3339e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "%d", res); 3340e5b75505Sopenharmony_ci if (os_snprintf_error(reply_size, reply_len)) 3341e5b75505Sopenharmony_ci reply_len = -1; 3342e5b75505Sopenharmony_ci } 3343e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { 3344e5b75505Sopenharmony_ci if (dpp_configurator_remove(hapd->iface->interfaces->dpp, 3345e5b75505Sopenharmony_ci buf + 24) < 0) 3346e5b75505Sopenharmony_ci reply_len = -1; 3347e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { 3348e5b75505Sopenharmony_ci if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0) 3349e5b75505Sopenharmony_ci reply_len = -1; 3350e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { 3351e5b75505Sopenharmony_ci reply_len = dpp_configurator_get_key_id( 3352e5b75505Sopenharmony_ci hapd->iface->interfaces->dpp, 3353e5b75505Sopenharmony_ci atoi(buf + 25), 3354e5b75505Sopenharmony_ci reply, reply_size); 3355e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { 3356e5b75505Sopenharmony_ci res = hostapd_dpp_pkex_add(hapd, buf + 12); 3357e5b75505Sopenharmony_ci if (res < 0) { 3358e5b75505Sopenharmony_ci reply_len = -1; 3359e5b75505Sopenharmony_ci } else { 3360e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "%d", res); 3361e5b75505Sopenharmony_ci if (os_snprintf_error(reply_size, reply_len)) 3362e5b75505Sopenharmony_ci reply_len = -1; 3363e5b75505Sopenharmony_ci } 3364e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { 3365e5b75505Sopenharmony_ci if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0) 3366e5b75505Sopenharmony_ci reply_len = -1; 3367e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 3368e5b75505Sopenharmony_ci#ifdef RADIUS_SERVER 3369e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) { 3370e5b75505Sopenharmony_ci if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0) 3371e5b75505Sopenharmony_ci reply_len = -1; 3372e5b75505Sopenharmony_ci#endif /* RADIUS_SERVER */ 3373e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 3374e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_get_capability( 3375e5b75505Sopenharmony_ci hapd, buf + 15, reply, reply_size); 3376e5b75505Sopenharmony_ci } else { 3377e5b75505Sopenharmony_ci os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 3378e5b75505Sopenharmony_ci reply_len = 16; 3379e5b75505Sopenharmony_ci } 3380e5b75505Sopenharmony_ci 3381e5b75505Sopenharmony_ci if (reply_len < 0) { 3382e5b75505Sopenharmony_ci os_memcpy(reply, "FAIL\n", 5); 3383e5b75505Sopenharmony_ci reply_len = 5; 3384e5b75505Sopenharmony_ci } 3385e5b75505Sopenharmony_ci 3386e5b75505Sopenharmony_ci return reply_len; 3387e5b75505Sopenharmony_ci} 3388e5b75505Sopenharmony_ci 3389e5b75505Sopenharmony_ci 3390e5b75505Sopenharmony_cistatic void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 3391e5b75505Sopenharmony_ci void *sock_ctx) 3392e5b75505Sopenharmony_ci{ 3393e5b75505Sopenharmony_ci struct hostapd_data *hapd = eloop_ctx; 3394e5b75505Sopenharmony_ci char buf[4096]; 3395e5b75505Sopenharmony_ci int res; 3396e5b75505Sopenharmony_ci struct sockaddr_storage from; 3397e5b75505Sopenharmony_ci socklen_t fromlen = sizeof(from); 3398e5b75505Sopenharmony_ci char *reply, *pos = buf; 3399e5b75505Sopenharmony_ci const int reply_size = 4096; 3400e5b75505Sopenharmony_ci int reply_len; 3401e5b75505Sopenharmony_ci int level = MSG_DEBUG; 3402e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 3403e5b75505Sopenharmony_ci unsigned char lcookie[COOKIE_LEN]; 3404e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 3405e5b75505Sopenharmony_ci 3406e5b75505Sopenharmony_ci res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 3407e5b75505Sopenharmony_ci (struct sockaddr *) &from, &fromlen); 3408e5b75505Sopenharmony_ci if (res < 0) { 3409e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 3410e5b75505Sopenharmony_ci strerror(errno)); 3411e5b75505Sopenharmony_ci return; 3412e5b75505Sopenharmony_ci } 3413e5b75505Sopenharmony_ci buf[res] = '\0'; 3414e5b75505Sopenharmony_ci 3415e5b75505Sopenharmony_ci reply = os_malloc(reply_size); 3416e5b75505Sopenharmony_ci if (reply == NULL) { 3417e5b75505Sopenharmony_ci if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 3418e5b75505Sopenharmony_ci fromlen) < 0) { 3419e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 3420e5b75505Sopenharmony_ci strerror(errno)); 3421e5b75505Sopenharmony_ci } 3422e5b75505Sopenharmony_ci return; 3423e5b75505Sopenharmony_ci } 3424e5b75505Sopenharmony_ci 3425e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 3426e5b75505Sopenharmony_ci if (os_strcmp(buf, "GET_COOKIE") == 0) { 3427e5b75505Sopenharmony_ci os_memcpy(reply, "COOKIE=", 7); 3428e5b75505Sopenharmony_ci wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 3429e5b75505Sopenharmony_ci cookie, COOKIE_LEN); 3430e5b75505Sopenharmony_ci reply_len = 7 + 2 * COOKIE_LEN; 3431e5b75505Sopenharmony_ci goto done; 3432e5b75505Sopenharmony_ci } 3433e5b75505Sopenharmony_ci 3434e5b75505Sopenharmony_ci if (os_strncmp(buf, "COOKIE=", 7) != 0 || 3435e5b75505Sopenharmony_ci hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { 3436e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 3437e5b75505Sopenharmony_ci "CTRL: No cookie in the request - drop request"); 3438e5b75505Sopenharmony_ci os_free(reply); 3439e5b75505Sopenharmony_ci return; 3440e5b75505Sopenharmony_ci } 3441e5b75505Sopenharmony_ci 3442e5b75505Sopenharmony_ci if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) { 3443e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 3444e5b75505Sopenharmony_ci "CTRL: Invalid cookie in the request - drop request"); 3445e5b75505Sopenharmony_ci os_free(reply); 3446e5b75505Sopenharmony_ci return; 3447e5b75505Sopenharmony_ci } 3448e5b75505Sopenharmony_ci 3449e5b75505Sopenharmony_ci pos = buf + 7 + 2 * COOKIE_LEN; 3450e5b75505Sopenharmony_ci while (*pos == ' ') 3451e5b75505Sopenharmony_ci pos++; 3452e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 3453e5b75505Sopenharmony_ci 3454e5b75505Sopenharmony_ci if (os_strcmp(pos, "PING") == 0) 3455e5b75505Sopenharmony_ci level = MSG_EXCESSIVE; 3456e5b75505Sopenharmony_ci wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res); 3457e5b75505Sopenharmony_ci 3458e5b75505Sopenharmony_ci reply_len = hostapd_ctrl_iface_receive_process(hapd, pos, 3459e5b75505Sopenharmony_ci reply, reply_size, 3460e5b75505Sopenharmony_ci &from, fromlen); 3461e5b75505Sopenharmony_ci 3462e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 3463e5b75505Sopenharmony_cidone: 3464e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 3465e5b75505Sopenharmony_ci if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 3466e5b75505Sopenharmony_ci fromlen) < 0) { 3467e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 3468e5b75505Sopenharmony_ci strerror(errno)); 3469e5b75505Sopenharmony_ci } 3470e5b75505Sopenharmony_ci os_free(reply); 3471e5b75505Sopenharmony_ci} 3472e5b75505Sopenharmony_ci 3473e5b75505Sopenharmony_ci 3474e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 3475e5b75505Sopenharmony_cistatic char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 3476e5b75505Sopenharmony_ci{ 3477e5b75505Sopenharmony_ci char *buf; 3478e5b75505Sopenharmony_ci size_t len; 3479e5b75505Sopenharmony_ci 3480e5b75505Sopenharmony_ci if (hapd->conf->ctrl_interface == NULL) 3481e5b75505Sopenharmony_ci return NULL; 3482e5b75505Sopenharmony_ci 3483e5b75505Sopenharmony_ci len = os_strlen(hapd->conf->ctrl_interface) + 3484e5b75505Sopenharmony_ci os_strlen(hapd->conf->iface) + 2; 3485e5b75505Sopenharmony_ci buf = os_malloc(len); 3486e5b75505Sopenharmony_ci if (buf == NULL) 3487e5b75505Sopenharmony_ci return NULL; 3488e5b75505Sopenharmony_ci 3489e5b75505Sopenharmony_ci os_snprintf(buf, len, "%s/%s", 3490e5b75505Sopenharmony_ci hapd->conf->ctrl_interface, hapd->conf->iface); 3491e5b75505Sopenharmony_ci buf[len - 1] = '\0'; 3492e5b75505Sopenharmony_ci return buf; 3493e5b75505Sopenharmony_ci} 3494e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 3495e5b75505Sopenharmony_ci 3496e5b75505Sopenharmony_ci 3497e5b75505Sopenharmony_cistatic void hostapd_ctrl_iface_msg_cb(void *ctx, int level, 3498e5b75505Sopenharmony_ci enum wpa_msg_type type, 3499e5b75505Sopenharmony_ci const char *txt, size_t len) 3500e5b75505Sopenharmony_ci{ 3501e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 3502e5b75505Sopenharmony_ci if (hapd == NULL) 3503e5b75505Sopenharmony_ci return; 3504e5b75505Sopenharmony_ci hostapd_ctrl_iface_send(hapd, level, type, txt, len); 3505e5b75505Sopenharmony_ci} 3506e5b75505Sopenharmony_ci 3507e5b75505Sopenharmony_ci 3508e5b75505Sopenharmony_ciint hostapd_ctrl_iface_init(struct hostapd_data *hapd) 3509e5b75505Sopenharmony_ci{ 3510e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 3511e5b75505Sopenharmony_ci int port = HOSTAPD_CTRL_IFACE_PORT; 3512e5b75505Sopenharmony_ci char p[32] = { 0 }; 3513e5b75505Sopenharmony_ci char port_str[40], *tmp; 3514e5b75505Sopenharmony_ci char *pos; 3515e5b75505Sopenharmony_ci struct addrinfo hints = { 0 }, *res, *saveres; 3516e5b75505Sopenharmony_ci int n; 3517e5b75505Sopenharmony_ci 3518e5b75505Sopenharmony_ci if (hapd->ctrl_sock > -1) { 3519e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 3520e5b75505Sopenharmony_ci return 0; 3521e5b75505Sopenharmony_ci } 3522e5b75505Sopenharmony_ci 3523e5b75505Sopenharmony_ci if (hapd->conf->ctrl_interface == NULL) 3524e5b75505Sopenharmony_ci return 0; 3525e5b75505Sopenharmony_ci 3526e5b75505Sopenharmony_ci pos = os_strstr(hapd->conf->ctrl_interface, "udp:"); 3527e5b75505Sopenharmony_ci if (pos) { 3528e5b75505Sopenharmony_ci pos += 4; 3529e5b75505Sopenharmony_ci port = atoi(pos); 3530e5b75505Sopenharmony_ci if (port <= 0) { 3531e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port"); 3532e5b75505Sopenharmony_ci goto fail; 3533e5b75505Sopenharmony_ci } 3534e5b75505Sopenharmony_ci } 3535e5b75505Sopenharmony_ci 3536e5b75505Sopenharmony_ci dl_list_init(&hapd->ctrl_dst); 3537e5b75505Sopenharmony_ci hapd->ctrl_sock = -1; 3538e5b75505Sopenharmony_ci os_get_random(cookie, COOKIE_LEN); 3539e5b75505Sopenharmony_ci 3540e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 3541e5b75505Sopenharmony_ci hints.ai_flags = AI_PASSIVE; 3542e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 3543e5b75505Sopenharmony_ci 3544e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 3545e5b75505Sopenharmony_ci hints.ai_family = AF_INET6; 3546e5b75505Sopenharmony_ci#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 3547e5b75505Sopenharmony_ci hints.ai_family = AF_INET; 3548e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 3549e5b75505Sopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 3550e5b75505Sopenharmony_ci 3551e5b75505Sopenharmony_citry_again: 3552e5b75505Sopenharmony_ci os_snprintf(p, sizeof(p), "%d", port); 3553e5b75505Sopenharmony_ci n = getaddrinfo(NULL, p, &hints, &res); 3554e5b75505Sopenharmony_ci if (n) { 3555e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n)); 3556e5b75505Sopenharmony_ci goto fail; 3557e5b75505Sopenharmony_ci } 3558e5b75505Sopenharmony_ci 3559e5b75505Sopenharmony_ci saveres = res; 3560e5b75505Sopenharmony_ci hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype, 3561e5b75505Sopenharmony_ci res->ai_protocol); 3562e5b75505Sopenharmony_ci if (hapd->ctrl_sock < 0) { 3563e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 3564e5b75505Sopenharmony_ci goto fail; 3565e5b75505Sopenharmony_ci } 3566e5b75505Sopenharmony_ci 3567e5b75505Sopenharmony_ci if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) { 3568e5b75505Sopenharmony_ci port--; 3569e5b75505Sopenharmony_ci if ((HOSTAPD_CTRL_IFACE_PORT - port) < 3570e5b75505Sopenharmony_ci HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos) 3571e5b75505Sopenharmony_ci goto try_again; 3572e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 3573e5b75505Sopenharmony_ci goto fail; 3574e5b75505Sopenharmony_ci } 3575e5b75505Sopenharmony_ci 3576e5b75505Sopenharmony_ci freeaddrinfo(saveres); 3577e5b75505Sopenharmony_ci 3578e5b75505Sopenharmony_ci os_snprintf(port_str, sizeof(port_str), "udp:%d", port); 3579e5b75505Sopenharmony_ci tmp = os_strdup(port_str); 3580e5b75505Sopenharmony_ci if (tmp) { 3581e5b75505Sopenharmony_ci os_free(hapd->conf->ctrl_interface); 3582e5b75505Sopenharmony_ci hapd->conf->ctrl_interface = tmp; 3583e5b75505Sopenharmony_ci } 3584e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port); 3585e5b75505Sopenharmony_ci 3586e5b75505Sopenharmony_ci if (eloop_register_read_sock(hapd->ctrl_sock, 3587e5b75505Sopenharmony_ci hostapd_ctrl_iface_receive, hapd, NULL) < 3588e5b75505Sopenharmony_ci 0) { 3589e5b75505Sopenharmony_ci hostapd_ctrl_iface_deinit(hapd); 3590e5b75505Sopenharmony_ci return -1; 3591e5b75505Sopenharmony_ci } 3592e5b75505Sopenharmony_ci 3593e5b75505Sopenharmony_ci hapd->msg_ctx = hapd; 3594e5b75505Sopenharmony_ci wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 3595e5b75505Sopenharmony_ci 3596e5b75505Sopenharmony_ci return 0; 3597e5b75505Sopenharmony_ci 3598e5b75505Sopenharmony_cifail: 3599e5b75505Sopenharmony_ci if (hapd->ctrl_sock >= 0) 3600e5b75505Sopenharmony_ci close(hapd->ctrl_sock); 3601e5b75505Sopenharmony_ci return -1; 3602e5b75505Sopenharmony_ci#else /* CONFIG_CTRL_IFACE_UDP */ 3603e5b75505Sopenharmony_ci struct sockaddr_un addr; 3604e5b75505Sopenharmony_ci int s = -1; 3605e5b75505Sopenharmony_ci char *fname = NULL; 3606e5b75505Sopenharmony_ci 3607e5b75505Sopenharmony_ci if (hapd->ctrl_sock > -1) { 3608e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 3609e5b75505Sopenharmony_ci return 0; 3610e5b75505Sopenharmony_ci } 3611e5b75505Sopenharmony_ci 3612e5b75505Sopenharmony_ci dl_list_init(&hapd->ctrl_dst); 3613e5b75505Sopenharmony_ci 3614e5b75505Sopenharmony_ci if (hapd->conf->ctrl_interface == NULL) 3615e5b75505Sopenharmony_ci return 0; 3616e5b75505Sopenharmony_ci 3617e5b75505Sopenharmony_ci if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 3618e5b75505Sopenharmony_ci if (errno == EEXIST) { 3619e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Using existing control " 3620e5b75505Sopenharmony_ci "interface directory."); 3621e5b75505Sopenharmony_ci } else { 3622e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 3623e5b75505Sopenharmony_ci strerror(errno)); 3624e5b75505Sopenharmony_ci goto fail; 3625e5b75505Sopenharmony_ci } 3626e5b75505Sopenharmony_ci } 3627e5b75505Sopenharmony_ci 3628e5b75505Sopenharmony_ci if (hapd->conf->ctrl_interface_gid_set && 3629e5b75505Sopenharmony_ci lchown(hapd->conf->ctrl_interface, -1, 3630e5b75505Sopenharmony_ci hapd->conf->ctrl_interface_gid) < 0) { 3631e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 3632e5b75505Sopenharmony_ci strerror(errno)); 3633e5b75505Sopenharmony_ci return -1; 3634e5b75505Sopenharmony_ci } 3635e5b75505Sopenharmony_ci 3636e5b75505Sopenharmony_ci if (!hapd->conf->ctrl_interface_gid_set && 3637e5b75505Sopenharmony_ci hapd->iface->interfaces->ctrl_iface_group && 3638e5b75505Sopenharmony_ci lchown(hapd->conf->ctrl_interface, -1, 3639e5b75505Sopenharmony_ci hapd->iface->interfaces->ctrl_iface_group) < 0) { 3640e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 3641e5b75505Sopenharmony_ci strerror(errno)); 3642e5b75505Sopenharmony_ci return -1; 3643e5b75505Sopenharmony_ci } 3644e5b75505Sopenharmony_ci 3645e5b75505Sopenharmony_ci#ifdef ANDROID 3646e5b75505Sopenharmony_ci /* 3647e5b75505Sopenharmony_ci * Android is using umask 0077 which would leave the control interface 3648e5b75505Sopenharmony_ci * directory without group access. This breaks things since Wi-Fi 3649e5b75505Sopenharmony_ci * framework assumes that this directory can be accessed by other 3650e5b75505Sopenharmony_ci * applications in the wifi group. Fix this by adding group access even 3651e5b75505Sopenharmony_ci * if umask value would prevent this. 3652e5b75505Sopenharmony_ci */ 3653e5b75505Sopenharmony_ci if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 3654e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 3655e5b75505Sopenharmony_ci strerror(errno)); 3656e5b75505Sopenharmony_ci /* Try to continue anyway */ 3657e5b75505Sopenharmony_ci } 3658e5b75505Sopenharmony_ci#endif /* ANDROID */ 3659e5b75505Sopenharmony_ci 3660e5b75505Sopenharmony_ci if (os_strlen(hapd->conf->ctrl_interface) + 1 + 3661e5b75505Sopenharmony_ci os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 3662e5b75505Sopenharmony_ci goto fail; 3663e5b75505Sopenharmony_ci 3664e5b75505Sopenharmony_ci s = socket(PF_UNIX, SOCK_DGRAM, 0); 3665e5b75505Sopenharmony_ci if (s < 0) { 3666e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 3667e5b75505Sopenharmony_ci goto fail; 3668e5b75505Sopenharmony_ci } 3669e5b75505Sopenharmony_ci 3670e5b75505Sopenharmony_ci os_memset(&addr, 0, sizeof(addr)); 3671e5b75505Sopenharmony_ci#ifdef __FreeBSD__ 3672e5b75505Sopenharmony_ci addr.sun_len = sizeof(addr); 3673e5b75505Sopenharmony_ci#endif /* __FreeBSD__ */ 3674e5b75505Sopenharmony_ci addr.sun_family = AF_UNIX; 3675e5b75505Sopenharmony_ci fname = hostapd_ctrl_iface_path(hapd); 3676e5b75505Sopenharmony_ci if (fname == NULL) 3677e5b75505Sopenharmony_ci goto fail; 3678e5b75505Sopenharmony_ci os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 3679e5b75505Sopenharmony_ci if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3680e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 3681e5b75505Sopenharmony_ci strerror(errno)); 3682e5b75505Sopenharmony_ci if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3683e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 3684e5b75505Sopenharmony_ci " allow connections - assuming it was left" 3685e5b75505Sopenharmony_ci "over from forced program termination"); 3686e5b75505Sopenharmony_ci if (unlink(fname) < 0) { 3687e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 3688e5b75505Sopenharmony_ci "Could not unlink existing ctrl_iface socket '%s': %s", 3689e5b75505Sopenharmony_ci fname, strerror(errno)); 3690e5b75505Sopenharmony_ci goto fail; 3691e5b75505Sopenharmony_ci } 3692e5b75505Sopenharmony_ci if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 3693e5b75505Sopenharmony_ci 0) { 3694e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 3695e5b75505Sopenharmony_ci "hostapd-ctrl-iface: bind(PF_UNIX): %s", 3696e5b75505Sopenharmony_ci strerror(errno)); 3697e5b75505Sopenharmony_ci goto fail; 3698e5b75505Sopenharmony_ci } 3699e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 3700e5b75505Sopenharmony_ci "ctrl_iface socket '%s'", fname); 3701e5b75505Sopenharmony_ci } else { 3702e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 3703e5b75505Sopenharmony_ci "be in use - cannot override it"); 3704e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 3705e5b75505Sopenharmony_ci "not used anymore", fname); 3706e5b75505Sopenharmony_ci os_free(fname); 3707e5b75505Sopenharmony_ci fname = NULL; 3708e5b75505Sopenharmony_ci goto fail; 3709e5b75505Sopenharmony_ci } 3710e5b75505Sopenharmony_ci } 3711e5b75505Sopenharmony_ci 3712e5b75505Sopenharmony_ci if (hapd->conf->ctrl_interface_gid_set && 3713e5b75505Sopenharmony_ci lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 3714e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s", 3715e5b75505Sopenharmony_ci strerror(errno)); 3716e5b75505Sopenharmony_ci goto fail; 3717e5b75505Sopenharmony_ci } 3718e5b75505Sopenharmony_ci 3719e5b75505Sopenharmony_ci if (!hapd->conf->ctrl_interface_gid_set && 3720e5b75505Sopenharmony_ci hapd->iface->interfaces->ctrl_iface_group && 3721e5b75505Sopenharmony_ci lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 3722e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s", 3723e5b75505Sopenharmony_ci strerror(errno)); 3724e5b75505Sopenharmony_ci goto fail; 3725e5b75505Sopenharmony_ci } 3726e5b75505Sopenharmony_ci 3727e5b75505Sopenharmony_ci if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 3728e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 3729e5b75505Sopenharmony_ci strerror(errno)); 3730e5b75505Sopenharmony_ci goto fail; 3731e5b75505Sopenharmony_ci } 3732e5b75505Sopenharmony_ci os_free(fname); 3733e5b75505Sopenharmony_ci 3734e5b75505Sopenharmony_ci hapd->ctrl_sock = s; 3735e5b75505Sopenharmony_ci if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 3736e5b75505Sopenharmony_ci NULL) < 0) { 3737e5b75505Sopenharmony_ci hostapd_ctrl_iface_deinit(hapd); 3738e5b75505Sopenharmony_ci return -1; 3739e5b75505Sopenharmony_ci } 3740e5b75505Sopenharmony_ci hapd->msg_ctx = hapd; 3741e5b75505Sopenharmony_ci wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 3742e5b75505Sopenharmony_ci 3743e5b75505Sopenharmony_ci return 0; 3744e5b75505Sopenharmony_ci 3745e5b75505Sopenharmony_cifail: 3746e5b75505Sopenharmony_ci if (s >= 0) 3747e5b75505Sopenharmony_ci close(s); 3748e5b75505Sopenharmony_ci if (fname) { 3749e5b75505Sopenharmony_ci unlink(fname); 3750e5b75505Sopenharmony_ci os_free(fname); 3751e5b75505Sopenharmony_ci } 3752e5b75505Sopenharmony_ci return -1; 3753e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 3754e5b75505Sopenharmony_ci} 3755e5b75505Sopenharmony_ci 3756e5b75505Sopenharmony_ci 3757e5b75505Sopenharmony_civoid hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 3758e5b75505Sopenharmony_ci{ 3759e5b75505Sopenharmony_ci struct wpa_ctrl_dst *dst, *prev; 3760e5b75505Sopenharmony_ci 3761e5b75505Sopenharmony_ci if (hapd->ctrl_sock > -1) { 3762e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 3763e5b75505Sopenharmony_ci char *fname; 3764e5b75505Sopenharmony_ci#endif /* !CONFIG_CTRL_IFACE_UDP */ 3765e5b75505Sopenharmony_ci 3766e5b75505Sopenharmony_ci eloop_unregister_read_sock(hapd->ctrl_sock); 3767e5b75505Sopenharmony_ci close(hapd->ctrl_sock); 3768e5b75505Sopenharmony_ci hapd->ctrl_sock = -1; 3769e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 3770e5b75505Sopenharmony_ci fname = hostapd_ctrl_iface_path(hapd); 3771e5b75505Sopenharmony_ci if (fname) 3772e5b75505Sopenharmony_ci unlink(fname); 3773e5b75505Sopenharmony_ci os_free(fname); 3774e5b75505Sopenharmony_ci 3775e5b75505Sopenharmony_ci if (hapd->conf->ctrl_interface && 3776e5b75505Sopenharmony_ci rmdir(hapd->conf->ctrl_interface) < 0) { 3777e5b75505Sopenharmony_ci if (errno == ENOTEMPTY) { 3778e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Control interface " 3779e5b75505Sopenharmony_ci "directory not empty - leaving it " 3780e5b75505Sopenharmony_ci "behind"); 3781e5b75505Sopenharmony_ci } else { 3782e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 3783e5b75505Sopenharmony_ci "rmdir[ctrl_interface=%s]: %s", 3784e5b75505Sopenharmony_ci hapd->conf->ctrl_interface, 3785e5b75505Sopenharmony_ci strerror(errno)); 3786e5b75505Sopenharmony_ci } 3787e5b75505Sopenharmony_ci } 3788e5b75505Sopenharmony_ci#endif /* !CONFIG_CTRL_IFACE_UDP */ 3789e5b75505Sopenharmony_ci } 3790e5b75505Sopenharmony_ci 3791e5b75505Sopenharmony_ci dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst, 3792e5b75505Sopenharmony_ci list) 3793e5b75505Sopenharmony_ci os_free(dst); 3794e5b75505Sopenharmony_ci 3795e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 3796e5b75505Sopenharmony_ci l2_packet_deinit(hapd->l2_test); 3797e5b75505Sopenharmony_ci hapd->l2_test = NULL; 3798e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 3799e5b75505Sopenharmony_ci} 3800e5b75505Sopenharmony_ci 3801e5b75505Sopenharmony_ci 3802e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 3803e5b75505Sopenharmony_ci char *buf) 3804e5b75505Sopenharmony_ci{ 3805e5b75505Sopenharmony_ci if (hostapd_add_iface(interfaces, buf) < 0) { 3806e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 3807e5b75505Sopenharmony_ci return -1; 3808e5b75505Sopenharmony_ci } 3809e5b75505Sopenharmony_ci return 0; 3810e5b75505Sopenharmony_ci} 3811e5b75505Sopenharmony_ci 3812e5b75505Sopenharmony_ci 3813e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 3814e5b75505Sopenharmony_ci char *buf) 3815e5b75505Sopenharmony_ci{ 3816e5b75505Sopenharmony_ci if (hostapd_remove_iface(interfaces, buf) < 0) { 3817e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 3818e5b75505Sopenharmony_ci return -1; 3819e5b75505Sopenharmony_ci } 3820e5b75505Sopenharmony_ci return 0; 3821e5b75505Sopenharmony_ci} 3822e5b75505Sopenharmony_ci 3823e5b75505Sopenharmony_ci 3824e5b75505Sopenharmony_cistatic int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces, 3825e5b75505Sopenharmony_ci struct sockaddr_storage *from, 3826e5b75505Sopenharmony_ci socklen_t fromlen, char *input) 3827e5b75505Sopenharmony_ci{ 3828e5b75505Sopenharmony_ci return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen, 3829e5b75505Sopenharmony_ci input); 3830e5b75505Sopenharmony_ci} 3831e5b75505Sopenharmony_ci 3832e5b75505Sopenharmony_ci 3833e5b75505Sopenharmony_cistatic int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces, 3834e5b75505Sopenharmony_ci struct sockaddr_storage *from, 3835e5b75505Sopenharmony_ci socklen_t fromlen) 3836e5b75505Sopenharmony_ci{ 3837e5b75505Sopenharmony_ci return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen); 3838e5b75505Sopenharmony_ci} 3839e5b75505Sopenharmony_ci 3840e5b75505Sopenharmony_ci 3841e5b75505Sopenharmony_cistatic void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) 3842e5b75505Sopenharmony_ci{ 3843e5b75505Sopenharmony_ci#ifdef CONFIG_WPS_TESTING 3844e5b75505Sopenharmony_ci wps_version_number = 0x20; 3845e5b75505Sopenharmony_ci wps_testing_dummy_cred = 0; 3846e5b75505Sopenharmony_ci wps_corrupt_pkhash = 0; 3847e5b75505Sopenharmony_ci#endif /* CONFIG_WPS_TESTING */ 3848e5b75505Sopenharmony_ci 3849e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 3850e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 3851e5b75505Sopenharmony_ci dpp_test = DPP_TEST_DISABLED; 3852e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 3853e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 3854e5b75505Sopenharmony_ci 3855e5b75505Sopenharmony_ci#ifdef CONFIG_DPP 3856e5b75505Sopenharmony_ci dpp_global_clear(interfaces->dpp); 3857e5b75505Sopenharmony_ci#endif /* CONFIG_DPP */ 3858e5b75505Sopenharmony_ci} 3859e5b75505Sopenharmony_ci 3860e5b75505Sopenharmony_ci 3861e5b75505Sopenharmony_ci#ifdef CONFIG_FST 3862e5b75505Sopenharmony_ci 3863e5b75505Sopenharmony_cistatic int 3864e5b75505Sopenharmony_cihostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces, 3865e5b75505Sopenharmony_ci const char *cmd) 3866e5b75505Sopenharmony_ci{ 3867e5b75505Sopenharmony_ci char ifname[IFNAMSIZ + 1]; 3868e5b75505Sopenharmony_ci struct fst_iface_cfg cfg; 3869e5b75505Sopenharmony_ci struct hostapd_data *hapd; 3870e5b75505Sopenharmony_ci struct fst_wpa_obj iface_obj; 3871e5b75505Sopenharmony_ci 3872e5b75505Sopenharmony_ci if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 3873e5b75505Sopenharmony_ci hapd = hostapd_get_iface(interfaces, ifname); 3874e5b75505Sopenharmony_ci if (hapd) { 3875e5b75505Sopenharmony_ci if (hapd->iface->fst) { 3876e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "FST: Already attached"); 3877e5b75505Sopenharmony_ci return -1; 3878e5b75505Sopenharmony_ci } 3879e5b75505Sopenharmony_ci fst_hostapd_fill_iface_obj(hapd, &iface_obj); 3880e5b75505Sopenharmony_ci hapd->iface->fst = fst_attach(ifname, hapd->own_addr, 3881e5b75505Sopenharmony_ci &iface_obj, &cfg); 3882e5b75505Sopenharmony_ci if (hapd->iface->fst) 3883e5b75505Sopenharmony_ci return 0; 3884e5b75505Sopenharmony_ci } 3885e5b75505Sopenharmony_ci } 3886e5b75505Sopenharmony_ci 3887e5b75505Sopenharmony_ci return -EINVAL; 3888e5b75505Sopenharmony_ci} 3889e5b75505Sopenharmony_ci 3890e5b75505Sopenharmony_ci 3891e5b75505Sopenharmony_cistatic int 3892e5b75505Sopenharmony_cihostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces, 3893e5b75505Sopenharmony_ci const char *cmd) 3894e5b75505Sopenharmony_ci{ 3895e5b75505Sopenharmony_ci char ifname[IFNAMSIZ + 1]; 3896e5b75505Sopenharmony_ci struct hostapd_data * hapd; 3897e5b75505Sopenharmony_ci 3898e5b75505Sopenharmony_ci if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 3899e5b75505Sopenharmony_ci hapd = hostapd_get_iface(interfaces, ifname); 3900e5b75505Sopenharmony_ci if (hapd) { 3901e5b75505Sopenharmony_ci if (!fst_iface_detach(ifname)) { 3902e5b75505Sopenharmony_ci hapd->iface->fst = NULL; 3903e5b75505Sopenharmony_ci hapd->iface->fst_ies = NULL; 3904e5b75505Sopenharmony_ci return 0; 3905e5b75505Sopenharmony_ci } 3906e5b75505Sopenharmony_ci } 3907e5b75505Sopenharmony_ci } 3908e5b75505Sopenharmony_ci 3909e5b75505Sopenharmony_ci return -EINVAL; 3910e5b75505Sopenharmony_ci} 3911e5b75505Sopenharmony_ci 3912e5b75505Sopenharmony_ci#endif /* CONFIG_FST */ 3913e5b75505Sopenharmony_ci 3914e5b75505Sopenharmony_ci 3915e5b75505Sopenharmony_cistatic struct hostapd_data * 3916e5b75505Sopenharmony_cihostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces, 3917e5b75505Sopenharmony_ci const char *ifname) 3918e5b75505Sopenharmony_ci{ 3919e5b75505Sopenharmony_ci size_t i, j; 3920e5b75505Sopenharmony_ci 3921e5b75505Sopenharmony_ci for (i = 0; i < interfaces->count; i++) { 3922e5b75505Sopenharmony_ci struct hostapd_iface *iface = interfaces->iface[i]; 3923e5b75505Sopenharmony_ci 3924e5b75505Sopenharmony_ci for (j = 0; j < iface->num_bss; j++) { 3925e5b75505Sopenharmony_ci struct hostapd_data *hapd; 3926e5b75505Sopenharmony_ci 3927e5b75505Sopenharmony_ci hapd = iface->bss[j]; 3928e5b75505Sopenharmony_ci if (os_strcmp(ifname, hapd->conf->iface) == 0) 3929e5b75505Sopenharmony_ci return hapd; 3930e5b75505Sopenharmony_ci } 3931e5b75505Sopenharmony_ci } 3932e5b75505Sopenharmony_ci 3933e5b75505Sopenharmony_ci return NULL; 3934e5b75505Sopenharmony_ci} 3935e5b75505Sopenharmony_ci 3936e5b75505Sopenharmony_ci 3937e5b75505Sopenharmony_cistatic int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd, 3938e5b75505Sopenharmony_ci struct hostapd_data *dst_hapd, 3939e5b75505Sopenharmony_ci const char *param) 3940e5b75505Sopenharmony_ci{ 3941e5b75505Sopenharmony_ci int res; 3942e5b75505Sopenharmony_ci char *value; 3943e5b75505Sopenharmony_ci 3944e5b75505Sopenharmony_ci value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN); 3945e5b75505Sopenharmony_ci if (!value) { 3946e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 3947e5b75505Sopenharmony_ci "DUP: cannot allocate buffer to stringify %s", 3948e5b75505Sopenharmony_ci param); 3949e5b75505Sopenharmony_ci goto error_return; 3950e5b75505Sopenharmony_ci } 3951e5b75505Sopenharmony_ci 3952e5b75505Sopenharmony_ci if (os_strcmp(param, "wpa") == 0) { 3953e5b75505Sopenharmony_ci os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d", 3954e5b75505Sopenharmony_ci src_hapd->conf->wpa); 3955e5b75505Sopenharmony_ci } else if (os_strcmp(param, "wpa_key_mgmt") == 0 && 3956e5b75505Sopenharmony_ci src_hapd->conf->wpa_key_mgmt) { 3957e5b75505Sopenharmony_ci res = hostapd_ctrl_iface_get_key_mgmt( 3958e5b75505Sopenharmony_ci src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN); 3959e5b75505Sopenharmony_ci if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res)) 3960e5b75505Sopenharmony_ci goto error_stringify; 3961e5b75505Sopenharmony_ci } else if (os_strcmp(param, "wpa_pairwise") == 0 && 3962e5b75505Sopenharmony_ci src_hapd->conf->wpa_pairwise) { 3963e5b75505Sopenharmony_ci res = wpa_write_ciphers(value, 3964e5b75505Sopenharmony_ci value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 3965e5b75505Sopenharmony_ci src_hapd->conf->wpa_pairwise, " "); 3966e5b75505Sopenharmony_ci if (res < 0) 3967e5b75505Sopenharmony_ci goto error_stringify; 3968e5b75505Sopenharmony_ci } else if (os_strcmp(param, "rsn_pairwise") == 0 && 3969e5b75505Sopenharmony_ci src_hapd->conf->rsn_pairwise) { 3970e5b75505Sopenharmony_ci res = wpa_write_ciphers(value, 3971e5b75505Sopenharmony_ci value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 3972e5b75505Sopenharmony_ci src_hapd->conf->rsn_pairwise, " "); 3973e5b75505Sopenharmony_ci if (res < 0) 3974e5b75505Sopenharmony_ci goto error_stringify; 3975e5b75505Sopenharmony_ci } else if (os_strcmp(param, "wpa_passphrase") == 0 && 3976e5b75505Sopenharmony_ci src_hapd->conf->ssid.wpa_passphrase) { 3977e5b75505Sopenharmony_ci os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s", 3978e5b75505Sopenharmony_ci src_hapd->conf->ssid.wpa_passphrase); 3979e5b75505Sopenharmony_ci } else if (os_strcmp(param, "wpa_psk") == 0 && 3980e5b75505Sopenharmony_ci src_hapd->conf->ssid.wpa_psk_set) { 3981e5b75505Sopenharmony_ci wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 3982e5b75505Sopenharmony_ci src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 3983e5b75505Sopenharmony_ci } else { 3984e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param); 3985e5b75505Sopenharmony_ci goto error_return; 3986e5b75505Sopenharmony_ci } 3987e5b75505Sopenharmony_ci 3988e5b75505Sopenharmony_ci res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value); 3989e5b75505Sopenharmony_ci os_free(value); 3990e5b75505Sopenharmony_ci return res; 3991e5b75505Sopenharmony_ci 3992e5b75505Sopenharmony_cierror_stringify: 3993e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param); 3994e5b75505Sopenharmony_cierror_return: 3995e5b75505Sopenharmony_ci os_free(value); 3996e5b75505Sopenharmony_ci return -1; 3997e5b75505Sopenharmony_ci} 3998e5b75505Sopenharmony_ci 3999e5b75505Sopenharmony_ci 4000e5b75505Sopenharmony_cistatic int 4001e5b75505Sopenharmony_cihostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces, 4002e5b75505Sopenharmony_ci const char *input, 4003e5b75505Sopenharmony_ci char *reply, int reply_size) 4004e5b75505Sopenharmony_ci{ 4005e5b75505Sopenharmony_ci size_t i, j; 4006e5b75505Sopenharmony_ci int res; 4007e5b75505Sopenharmony_ci char *pos, *end; 4008e5b75505Sopenharmony_ci struct hostapd_iface *iface; 4009e5b75505Sopenharmony_ci int show_ctrl = 0; 4010e5b75505Sopenharmony_ci 4011e5b75505Sopenharmony_ci if (input) 4012e5b75505Sopenharmony_ci show_ctrl = !!os_strstr(input, "ctrl"); 4013e5b75505Sopenharmony_ci 4014e5b75505Sopenharmony_ci pos = reply; 4015e5b75505Sopenharmony_ci end = reply + reply_size; 4016e5b75505Sopenharmony_ci 4017e5b75505Sopenharmony_ci for (i = 0; i < interfaces->count; i++) { 4018e5b75505Sopenharmony_ci iface = interfaces->iface[i]; 4019e5b75505Sopenharmony_ci 4020e5b75505Sopenharmony_ci for (j = 0; j < iface->num_bss; j++) { 4021e5b75505Sopenharmony_ci struct hostapd_bss_config *conf; 4022e5b75505Sopenharmony_ci 4023e5b75505Sopenharmony_ci conf = iface->conf->bss[j]; 4024e5b75505Sopenharmony_ci if (show_ctrl) 4025e5b75505Sopenharmony_ci res = os_snprintf(pos, end - pos, 4026e5b75505Sopenharmony_ci "%s ctrl_iface=%s\n", 4027e5b75505Sopenharmony_ci conf->iface, 4028e5b75505Sopenharmony_ci conf->ctrl_interface ? 4029e5b75505Sopenharmony_ci conf->ctrl_interface : "N/A"); 4030e5b75505Sopenharmony_ci else 4031e5b75505Sopenharmony_ci res = os_snprintf(pos, end - pos, "%s\n", 4032e5b75505Sopenharmony_ci conf->iface); 4033e5b75505Sopenharmony_ci if (os_snprintf_error(end - pos, res)) { 4034e5b75505Sopenharmony_ci *pos = '\0'; 4035e5b75505Sopenharmony_ci return pos - reply; 4036e5b75505Sopenharmony_ci } 4037e5b75505Sopenharmony_ci pos += res; 4038e5b75505Sopenharmony_ci } 4039e5b75505Sopenharmony_ci } 4040e5b75505Sopenharmony_ci 4041e5b75505Sopenharmony_ci return pos - reply; 4042e5b75505Sopenharmony_ci} 4043e5b75505Sopenharmony_ci 4044e5b75505Sopenharmony_ci 4045e5b75505Sopenharmony_cistatic int 4046e5b75505Sopenharmony_cihostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces, 4047e5b75505Sopenharmony_ci char *cmd) 4048e5b75505Sopenharmony_ci{ 4049e5b75505Sopenharmony_ci char *p_start = cmd, *p_end; 4050e5b75505Sopenharmony_ci struct hostapd_data *src_hapd, *dst_hapd; 4051e5b75505Sopenharmony_ci 4052e5b75505Sopenharmony_ci /* cmd: "<src ifname> <dst ifname> <variable name> */ 4053e5b75505Sopenharmony_ci 4054e5b75505Sopenharmony_ci p_end = os_strchr(p_start, ' '); 4055e5b75505Sopenharmony_ci if (!p_end) { 4056e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'", 4057e5b75505Sopenharmony_ci cmd); 4058e5b75505Sopenharmony_ci return -1; 4059e5b75505Sopenharmony_ci } 4060e5b75505Sopenharmony_ci 4061e5b75505Sopenharmony_ci *p_end = '\0'; 4062e5b75505Sopenharmony_ci src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start); 4063e5b75505Sopenharmony_ci if (!src_hapd) { 4064e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'", 4065e5b75505Sopenharmony_ci p_start); 4066e5b75505Sopenharmony_ci return -1; 4067e5b75505Sopenharmony_ci } 4068e5b75505Sopenharmony_ci 4069e5b75505Sopenharmony_ci p_start = p_end + 1; 4070e5b75505Sopenharmony_ci p_end = os_strchr(p_start, ' '); 4071e5b75505Sopenharmony_ci if (!p_end) { 4072e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'", 4073e5b75505Sopenharmony_ci cmd); 4074e5b75505Sopenharmony_ci return -1; 4075e5b75505Sopenharmony_ci } 4076e5b75505Sopenharmony_ci 4077e5b75505Sopenharmony_ci *p_end = '\0'; 4078e5b75505Sopenharmony_ci dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start); 4079e5b75505Sopenharmony_ci if (!dst_hapd) { 4080e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'", 4081e5b75505Sopenharmony_ci p_start); 4082e5b75505Sopenharmony_ci return -1; 4083e5b75505Sopenharmony_ci } 4084e5b75505Sopenharmony_ci 4085e5b75505Sopenharmony_ci p_start = p_end + 1; 4086e5b75505Sopenharmony_ci return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start); 4087e5b75505Sopenharmony_ci} 4088e5b75505Sopenharmony_ci 4089e5b75505Sopenharmony_ci 4090e5b75505Sopenharmony_cistatic int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces, 4091e5b75505Sopenharmony_ci const char *ifname, 4092e5b75505Sopenharmony_ci char *buf, char *reply, 4093e5b75505Sopenharmony_ci int reply_size, 4094e5b75505Sopenharmony_ci struct sockaddr_storage *from, 4095e5b75505Sopenharmony_ci socklen_t fromlen) 4096e5b75505Sopenharmony_ci{ 4097e5b75505Sopenharmony_ci struct hostapd_data *hapd; 4098e5b75505Sopenharmony_ci 4099e5b75505Sopenharmony_ci hapd = hostapd_interfaces_get_hapd(interfaces, ifname); 4100e5b75505Sopenharmony_ci if (hapd == NULL) { 4101e5b75505Sopenharmony_ci int res; 4102e5b75505Sopenharmony_ci 4103e5b75505Sopenharmony_ci res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n"); 4104e5b75505Sopenharmony_ci if (os_snprintf_error(reply_size, res)) 4105e5b75505Sopenharmony_ci return -1; 4106e5b75505Sopenharmony_ci return res; 4107e5b75505Sopenharmony_ci } 4108e5b75505Sopenharmony_ci 4109e5b75505Sopenharmony_ci return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size, 4110e5b75505Sopenharmony_ci from, fromlen); 4111e5b75505Sopenharmony_ci} 4112e5b75505Sopenharmony_ci 4113e5b75505Sopenharmony_ci 4114e5b75505Sopenharmony_cistatic void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 4115e5b75505Sopenharmony_ci void *sock_ctx) 4116e5b75505Sopenharmony_ci{ 4117e5b75505Sopenharmony_ci void *interfaces = eloop_ctx; 4118e5b75505Sopenharmony_ci char buffer[256], *buf = buffer; 4119e5b75505Sopenharmony_ci int res; 4120e5b75505Sopenharmony_ci struct sockaddr_storage from; 4121e5b75505Sopenharmony_ci socklen_t fromlen = sizeof(from); 4122e5b75505Sopenharmony_ci char *reply; 4123e5b75505Sopenharmony_ci int reply_len; 4124e5b75505Sopenharmony_ci const int reply_size = 4096; 4125e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 4126e5b75505Sopenharmony_ci unsigned char lcookie[COOKIE_LEN]; 4127e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 4128e5b75505Sopenharmony_ci 4129e5b75505Sopenharmony_ci res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, 4130e5b75505Sopenharmony_ci (struct sockaddr *) &from, &fromlen); 4131e5b75505Sopenharmony_ci if (res < 0) { 4132e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 4133e5b75505Sopenharmony_ci strerror(errno)); 4134e5b75505Sopenharmony_ci return; 4135e5b75505Sopenharmony_ci } 4136e5b75505Sopenharmony_ci buf[res] = '\0'; 4137e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf); 4138e5b75505Sopenharmony_ci 4139e5b75505Sopenharmony_ci reply = os_malloc(reply_size); 4140e5b75505Sopenharmony_ci if (reply == NULL) { 4141e5b75505Sopenharmony_ci if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 4142e5b75505Sopenharmony_ci fromlen) < 0) { 4143e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 4144e5b75505Sopenharmony_ci strerror(errno)); 4145e5b75505Sopenharmony_ci } 4146e5b75505Sopenharmony_ci return; 4147e5b75505Sopenharmony_ci } 4148e5b75505Sopenharmony_ci 4149e5b75505Sopenharmony_ci os_memcpy(reply, "OK\n", 3); 4150e5b75505Sopenharmony_ci reply_len = 3; 4151e5b75505Sopenharmony_ci 4152e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 4153e5b75505Sopenharmony_ci if (os_strcmp(buf, "GET_COOKIE") == 0) { 4154e5b75505Sopenharmony_ci os_memcpy(reply, "COOKIE=", 7); 4155e5b75505Sopenharmony_ci wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 4156e5b75505Sopenharmony_ci gcookie, COOKIE_LEN); 4157e5b75505Sopenharmony_ci reply_len = 7 + 2 * COOKIE_LEN; 4158e5b75505Sopenharmony_ci goto send_reply; 4159e5b75505Sopenharmony_ci } 4160e5b75505Sopenharmony_ci 4161e5b75505Sopenharmony_ci if (os_strncmp(buf, "COOKIE=", 7) != 0 || 4162e5b75505Sopenharmony_ci hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { 4163e5b75505Sopenharmony_ci#ifdef CONFIG_OPEN_HARMONY_PATCH 4164e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 4165e5b75505Sopenharmony_ci "CTRL: No cookie in the request - reply failed!"); 4166e5b75505Sopenharmony_ci reply_len = -1; 4167e5b75505Sopenharmony_ci goto send_reply; 4168e5b75505Sopenharmony_ci#else 4169e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 4170e5b75505Sopenharmony_ci "CTRL: No cookie in the request - drop request"); 4171e5b75505Sopenharmony_ci os_free(reply); 4172e5b75505Sopenharmony_ci#endif 4173e5b75505Sopenharmony_ci return; 4174e5b75505Sopenharmony_ci } 4175e5b75505Sopenharmony_ci 4176e5b75505Sopenharmony_ci if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) { 4177e5b75505Sopenharmony_ci#ifdef CONFIG_OPEN_HARMONY_PATCH 4178e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, 4179e5b75505Sopenharmony_ci "CTRL: Invalid cookie in the request - reply failed!"); 4180e5b75505Sopenharmony_ci reply_len = -1; 4181e5b75505Sopenharmony_ci goto send_reply; 4182e5b75505Sopenharmony_ci#else 4183e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 4184e5b75505Sopenharmony_ci "CTRL: Invalid cookie in the request - drop request"); 4185e5b75505Sopenharmony_ci os_free(reply); 4186e5b75505Sopenharmony_ci return; 4187e5b75505Sopenharmony_ci#endif 4188e5b75505Sopenharmony_ci } 4189e5b75505Sopenharmony_ci 4190e5b75505Sopenharmony_ci buf += 7 + 2 * COOKIE_LEN; 4191e5b75505Sopenharmony_ci while (*buf == ' ') 4192e5b75505Sopenharmony_ci buf++; 4193e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 4194e5b75505Sopenharmony_ci 4195e5b75505Sopenharmony_ci if (os_strncmp(buf, "IFNAME=", 7) == 0) { 4196e5b75505Sopenharmony_ci char *pos = os_strchr(buf + 7, ' '); 4197e5b75505Sopenharmony_ci 4198e5b75505Sopenharmony_ci if (pos) { 4199e5b75505Sopenharmony_ci *pos++ = '\0'; 4200e5b75505Sopenharmony_ci reply_len = hostapd_global_ctrl_iface_ifname( 4201e5b75505Sopenharmony_ci interfaces, buf + 7, pos, reply, reply_size, 4202e5b75505Sopenharmony_ci &from, fromlen); 4203e5b75505Sopenharmony_ci goto send_reply; 4204e5b75505Sopenharmony_ci } 4205e5b75505Sopenharmony_ci } 4206e5b75505Sopenharmony_ci 4207e5b75505Sopenharmony_ci if (os_strcmp(buf, "PING") == 0) { 4208e5b75505Sopenharmony_ci os_memcpy(reply, "PONG\n", 5); 4209e5b75505Sopenharmony_ci reply_len = 5; 4210e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "RELOG", 5) == 0) { 4211e5b75505Sopenharmony_ci if (wpa_debug_reopen_file() < 0) 4212e5b75505Sopenharmony_ci reply_len = -1; 4213e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "FLUSH") == 0) { 4214e5b75505Sopenharmony_ci hostapd_ctrl_iface_flush(interfaces); 4215e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "ADD ", 4) == 0) { 4216e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 4217e5b75505Sopenharmony_ci reply_len = -1; 4218e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 4219e5b75505Sopenharmony_ci if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 4220e5b75505Sopenharmony_ci reply_len = -1; 4221e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "ATTACH") == 0) { 4222e5b75505Sopenharmony_ci if (hostapd_global_ctrl_iface_attach(interfaces, &from, 4223e5b75505Sopenharmony_ci fromlen, NULL)) 4224e5b75505Sopenharmony_ci reply_len = -1; 4225e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "ATTACH ", 7) == 0) { 4226e5b75505Sopenharmony_ci if (hostapd_global_ctrl_iface_attach(interfaces, &from, 4227e5b75505Sopenharmony_ci fromlen, buf + 7)) 4228e5b75505Sopenharmony_ci reply_len = -1; 4229e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "DETACH") == 0) { 4230e5b75505Sopenharmony_ci if (hostapd_global_ctrl_iface_detach(interfaces, &from, 4231e5b75505Sopenharmony_ci fromlen)) 4232e5b75505Sopenharmony_ci reply_len = -1; 4233e5b75505Sopenharmony_ci#ifdef CONFIG_MODULE_TESTS 4234e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 4235e5b75505Sopenharmony_ci if (hapd_module_tests() < 0) 4236e5b75505Sopenharmony_ci reply_len = -1; 4237e5b75505Sopenharmony_ci#endif /* CONFIG_MODULE_TESTS */ 4238e5b75505Sopenharmony_ci#ifdef CONFIG_FST 4239e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 4240e5b75505Sopenharmony_ci if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11)) 4241e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "OK\n"); 4242e5b75505Sopenharmony_ci else 4243e5b75505Sopenharmony_ci reply_len = -1; 4244e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 4245e5b75505Sopenharmony_ci if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11)) 4246e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "OK\n"); 4247e5b75505Sopenharmony_ci else 4248e5b75505Sopenharmony_ci reply_len = -1; 4249e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 4250e5b75505Sopenharmony_ci reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 4251e5b75505Sopenharmony_ci#endif /* CONFIG_FST */ 4252e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 4253e5b75505Sopenharmony_ci if (!hostapd_global_ctrl_iface_dup_network(interfaces, 4254e5b75505Sopenharmony_ci buf + 12)) 4255e5b75505Sopenharmony_ci reply_len = os_snprintf(reply, reply_size, "OK\n"); 4256e5b75505Sopenharmony_ci else 4257e5b75505Sopenharmony_ci reply_len = -1; 4258e5b75505Sopenharmony_ci } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 4259e5b75505Sopenharmony_ci reply_len = hostapd_global_ctrl_iface_interfaces( 4260e5b75505Sopenharmony_ci interfaces, buf + 10, reply, sizeof(buffer)); 4261e5b75505Sopenharmony_ci } else if (os_strcmp(buf, "TERMINATE") == 0) { 4262e5b75505Sopenharmony_ci eloop_terminate(); 4263e5b75505Sopenharmony_ci } else { 4264e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 4265e5b75505Sopenharmony_ci "ignored"); 4266e5b75505Sopenharmony_ci reply_len = -1; 4267e5b75505Sopenharmony_ci } 4268e5b75505Sopenharmony_ci 4269e5b75505Sopenharmony_cisend_reply: 4270e5b75505Sopenharmony_ci if (reply_len < 0) { 4271e5b75505Sopenharmony_ci os_memcpy(reply, "FAIL\n", 5); 4272e5b75505Sopenharmony_ci reply_len = 5; 4273e5b75505Sopenharmony_ci } 4274e5b75505Sopenharmony_ci 4275e5b75505Sopenharmony_ci if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 4276e5b75505Sopenharmony_ci fromlen) < 0) { 4277e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 4278e5b75505Sopenharmony_ci strerror(errno)); 4279e5b75505Sopenharmony_ci } 4280e5b75505Sopenharmony_ci os_free(reply); 4281e5b75505Sopenharmony_ci} 4282e5b75505Sopenharmony_ci 4283e5b75505Sopenharmony_ci 4284e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 4285e5b75505Sopenharmony_cistatic char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 4286e5b75505Sopenharmony_ci{ 4287e5b75505Sopenharmony_ci char *buf; 4288e5b75505Sopenharmony_ci size_t len; 4289e5b75505Sopenharmony_ci 4290e5b75505Sopenharmony_ci if (interface->global_iface_path == NULL) 4291e5b75505Sopenharmony_ci return NULL; 4292e5b75505Sopenharmony_ci 4293e5b75505Sopenharmony_ci len = os_strlen(interface->global_iface_path) + 4294e5b75505Sopenharmony_ci os_strlen(interface->global_iface_name) + 2; 4295e5b75505Sopenharmony_ci buf = os_malloc(len); 4296e5b75505Sopenharmony_ci if (buf == NULL) 4297e5b75505Sopenharmony_ci return NULL; 4298e5b75505Sopenharmony_ci 4299e5b75505Sopenharmony_ci os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 4300e5b75505Sopenharmony_ci interface->global_iface_name); 4301e5b75505Sopenharmony_ci buf[len - 1] = '\0'; 4302e5b75505Sopenharmony_ci return buf; 4303e5b75505Sopenharmony_ci} 4304e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 4305e5b75505Sopenharmony_ci 4306e5b75505Sopenharmony_ci 4307e5b75505Sopenharmony_ciint hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 4308e5b75505Sopenharmony_ci{ 4309e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP 4310e5b75505Sopenharmony_ci int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT; 4311e5b75505Sopenharmony_ci char p[32] = { 0 }; 4312e5b75505Sopenharmony_ci char *pos; 4313e5b75505Sopenharmony_ci struct addrinfo hints = { 0 }, *res, *saveres; 4314e5b75505Sopenharmony_ci int n; 4315e5b75505Sopenharmony_ci 4316e5b75505Sopenharmony_ci if (interface->global_ctrl_sock > -1) { 4317e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 4318e5b75505Sopenharmony_ci return 0; 4319e5b75505Sopenharmony_ci } 4320e5b75505Sopenharmony_ci 4321e5b75505Sopenharmony_ci if (interface->global_iface_path == NULL) 4322e5b75505Sopenharmony_ci return 0; 4323e5b75505Sopenharmony_ci 4324e5b75505Sopenharmony_ci pos = os_strstr(interface->global_iface_path, "udp:"); 4325e5b75505Sopenharmony_ci if (pos) { 4326e5b75505Sopenharmony_ci pos += 4; 4327e5b75505Sopenharmony_ci port = atoi(pos); 4328e5b75505Sopenharmony_ci if (port <= 0) { 4329e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port"); 4330e5b75505Sopenharmony_ci goto fail; 4331e5b75505Sopenharmony_ci } 4332e5b75505Sopenharmony_ci } 4333e5b75505Sopenharmony_ci 4334e5b75505Sopenharmony_ci os_get_random(gcookie, COOKIE_LEN); 4335e5b75505Sopenharmony_ci 4336e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 4337e5b75505Sopenharmony_ci hints.ai_flags = AI_PASSIVE; 4338e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 4339e5b75505Sopenharmony_ci 4340e5b75505Sopenharmony_ci#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 4341e5b75505Sopenharmony_ci hints.ai_family = AF_INET6; 4342e5b75505Sopenharmony_ci#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 4343e5b75505Sopenharmony_ci hints.ai_family = AF_INET; 4344e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 4345e5b75505Sopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 4346e5b75505Sopenharmony_ci 4347e5b75505Sopenharmony_citry_again: 4348e5b75505Sopenharmony_ci os_snprintf(p, sizeof(p), "%d", port); 4349e5b75505Sopenharmony_ci n = getaddrinfo(NULL, p, &hints, &res); 4350e5b75505Sopenharmony_ci if (n) { 4351e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n)); 4352e5b75505Sopenharmony_ci goto fail; 4353e5b75505Sopenharmony_ci } 4354e5b75505Sopenharmony_ci 4355e5b75505Sopenharmony_ci saveres = res; 4356e5b75505Sopenharmony_ci interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype, 4357e5b75505Sopenharmony_ci res->ai_protocol); 4358e5b75505Sopenharmony_ci if (interface->global_ctrl_sock < 0) { 4359e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 4360e5b75505Sopenharmony_ci goto fail; 4361e5b75505Sopenharmony_ci } 4362e5b75505Sopenharmony_ci 4363e5b75505Sopenharmony_ci if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) < 4364e5b75505Sopenharmony_ci 0) { 4365e5b75505Sopenharmony_ci port++; 4366e5b75505Sopenharmony_ci if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) < 4367e5b75505Sopenharmony_ci HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos) 4368e5b75505Sopenharmony_ci goto try_again; 4369e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 4370e5b75505Sopenharmony_ci goto fail; 4371e5b75505Sopenharmony_ci } 4372e5b75505Sopenharmony_ci 4373e5b75505Sopenharmony_ci freeaddrinfo(saveres); 4374e5b75505Sopenharmony_ci 4375e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port); 4376e5b75505Sopenharmony_ci 4377e5b75505Sopenharmony_ci if (eloop_register_read_sock(interface->global_ctrl_sock, 4378e5b75505Sopenharmony_ci hostapd_global_ctrl_iface_receive, 4379e5b75505Sopenharmony_ci interface, NULL) < 0) { 4380e5b75505Sopenharmony_ci hostapd_global_ctrl_iface_deinit(interface); 4381e5b75505Sopenharmony_ci return -1; 4382e5b75505Sopenharmony_ci } 4383e5b75505Sopenharmony_ci 4384e5b75505Sopenharmony_ci return 0; 4385e5b75505Sopenharmony_ci 4386e5b75505Sopenharmony_cifail: 4387e5b75505Sopenharmony_ci if (interface->global_ctrl_sock >= 0) 4388e5b75505Sopenharmony_ci close(interface->global_ctrl_sock); 4389e5b75505Sopenharmony_ci return -1; 4390e5b75505Sopenharmony_ci#else /* CONFIG_CTRL_IFACE_UDP */ 4391e5b75505Sopenharmony_ci struct sockaddr_un addr; 4392e5b75505Sopenharmony_ci int s = -1; 4393e5b75505Sopenharmony_ci char *fname = NULL; 4394e5b75505Sopenharmony_ci 4395e5b75505Sopenharmony_ci if (interface->global_iface_path == NULL) { 4396e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 4397e5b75505Sopenharmony_ci return 0; 4398e5b75505Sopenharmony_ci } 4399e5b75505Sopenharmony_ci 4400e5b75505Sopenharmony_ci if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 4401e5b75505Sopenharmony_ci if (errno == EEXIST) { 4402e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Using existing control " 4403e5b75505Sopenharmony_ci "interface directory."); 4404e5b75505Sopenharmony_ci } else { 4405e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 4406e5b75505Sopenharmony_ci strerror(errno)); 4407e5b75505Sopenharmony_ci goto fail; 4408e5b75505Sopenharmony_ci } 4409e5b75505Sopenharmony_ci } else if (interface->ctrl_iface_group && 4410e5b75505Sopenharmony_ci lchown(interface->global_iface_path, -1, 4411e5b75505Sopenharmony_ci interface->ctrl_iface_group) < 0) { 4412e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 4413e5b75505Sopenharmony_ci strerror(errno)); 4414e5b75505Sopenharmony_ci goto fail; 4415e5b75505Sopenharmony_ci } 4416e5b75505Sopenharmony_ci 4417e5b75505Sopenharmony_ci if (os_strlen(interface->global_iface_path) + 1 + 4418e5b75505Sopenharmony_ci os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 4419e5b75505Sopenharmony_ci goto fail; 4420e5b75505Sopenharmony_ci 4421e5b75505Sopenharmony_ci s = socket(PF_UNIX, SOCK_DGRAM, 0); 4422e5b75505Sopenharmony_ci if (s < 0) { 4423e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 4424e5b75505Sopenharmony_ci goto fail; 4425e5b75505Sopenharmony_ci } 4426e5b75505Sopenharmony_ci 4427e5b75505Sopenharmony_ci os_memset(&addr, 0, sizeof(addr)); 4428e5b75505Sopenharmony_ci#ifdef __FreeBSD__ 4429e5b75505Sopenharmony_ci addr.sun_len = sizeof(addr); 4430e5b75505Sopenharmony_ci#endif /* __FreeBSD__ */ 4431e5b75505Sopenharmony_ci addr.sun_family = AF_UNIX; 4432e5b75505Sopenharmony_ci fname = hostapd_global_ctrl_iface_path(interface); 4433e5b75505Sopenharmony_ci if (fname == NULL) 4434e5b75505Sopenharmony_ci goto fail; 4435e5b75505Sopenharmony_ci os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 4436e5b75505Sopenharmony_ci if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 4437e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 4438e5b75505Sopenharmony_ci strerror(errno)); 4439e5b75505Sopenharmony_ci if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 4440e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 4441e5b75505Sopenharmony_ci " allow connections - assuming it was left" 4442e5b75505Sopenharmony_ci "over from forced program termination"); 4443e5b75505Sopenharmony_ci if (unlink(fname) < 0) { 4444e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 4445e5b75505Sopenharmony_ci "Could not unlink existing ctrl_iface socket '%s': %s", 4446e5b75505Sopenharmony_ci fname, strerror(errno)); 4447e5b75505Sopenharmony_ci goto fail; 4448e5b75505Sopenharmony_ci } 4449e5b75505Sopenharmony_ci if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 4450e5b75505Sopenharmony_ci 0) { 4451e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s", 4452e5b75505Sopenharmony_ci strerror(errno)); 4453e5b75505Sopenharmony_ci goto fail; 4454e5b75505Sopenharmony_ci } 4455e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 4456e5b75505Sopenharmony_ci "ctrl_iface socket '%s'", fname); 4457e5b75505Sopenharmony_ci } else { 4458e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 4459e5b75505Sopenharmony_ci "be in use - cannot override it"); 4460e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 4461e5b75505Sopenharmony_ci "not used anymore", fname); 4462e5b75505Sopenharmony_ci os_free(fname); 4463e5b75505Sopenharmony_ci fname = NULL; 4464e5b75505Sopenharmony_ci goto fail; 4465e5b75505Sopenharmony_ci } 4466e5b75505Sopenharmony_ci } 4467e5b75505Sopenharmony_ci 4468e5b75505Sopenharmony_ci if (interface->ctrl_iface_group && 4469e5b75505Sopenharmony_ci lchown(fname, -1, interface->ctrl_iface_group) < 0) { 4470e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 4471e5b75505Sopenharmony_ci strerror(errno)); 4472e5b75505Sopenharmony_ci goto fail; 4473e5b75505Sopenharmony_ci } 4474e5b75505Sopenharmony_ci 4475e5b75505Sopenharmony_ci if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 4476e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 4477e5b75505Sopenharmony_ci strerror(errno)); 4478e5b75505Sopenharmony_ci goto fail; 4479e5b75505Sopenharmony_ci } 4480e5b75505Sopenharmony_ci os_free(fname); 4481e5b75505Sopenharmony_ci 4482e5b75505Sopenharmony_ci interface->global_ctrl_sock = s; 4483e5b75505Sopenharmony_ci eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 4484e5b75505Sopenharmony_ci interface, NULL); 4485e5b75505Sopenharmony_ci 4486e5b75505Sopenharmony_ci return 0; 4487e5b75505Sopenharmony_ci 4488e5b75505Sopenharmony_cifail: 4489e5b75505Sopenharmony_ci if (s >= 0) 4490e5b75505Sopenharmony_ci close(s); 4491e5b75505Sopenharmony_ci if (fname) { 4492e5b75505Sopenharmony_ci unlink(fname); 4493e5b75505Sopenharmony_ci os_free(fname); 4494e5b75505Sopenharmony_ci } 4495e5b75505Sopenharmony_ci return -1; 4496e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 4497e5b75505Sopenharmony_ci} 4498e5b75505Sopenharmony_ci 4499e5b75505Sopenharmony_ci 4500e5b75505Sopenharmony_civoid hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 4501e5b75505Sopenharmony_ci{ 4502e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 4503e5b75505Sopenharmony_ci char *fname = NULL; 4504e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 4505e5b75505Sopenharmony_ci struct wpa_ctrl_dst *dst, *prev; 4506e5b75505Sopenharmony_ci 4507e5b75505Sopenharmony_ci if (interfaces->global_ctrl_sock > -1) { 4508e5b75505Sopenharmony_ci eloop_unregister_read_sock(interfaces->global_ctrl_sock); 4509e5b75505Sopenharmony_ci close(interfaces->global_ctrl_sock); 4510e5b75505Sopenharmony_ci interfaces->global_ctrl_sock = -1; 4511e5b75505Sopenharmony_ci#ifndef CONFIG_CTRL_IFACE_UDP 4512e5b75505Sopenharmony_ci fname = hostapd_global_ctrl_iface_path(interfaces); 4513e5b75505Sopenharmony_ci if (fname) { 4514e5b75505Sopenharmony_ci unlink(fname); 4515e5b75505Sopenharmony_ci os_free(fname); 4516e5b75505Sopenharmony_ci } 4517e5b75505Sopenharmony_ci 4518e5b75505Sopenharmony_ci if (interfaces->global_iface_path && 4519e5b75505Sopenharmony_ci rmdir(interfaces->global_iface_path) < 0) { 4520e5b75505Sopenharmony_ci if (errno == ENOTEMPTY) { 4521e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Control interface " 4522e5b75505Sopenharmony_ci "directory not empty - leaving it " 4523e5b75505Sopenharmony_ci "behind"); 4524e5b75505Sopenharmony_ci } else { 4525e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, 4526e5b75505Sopenharmony_ci "rmdir[ctrl_interface=%s]: %s", 4527e5b75505Sopenharmony_ci interfaces->global_iface_path, 4528e5b75505Sopenharmony_ci strerror(errno)); 4529e5b75505Sopenharmony_ci } 4530e5b75505Sopenharmony_ci } 4531e5b75505Sopenharmony_ci#endif /* CONFIG_CTRL_IFACE_UDP */ 4532e5b75505Sopenharmony_ci } 4533e5b75505Sopenharmony_ci 4534e5b75505Sopenharmony_ci os_free(interfaces->global_iface_path); 4535e5b75505Sopenharmony_ci interfaces->global_iface_path = NULL; 4536e5b75505Sopenharmony_ci 4537e5b75505Sopenharmony_ci dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst, 4538e5b75505Sopenharmony_ci struct wpa_ctrl_dst, list) 4539e5b75505Sopenharmony_ci os_free(dst); 4540e5b75505Sopenharmony_ci} 4541e5b75505Sopenharmony_ci 4542e5b75505Sopenharmony_ci 4543e5b75505Sopenharmony_cistatic int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst, 4544e5b75505Sopenharmony_ci const char *buf) 4545e5b75505Sopenharmony_ci{ 4546e5b75505Sopenharmony_ci /* Enable Probe Request events based on explicit request. 4547e5b75505Sopenharmony_ci * Other events are enabled by default. 4548e5b75505Sopenharmony_ci */ 4549e5b75505Sopenharmony_ci if (str_starts(buf, RX_PROBE_REQUEST)) 4550e5b75505Sopenharmony_ci return !!(dst->events & WPA_EVENT_RX_PROBE_REQUEST); 4551e5b75505Sopenharmony_ci return 1; 4552e5b75505Sopenharmony_ci} 4553e5b75505Sopenharmony_ci 4554e5b75505Sopenharmony_ci 4555e5b75505Sopenharmony_cistatic void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 4556e5b75505Sopenharmony_ci enum wpa_msg_type type, 4557e5b75505Sopenharmony_ci const char *buf, size_t len) 4558e5b75505Sopenharmony_ci{ 4559e5b75505Sopenharmony_ci struct wpa_ctrl_dst *dst, *next; 4560e5b75505Sopenharmony_ci struct dl_list *ctrl_dst; 4561e5b75505Sopenharmony_ci struct msghdr msg; 4562e5b75505Sopenharmony_ci int idx; 4563e5b75505Sopenharmony_ci struct iovec io[2]; 4564e5b75505Sopenharmony_ci char levelstr[10]; 4565e5b75505Sopenharmony_ci int s; 4566e5b75505Sopenharmony_ci 4567e5b75505Sopenharmony_ci if (type != WPA_MSG_ONLY_GLOBAL) { 4568e5b75505Sopenharmony_ci s = hapd->ctrl_sock; 4569e5b75505Sopenharmony_ci ctrl_dst = &hapd->ctrl_dst; 4570e5b75505Sopenharmony_ci } else { 4571e5b75505Sopenharmony_ci s = hapd->iface->interfaces->global_ctrl_sock; 4572e5b75505Sopenharmony_ci ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst; 4573e5b75505Sopenharmony_ci } 4574e5b75505Sopenharmony_ci 4575e5b75505Sopenharmony_ci if (s < 0 || dl_list_empty(ctrl_dst)) 4576e5b75505Sopenharmony_ci return; 4577e5b75505Sopenharmony_ci 4578e5b75505Sopenharmony_ci os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 4579e5b75505Sopenharmony_ci io[0].iov_base = levelstr; 4580e5b75505Sopenharmony_ci io[0].iov_len = os_strlen(levelstr); 4581e5b75505Sopenharmony_ci io[1].iov_base = (char *) buf; 4582e5b75505Sopenharmony_ci io[1].iov_len = len; 4583e5b75505Sopenharmony_ci os_memset(&msg, 0, sizeof(msg)); 4584e5b75505Sopenharmony_ci msg.msg_iov = io; 4585e5b75505Sopenharmony_ci msg.msg_iovlen = 2; 4586e5b75505Sopenharmony_ci 4587e5b75505Sopenharmony_ci idx = 0; 4588e5b75505Sopenharmony_ci dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) { 4589e5b75505Sopenharmony_ci if ((level >= dst->debug_level) && 4590e5b75505Sopenharmony_ci hostapd_ctrl_check_event_enabled(dst, buf)) { 4591e5b75505Sopenharmony_ci sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send", 4592e5b75505Sopenharmony_ci &dst->addr, dst->addrlen); 4593e5b75505Sopenharmony_ci msg.msg_name = &dst->addr; 4594e5b75505Sopenharmony_ci msg.msg_namelen = dst->addrlen; 4595e5b75505Sopenharmony_ci if (sendmsg(s, &msg, 0) < 0) { 4596e5b75505Sopenharmony_ci int _errno = errno; 4597e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 4598e5b75505Sopenharmony_ci "%d - %s", 4599e5b75505Sopenharmony_ci idx, errno, strerror(errno)); 4600e5b75505Sopenharmony_ci dst->errors++; 4601e5b75505Sopenharmony_ci if (dst->errors > 10 || _errno == ENOENT) { 4602e5b75505Sopenharmony_ci if (type != WPA_MSG_ONLY_GLOBAL) 4603e5b75505Sopenharmony_ci hostapd_ctrl_iface_detach( 4604e5b75505Sopenharmony_ci hapd, &dst->addr, 4605e5b75505Sopenharmony_ci dst->addrlen); 4606e5b75505Sopenharmony_ci else 4607e5b75505Sopenharmony_ci hostapd_global_ctrl_iface_detach( 4608e5b75505Sopenharmony_ci hapd->iface->interfaces, 4609e5b75505Sopenharmony_ci &dst->addr, 4610e5b75505Sopenharmony_ci dst->addrlen); 4611e5b75505Sopenharmony_ci } 4612e5b75505Sopenharmony_ci } else 4613e5b75505Sopenharmony_ci dst->errors = 0; 4614e5b75505Sopenharmony_ci } 4615e5b75505Sopenharmony_ci idx++; 4616e5b75505Sopenharmony_ci } 4617e5b75505Sopenharmony_ci} 4618e5b75505Sopenharmony_ci 4619e5b75505Sopenharmony_ci#endif /* CONFIG_NATIVE_WINDOWS */ 4620