/*
 * Common driver-related functions
 * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"
#include "utils/common.h"
#include "driver.h"

void wpa_scan_results_free(struct wpa_scan_results *res)
{
	size_t i;

	if (res == NULL)
		return;

	for (i = 0; i < res->num; i++)
		os_free(res->res[i]);
	os_free(res->res);
	os_free(res);
}


const char * event_to_string(enum wpa_event_type event)
{
#define E2S(n) case EVENT_ ## n: return #n
	switch (event) {
	E2S(ASSOC);
	E2S(DISASSOC);
	E2S(MICHAEL_MIC_FAILURE);
	E2S(SCAN_RESULTS);
	E2S(ASSOCINFO);
	E2S(INTERFACE_STATUS);
	E2S(PMKID_CANDIDATE);
	E2S(TDLS);
	E2S(FT_RESPONSE);
	E2S(IBSS_RSN_START);
	E2S(AUTH);
	E2S(DEAUTH);
	E2S(ASSOC_REJECT);
	E2S(AUTH_TIMED_OUT);
	E2S(ASSOC_TIMED_OUT);
	E2S(WPS_BUTTON_PUSHED);
	E2S(TX_STATUS);
	E2S(RX_FROM_UNKNOWN);
	E2S(RX_MGMT);
	E2S(REMAIN_ON_CHANNEL);
	E2S(CANCEL_REMAIN_ON_CHANNEL);
	E2S(RX_PROBE_REQ);
	E2S(NEW_STA);
	E2S(EAPOL_RX);
	E2S(SIGNAL_CHANGE);
	E2S(INTERFACE_ENABLED);
	E2S(INTERFACE_DISABLED);
	E2S(CHANNEL_LIST_CHANGED);
	E2S(INTERFACE_UNAVAILABLE);
	E2S(BEST_CHANNEL);
	E2S(UNPROT_DEAUTH);
	E2S(UNPROT_DISASSOC);
	E2S(STATION_LOW_ACK);
	E2S(IBSS_PEER_LOST);
	E2S(DRIVER_GTK_REKEY);
	E2S(SCHED_SCAN_STOPPED);
	E2S(DRIVER_CLIENT_POLL_OK);
	E2S(EAPOL_TX_STATUS);
	E2S(CH_SWITCH);
	E2S(WNM);
	E2S(CONNECT_FAILED_REASON);
	E2S(DFS_RADAR_DETECTED);
	E2S(DFS_CAC_FINISHED);
	E2S(DFS_CAC_ABORTED);
	E2S(DFS_NOP_FINISHED);
	E2S(SURVEY);
	E2S(SCAN_STARTED);
	E2S(AVOID_FREQUENCIES);
	E2S(NEW_PEER_CANDIDATE);
	E2S(ACS_CHANNEL_SELECTED);
	E2S(DFS_CAC_STARTED);
	E2S(P2P_LO_STOP);
	E2S(BEACON_LOSS);
	E2S(DFS_PRE_CAC_EXPIRED);
	E2S(EXTERNAL_AUTH);
	E2S(PORT_AUTHORIZED);
	E2S(STATION_OPMODE_CHANGED);
	E2S(INTERFACE_MAC_CHANGED);
	E2S(WDS_STA_INTERFACE_STATUS);
	}

	return "UNKNOWN";
#undef E2S
}


const char * channel_width_to_string(enum chan_width width)
{
	switch (width) {
	case CHAN_WIDTH_20_NOHT:
		return "20 MHz (no HT)";
	case CHAN_WIDTH_20:
		return "20 MHz";
	case CHAN_WIDTH_40:
		return "40 MHz";
	case CHAN_WIDTH_80:
		return "80 MHz";
	case CHAN_WIDTH_80P80:
		return "80+80 MHz";
	case CHAN_WIDTH_160:
		return "160 MHz";
	default:
		return "unknown";
	}
}


int channel_width_to_int(enum chan_width width)
{
	switch (width) {
	case CHAN_WIDTH_20_NOHT:
	case CHAN_WIDTH_20:
		return 20;
	case CHAN_WIDTH_40:
		return 40;
	case CHAN_WIDTH_80:
		return 80;
	case CHAN_WIDTH_80P80:
	case CHAN_WIDTH_160:
		return 160;
	default:
		return 0;
	}
}


int ht_supported(const struct hostapd_hw_modes *mode)
{
	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
		/*
		 * The driver did not indicate whether it supports HT. Assume
		 * it does to avoid connection issues.
		 */
		return 1;
	}

	/*
	 * IEEE Std 802.11n-2009 20.1.1:
	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
	 */
	return mode->mcs_set[0] == 0xff;
}


int vht_supported(const struct hostapd_hw_modes *mode)
{
	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
		/*
		 * The driver did not indicate whether it supports VHT. Assume
		 * it does to avoid connection issues.
		 */
		return 1;
	}

	/*
	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
	 * TODO: Verify if this complies with the standard
	 */
	return (mode->vht_mcs_set[0] & 0x3) != 3;
}


static int wpa_check_wowlan_trigger(const char *start, const char *trigger,
				    int capa_trigger, u8 *param_trigger)
{
	if (os_strcmp(start, trigger) != 0)
		return 0;
	if (!capa_trigger)
		return 0;

	*param_trigger = 1;
	return 1;
}


struct wowlan_triggers *
wpa_get_wowlan_triggers(const char *wowlan_triggers,
			const struct wpa_driver_capa *capa)
{
	struct wowlan_triggers *triggers;
	char *start, *end, *buf;
	int last;

	if (!wowlan_triggers)
		return NULL;

	buf = os_strdup(wowlan_triggers);
	if (buf == NULL)
		return NULL;

	triggers = os_zalloc(sizeof(*triggers));
	if (triggers == NULL)
		goto out;

#define CHECK_TRIGGER(trigger) \
	wpa_check_wowlan_trigger(start, #trigger,			\
				  capa->wowlan_triggers.trigger,	\
				  &triggers->trigger)

	start = buf;
	while (*start != '\0') {
		while (isblank((unsigned char) *start))
			start++;
		if (*start == '\0')
			break;
		end = start;
		while (!isblank((unsigned char) *end) && *end != '\0')
			end++;
		last = *end == '\0';
		*end = '\0';

		if (!CHECK_TRIGGER(any) &&
		    !CHECK_TRIGGER(disconnect) &&
		    !CHECK_TRIGGER(magic_pkt) &&
		    !CHECK_TRIGGER(gtk_rekey_failure) &&
		    !CHECK_TRIGGER(eap_identity_req) &&
		    !CHECK_TRIGGER(four_way_handshake) &&
		    !CHECK_TRIGGER(rfkill_release)) {
			wpa_printf(MSG_DEBUG,
				   "Unknown/unsupported wowlan trigger '%s'",
				   start);
			os_free(triggers);
			triggers = NULL;
			goto out;
		}

		if (last)
			break;
		start = end + 1;
	}
#undef CHECK_TRIGGER

out:
	os_free(buf);
	return triggers;
}


const char * driver_flag_to_string(u64 flag)
{
#define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
	switch (flag) {
	DF2S(DRIVER_IE);
	DF2S(SET_KEYS_AFTER_ASSOC);
	DF2S(DFS_OFFLOAD);
	DF2S(4WAY_HANDSHAKE_PSK);
	DF2S(4WAY_HANDSHAKE_8021X);
	DF2S(WIRED);
	DF2S(SME);
	DF2S(AP);
	DF2S(SET_KEYS_AFTER_ASSOC_DONE);
	DF2S(HT_2040_COEX);
	DF2S(P2P_CONCURRENT);
	DF2S(P2P_DEDICATED_INTERFACE);
	DF2S(P2P_CAPABLE);
	DF2S(AP_TEARDOWN_SUPPORT);
	DF2S(P2P_MGMT_AND_NON_P2P);
	DF2S(SANE_ERROR_CODES);
	DF2S(OFFCHANNEL_TX);
	DF2S(EAPOL_TX_STATUS);
	DF2S(DEAUTH_TX_STATUS);
	DF2S(BSS_SELECTION);
	DF2S(TDLS_SUPPORT);
	DF2S(TDLS_EXTERNAL_SETUP);
	DF2S(PROBE_RESP_OFFLOAD);
	DF2S(AP_UAPSD);
	DF2S(INACTIVITY_TIMER);
	DF2S(AP_MLME);
	DF2S(SAE);
	DF2S(OBSS_SCAN);
	DF2S(IBSS);
	DF2S(RADAR);
	DF2S(DEDICATED_P2P_DEVICE);
	DF2S(QOS_MAPPING);
	DF2S(AP_CSA);
	DF2S(MESH);
	DF2S(ACS_OFFLOAD);
	DF2S(KEY_MGMT_OFFLOAD);
	DF2S(TDLS_CHANNEL_SWITCH);
	DF2S(HT_IBSS);
	DF2S(VHT_IBSS);
	DF2S(SUPPORT_HW_MODE_ANY);
	DF2S(OFFCHANNEL_SIMULTANEOUS);
	DF2S(FULL_AP_CLIENT_STATE);
	DF2S(P2P_LISTEN_OFFLOAD);
	DF2S(SUPPORT_FILS);
	DF2S(BEACON_RATE_LEGACY);
	DF2S(BEACON_RATE_HT);
	DF2S(BEACON_RATE_VHT);
	DF2S(MGMT_TX_RANDOM_TA);
	DF2S(MGMT_TX_RANDOM_TA_CONNECTED);
	DF2S(SCHED_SCAN_RELATIVE_RSSI);
	DF2S(HE_CAPABILITIES);
	DF2S(FILS_SK_OFFLOAD);
	DF2S(OCE_STA);
	DF2S(OCE_AP);
	DF2S(OCE_STA_CFON);
	DF2S(MFP_OPTIONAL);
	}
	return "UNKNOWN";
#undef DF2S
}
