wpa: Import wpa_supplicant/hostapd commit b26f5c0fe
This is the December/January update to vendor/wpa committed upstream 2021-12-13. MFC after: 1 month
This commit is contained in:
parent
f567fcb2ff
commit
32a95656b5
@ -567,6 +567,9 @@ NEED_ASN1=y
|
|||||||
ifdef CONFIG_DPP2
|
ifdef CONFIG_DPP2
|
||||||
L_CFLAGS += -DCONFIG_DPP2
|
L_CFLAGS += -DCONFIG_DPP2
|
||||||
endif
|
endif
|
||||||
|
ifdef CONFIG_DPP3
|
||||||
|
L_CFLAGS += -DCONFIG_DPP3
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_PASN
|
ifdef CONFIG_PASN
|
||||||
|
@ -593,6 +593,9 @@ NEED_ASN1=y
|
|||||||
ifdef CONFIG_DPP2
|
ifdef CONFIG_DPP2
|
||||||
CFLAGS += -DCONFIG_DPP2
|
CFLAGS += -DCONFIG_DPP2
|
||||||
endif
|
endif
|
||||||
|
ifdef CONFIG_DPP3
|
||||||
|
CFLAGS += -DCONFIG_DPP3
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_PASN
|
ifdef CONFIG_PASN
|
||||||
|
@ -3193,6 +3193,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
conf->acs_freq_list_present = 1;
|
conf->acs_freq_list_present = 1;
|
||||||
} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
|
} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
|
||||||
conf->acs_exclude_6ghz_non_psc = atoi(pos);
|
conf->acs_exclude_6ghz_non_psc = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "min_tx_power") == 0) {
|
||||||
|
int val = atoi(pos);
|
||||||
|
|
||||||
|
if (val < 0 || val > 255) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Line %d: invalid min_tx_power %d (expected 0..255)",
|
||||||
|
line, val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
conf->min_tx_power = val;
|
||||||
} else if (os_strcmp(buf, "beacon_int") == 0) {
|
} else if (os_strcmp(buf, "beacon_int") == 0) {
|
||||||
int val = atoi(pos);
|
int val = atoi(pos);
|
||||||
/* MIB defines range as 1..65535, but very small values
|
/* MIB defines range as 1..65535, but very small values
|
||||||
|
@ -1504,7 +1504,7 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
val = atoi(value);
|
val = atoi(value);
|
||||||
if (val < 0 || val > 1)
|
if (val < 0 || val > MBO_ASSOC_DISALLOW_REASON_LOW_RSSI)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
hapd->mbo_assoc_disallow = val;
|
hapd->mbo_assoc_disallow = val;
|
||||||
@ -3463,7 +3463,9 @@ static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd,
|
|||||||
if (os_strcmp(field, "dpp") == 0) {
|
if (os_strcmp(field, "dpp") == 0) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP3
|
||||||
|
res = os_snprintf(buf, buflen, "DPP=3");
|
||||||
|
#elif defined(CONFIG_DPP2)
|
||||||
res = os_snprintf(buf, buflen, "DPP=2");
|
res = os_snprintf(buf, buflen, "DPP=2");
|
||||||
#else /* CONFIG_DPP2 */
|
#else /* CONFIG_DPP2 */
|
||||||
res = os_snprintf(buf, buflen, "DPP=1");
|
res = os_snprintf(buf, buflen, "DPP=1");
|
||||||
@ -4492,7 +4494,9 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
|
|||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
dpp_test = DPP_TEST_DISABLED;
|
dpp_test = DPP_TEST_DISABLED;
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP3
|
||||||
|
dpp_version_override = 3;
|
||||||
|
#elif defined(CONFIG_DPP2)
|
||||||
dpp_version_override = 2;
|
dpp_version_override = 2;
|
||||||
#else /* CONFIG_DPP2 */
|
#else /* CONFIG_DPP2 */
|
||||||
dpp_version_override = 1;
|
dpp_version_override = 1;
|
||||||
|
@ -402,3 +402,11 @@ CONFIG_IPV6=y
|
|||||||
# production use.
|
# production use.
|
||||||
# This requires CONFIG_IEEE80211W=y to be enabled, too.
|
# This requires CONFIG_IEEE80211W=y to be enabled, too.
|
||||||
#CONFIG_PASN=y
|
#CONFIG_PASN=y
|
||||||
|
|
||||||
|
# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
|
||||||
|
CONFIG_DPP=y
|
||||||
|
# DPP version 2 support
|
||||||
|
CONFIG_DPP2=y
|
||||||
|
# DPP version 3 support (experimental and still changing; do not enable for
|
||||||
|
# production use)
|
||||||
|
#CONFIG_DPP3=y
|
||||||
|
@ -225,6 +225,10 @@ channel=1
|
|||||||
# Default behavior is to include all PSC and non-PSC channels.
|
# Default behavior is to include all PSC and non-PSC channels.
|
||||||
#acs_exclude_6ghz_non_psc=1
|
#acs_exclude_6ghz_non_psc=1
|
||||||
|
|
||||||
|
# Set minimum permitted max TX power (in dBm) for ACS and DFS channel selection.
|
||||||
|
# (default 0, i.e., not constraint)
|
||||||
|
#min_tx_power=20
|
||||||
|
|
||||||
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
|
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
|
||||||
beacon_int=100
|
beacon_int=100
|
||||||
|
|
||||||
|
@ -546,6 +546,9 @@ static void acs_survey_mode_interference_factor(
|
|||||||
if (!is_in_freqlist(iface, chan))
|
if (!is_in_freqlist(iface, chan))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||||
|
continue;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
|
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
|
||||||
chan->chan, chan->freq);
|
chan->chan, chan->freq);
|
||||||
|
|
||||||
@ -673,6 +676,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
|||||||
if (!is_in_freqlist(iface, chan))
|
if (!is_in_freqlist(iface, chan))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!chan_bw_allowed(chan, bw, 1, 1)) {
|
if (!chan_bw_allowed(chan, bw, 1, 1)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"ACS: Channel %d: BW %u is not supported",
|
"ACS: Channel %d: BW %u is not supported",
|
||||||
@ -1047,6 +1053,9 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
|
|||||||
if (!is_in_freqlist(iface, chan))
|
if (!is_in_freqlist(iface, chan))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||||
|
continue;
|
||||||
|
|
||||||
*freq++ = chan->freq;
|
*freq++ = chan->freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ struct mesh_conf {
|
|||||||
int dot11MeshRetryTimeout; /* msec */
|
int dot11MeshRetryTimeout; /* msec */
|
||||||
int dot11MeshConfirmTimeout; /* msec */
|
int dot11MeshConfirmTimeout; /* msec */
|
||||||
int dot11MeshHoldingTimeout; /* msec */
|
int dot11MeshHoldingTimeout; /* msec */
|
||||||
|
int mesh_fwding;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_STA_COUNT 2007
|
#define MAX_STA_COUNT 2007
|
||||||
@ -696,6 +697,7 @@ struct hostapd_bss_config {
|
|||||||
|
|
||||||
#define MESH_ENABLED BIT(0)
|
#define MESH_ENABLED BIT(0)
|
||||||
int mesh;
|
int mesh;
|
||||||
|
int mesh_fwding;
|
||||||
|
|
||||||
u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
|
u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
|
||||||
|
|
||||||
@ -953,6 +955,7 @@ struct hostapd_config {
|
|||||||
struct wpa_freq_range_list acs_freq_list;
|
struct wpa_freq_range_list acs_freq_list;
|
||||||
u8 acs_freq_list_present;
|
u8 acs_freq_list_present;
|
||||||
int acs_exclude_dfs;
|
int acs_exclude_dfs;
|
||||||
|
u8 min_tx_power;
|
||||||
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
|
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
|
||||||
int acs_exclude_6ghz_non_psc;
|
int acs_exclude_6ghz_non_psc;
|
||||||
enum {
|
enum {
|
||||||
|
@ -888,7 +888,8 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
|
|||||||
continue;
|
continue;
|
||||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||||
!(hapd->iface->conf->acs_exclude_dfs &&
|
!(hapd->iface->conf->acs_exclude_dfs &&
|
||||||
(chan->flag & HOSTAPD_CHAN_RADAR)))
|
(chan->flag & HOSTAPD_CHAN_RADAR)) &&
|
||||||
|
!(chan->max_tx_power < hapd->iface->conf->min_tx_power))
|
||||||
int_array_add_unique(freq_list, chan->freq);
|
int_array_add_unique(freq_list, chan->freq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,9 +570,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
|
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
||||||
(hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
|
|
||||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
|
||||||
|
|
||||||
pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
|
pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
|
||||||
pos = hostapd_eid_fils_indic(hapd, pos, 0);
|
pos = hostapd_eid_fils_indic(hapd, pos, 0);
|
||||||
@ -1594,9 +1592,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
|
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
||||||
(hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
|
|
||||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
|
||||||
|
|
||||||
tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON);
|
tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON);
|
||||||
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
|
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
|
||||||
|
@ -246,6 +246,9 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (ret_chan && idx == channel_idx) {
|
if (ret_chan && idx == channel_idx) {
|
||||||
wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
|
wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
|
||||||
chan->freq, chan->chan);
|
chan->freq, chan->chan);
|
||||||
|
@ -1554,17 +1554,38 @@ static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
skip_connector:
|
skip_connector:
|
||||||
|
if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
|
||||||
|
goto skip_proto_ver;
|
||||||
|
}
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
if (DPP_VERSION > 1) {
|
if (DPP_VERSION > 1) {
|
||||||
|
u8 ver = DPP_VERSION;
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
int conn_ver;
|
||||||
|
|
||||||
|
conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
|
||||||
|
if (conn_ver > 0 && ver != conn_ver) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Use Connector version %d instead of current protocol version %d",
|
||||||
|
conn_ver, ver);
|
||||||
|
ver = conn_ver;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
/* Protocol Version */
|
/* Protocol Version */
|
||||||
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
wpabuf_put_le16(msg, 1);
|
wpabuf_put_le16(msg, 1);
|
||||||
wpabuf_put_u8(msg, DPP_VERSION);
|
wpabuf_put_u8(msg, ver);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
skip_proto_ver:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
|
wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
|
||||||
" status=%d", MAC2STR(src), status);
|
" status=%d", MAC2STR(src), status);
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
@ -1648,6 +1669,28 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
if (intro.peer_version && intro.peer_version >= 2) {
|
||||||
|
const u8 *version;
|
||||||
|
u16 version_len;
|
||||||
|
u8 attr_version = 1;
|
||||||
|
|
||||||
|
version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
|
||||||
|
&version_len);
|
||||||
|
if (version && version_len >= 1)
|
||||||
|
attr_version = version[0];
|
||||||
|
if (attr_version != intro.peer_version) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"DPP: Protocol version mismatch (Connector: %d Attribute: %d",
|
||||||
|
intro.peer_version, attr_version);
|
||||||
|
hostapd_dpp_send_peer_disc_resp(hapd, src, freq,
|
||||||
|
trans_id[0],
|
||||||
|
DPP_STATUS_NO_MATCH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
|
if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
|
||||||
expire = hapd->conf->dpp_netaccesskey_expiry;
|
expire = hapd->conf->dpp_netaccesskey_expiry;
|
||||||
if (expire)
|
if (expire)
|
||||||
@ -1670,7 +1713,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
|
|||||||
static void
|
static void
|
||||||
hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
||||||
const u8 *buf, size_t len,
|
const u8 *buf, size_t len,
|
||||||
unsigned int freq)
|
unsigned int freq, bool v2)
|
||||||
{
|
{
|
||||||
struct wpabuf *msg;
|
struct wpabuf *msg;
|
||||||
|
|
||||||
@ -1698,7 +1741,7 @@ hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
|||||||
hapd->own_addr, src,
|
hapd->own_addr, src,
|
||||||
hapd->dpp_pkex_identifier,
|
hapd->dpp_pkex_identifier,
|
||||||
hapd->dpp_pkex_code,
|
hapd->dpp_pkex_code,
|
||||||
buf, len);
|
buf, len, v2);
|
||||||
if (!hapd->dpp_pkex) {
|
if (!hapd->dpp_pkex) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"DPP: Failed to process the request - ignore it");
|
"DPP: Failed to process the request - ignore it");
|
||||||
@ -1910,8 +1953,18 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
|
|||||||
case DPP_PA_PEER_DISCOVERY_REQ:
|
case DPP_PA_PEER_DISCOVERY_REQ:
|
||||||
hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
|
hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
case DPP_PA_PKEX_EXCHANGE_REQ:
|
case DPP_PA_PKEX_EXCHANGE_REQ:
|
||||||
hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
|
/* This is for PKEXv2, but for now, process only with
|
||||||
|
* CONFIG_DPP3 to avoid issues with a capability that has not
|
||||||
|
* been tested with other implementations. */
|
||||||
|
hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq,
|
||||||
|
true);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
case DPP_PA_PKEX_V1_EXCHANGE_REQ:
|
||||||
|
hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq,
|
||||||
|
false);
|
||||||
break;
|
break;
|
||||||
case DPP_PA_PKEX_EXCHANGE_RESP:
|
case DPP_PA_PKEX_EXCHANGE_RESP:
|
||||||
hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
|
hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
|
||||||
@ -2118,15 +2171,16 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
|||||||
if (!hapd->dpp_pkex_code)
|
if (!hapd->dpp_pkex_code)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (os_strstr(cmd, " init=1")) {
|
if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) {
|
||||||
struct wpabuf *msg;
|
struct wpabuf *msg;
|
||||||
|
bool v2 = os_strstr(cmd, " init=2") != NULL;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
||||||
dpp_pkex_free(hapd->dpp_pkex);
|
dpp_pkex_free(hapd->dpp_pkex);
|
||||||
hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
|
hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
|
||||||
hapd->own_addr,
|
hapd->own_addr,
|
||||||
hapd->dpp_pkex_identifier,
|
hapd->dpp_pkex_identifier,
|
||||||
hapd->dpp_pkex_code);
|
hapd->dpp_pkex_code, v2);
|
||||||
if (!hapd->dpp_pkex)
|
if (!hapd->dpp_pkex)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -2134,7 +2188,8 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
|||||||
/* TODO: Which channel to use? */
|
/* TODO: Which channel to use? */
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
" freq=%u type=%d", MAC2STR(broadcast), 2437,
|
" freq=%u type=%d", MAC2STR(broadcast), 2437,
|
||||||
DPP_PA_PKEX_EXCHANGE_REQ);
|
v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||||
|
DPP_PA_PKEX_V1_EXCHANGE_REQ);
|
||||||
hostapd_drv_send_action(hapd, 2437, 0, broadcast,
|
hostapd_drv_send_action(hapd, 2437, 0, broadcast,
|
||||||
wpabuf_head(msg), wpabuf_len(msg));
|
wpabuf_head(msg), wpabuf_len(msg));
|
||||||
}
|
}
|
||||||
|
@ -957,6 +957,12 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||||||
hapd->iconf->ch_switch_vht_config = 0;
|
hapd->iconf->ch_switch_vht_config = 0;
|
||||||
hapd->iconf->ch_switch_he_config = 0;
|
hapd->iconf->ch_switch_he_config = 0;
|
||||||
|
|
||||||
|
if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 ||
|
||||||
|
width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160)
|
||||||
|
hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||||
|
else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT)
|
||||||
|
hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||||
|
|
||||||
hapd->iconf->secondary_channel = offset;
|
hapd->iconf->secondary_channel = offset;
|
||||||
hostapd_set_oper_chwidth(hapd->iconf, chwidth);
|
hostapd_set_oper_chwidth(hapd->iconf, chwidth);
|
||||||
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
|
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
|
||||||
|
@ -3461,6 +3461,20 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
|
|||||||
NULL))
|
NULL))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
switch (params->bandwidth) {
|
||||||
|
case 0:
|
||||||
|
case 20:
|
||||||
|
conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||||
|
break;
|
||||||
|
case 40:
|
||||||
|
case 80:
|
||||||
|
case 160:
|
||||||
|
conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (params->bandwidth) {
|
switch (params->bandwidth) {
|
||||||
case 0:
|
case 0:
|
||||||
case 20:
|
case 20:
|
||||||
@ -3482,6 +3496,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
conf->channel = channel;
|
conf->channel = channel;
|
||||||
conf->ieee80211n = params->ht_enabled;
|
conf->ieee80211n = params->ht_enabled;
|
||||||
|
conf->ieee80211ac = params->vht_enabled;
|
||||||
conf->secondary_channel = params->sec_channel_offset;
|
conf->secondary_channel = params->sec_channel_offset;
|
||||||
ieee80211_freq_to_chan(params->center_freq1,
|
ieee80211_freq_to_chan(params->center_freq1,
|
||||||
&seg0);
|
&seg0);
|
||||||
|
@ -28,7 +28,9 @@
|
|||||||
static const char * dpp_netrole_str(enum dpp_netrole netrole);
|
static const char * dpp_netrole_str(enum dpp_netrole netrole);
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP3
|
||||||
|
int dpp_version_override = 3;
|
||||||
|
#elif defined(CONFIG_DPP2)
|
||||||
int dpp_version_override = 2;
|
int dpp_version_override = 2;
|
||||||
#else
|
#else
|
||||||
int dpp_version_override = 1;
|
int dpp_version_override = 1;
|
||||||
@ -306,6 +308,8 @@ int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version)
|
|||||||
bi->version = 1;
|
bi->version = 1;
|
||||||
else if (*version == '2')
|
else if (*version == '2')
|
||||||
bi->version = 2;
|
bi->version = 2;
|
||||||
|
else if (*version == '3')
|
||||||
|
bi->version = 3;
|
||||||
else
|
else
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
|
wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
|
||||||
|
|
||||||
@ -628,7 +632,8 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
|
|||||||
macstr,
|
macstr,
|
||||||
bi->info ? "I:" : "", bi->info ? bi->info : "",
|
bi->info ? "I:" : "", bi->info ? bi->info : "",
|
||||||
bi->info ? ";" : "",
|
bi->info ? ";" : "",
|
||||||
DPP_VERSION == 2 ? "V:2;" : "",
|
DPP_VERSION == 3 ? "V:3;" :
|
||||||
|
(DPP_VERSION == 2 ? "V:2;" : ""),
|
||||||
bi->pk);
|
bi->pk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1499,6 +1504,10 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
|
|||||||
json_value_sep(dppcon);
|
json_value_sep(dppcon);
|
||||||
json_add_string(dppcon, "expiry", expiry);
|
json_add_string(dppcon, "expiry", expiry);
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
json_value_sep(dppcon);
|
||||||
|
json_add_int(dppcon, "version", auth->peer_version);
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
json_end_object(dppcon);
|
json_end_object(dppcon);
|
||||||
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
|
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
|
||||||
(const char *) wpabuf_head(dppcon));
|
(const char *) wpabuf_head(dppcon));
|
||||||
@ -3694,6 +3703,14 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
token = json_get_member(root, "version");
|
||||||
|
if (token && token->type == JSON_NUMBER) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: version = %d", token->number);
|
||||||
|
intro->peer_version = token->number;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
netkey = json_get_member(root, "netAccessKey");
|
netkey = json_get_member(root, "netAccessKey");
|
||||||
if (!netkey || netkey->type != JSON_OBJECT) {
|
if (!netkey || netkey->type != JSON_OBJECT) {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
|
wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
|
||||||
@ -3751,6 +3768,26 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
int dpp_get_connector_version(const char *connector)
|
||||||
|
{
|
||||||
|
struct json_token *root, *token;
|
||||||
|
int ver = -1;
|
||||||
|
|
||||||
|
root = dpp_parse_own_connector(connector);
|
||||||
|
if (!root)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
token = json_get_member(root, "version");
|
||||||
|
if (token && token->type == JSON_NUMBER)
|
||||||
|
ver = token->number;
|
||||||
|
|
||||||
|
json_free(root);
|
||||||
|
return ver;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
|
|
||||||
unsigned int dpp_next_id(struct dpp_global *dpp)
|
unsigned int dpp_next_id(struct dpp_global *dpp)
|
||||||
{
|
{
|
||||||
struct dpp_bootstrap_info *bi;
|
struct dpp_bootstrap_info *bi;
|
||||||
|
@ -25,7 +25,9 @@ struct dpp_reconfig_id;
|
|||||||
#define DPP_VERSION (dpp_version_override)
|
#define DPP_VERSION (dpp_version_override)
|
||||||
extern int dpp_version_override;
|
extern int dpp_version_override;
|
||||||
#else /* CONFIG_TESTING_OPTIONS */
|
#else /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP3
|
||||||
|
#define DPP_VERSION 3
|
||||||
|
#elif defined(CONFIG_DPP2)
|
||||||
#define DPP_VERSION 2
|
#define DPP_VERSION 2
|
||||||
#else
|
#else
|
||||||
#define DPP_VERSION 1
|
#define DPP_VERSION 1
|
||||||
@ -41,7 +43,7 @@ enum dpp_public_action_frame_type {
|
|||||||
DPP_PA_AUTHENTICATION_CONF = 2,
|
DPP_PA_AUTHENTICATION_CONF = 2,
|
||||||
DPP_PA_PEER_DISCOVERY_REQ = 5,
|
DPP_PA_PEER_DISCOVERY_REQ = 5,
|
||||||
DPP_PA_PEER_DISCOVERY_RESP = 6,
|
DPP_PA_PEER_DISCOVERY_RESP = 6,
|
||||||
DPP_PA_PKEX_EXCHANGE_REQ = 7,
|
DPP_PA_PKEX_V1_EXCHANGE_REQ = 7,
|
||||||
DPP_PA_PKEX_EXCHANGE_RESP = 8,
|
DPP_PA_PKEX_EXCHANGE_RESP = 8,
|
||||||
DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
|
DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
|
||||||
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
|
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
|
||||||
@ -52,6 +54,7 @@ enum dpp_public_action_frame_type {
|
|||||||
DPP_PA_RECONFIG_AUTH_REQ = 15,
|
DPP_PA_RECONFIG_AUTH_REQ = 15,
|
||||||
DPP_PA_RECONFIG_AUTH_RESP = 16,
|
DPP_PA_RECONFIG_AUTH_RESP = 16,
|
||||||
DPP_PA_RECONFIG_AUTH_CONF = 17,
|
DPP_PA_RECONFIG_AUTH_CONF = 17,
|
||||||
|
DPP_PA_PKEX_EXCHANGE_REQ = 18,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dpp_attribute_id {
|
enum dpp_attribute_id {
|
||||||
@ -173,6 +176,7 @@ struct dpp_pkex {
|
|||||||
unsigned int initiator:1;
|
unsigned int initiator:1;
|
||||||
unsigned int exchange_done:1;
|
unsigned int exchange_done:1;
|
||||||
unsigned int failed:1;
|
unsigned int failed:1;
|
||||||
|
unsigned int v2:1;
|
||||||
struct dpp_bootstrap_info *own_bi;
|
struct dpp_bootstrap_info *own_bi;
|
||||||
u8 own_mac[ETH_ALEN];
|
u8 own_mac[ETH_ALEN];
|
||||||
u8 peer_mac[ETH_ALEN];
|
u8 peer_mac[ETH_ALEN];
|
||||||
@ -190,6 +194,7 @@ struct dpp_pkex {
|
|||||||
unsigned int exch_req_wait_time;
|
unsigned int exch_req_wait_time;
|
||||||
unsigned int exch_req_tries;
|
unsigned int exch_req_tries;
|
||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
|
u8 peer_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dpp_akm {
|
enum dpp_akm {
|
||||||
@ -372,6 +377,7 @@ struct dpp_introduction {
|
|||||||
u8 pmkid[PMKID_LEN];
|
u8 pmkid[PMKID_LEN];
|
||||||
u8 pmk[PMK_LEN_MAX];
|
u8 pmk[PMK_LEN_MAX];
|
||||||
size_t pmk_len;
|
size_t pmk_len;
|
||||||
|
int peer_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dpp_relay_config {
|
struct dpp_relay_config {
|
||||||
@ -491,6 +497,8 @@ enum dpp_test_behavior {
|
|||||||
DPP_TEST_STOP_AT_AUTH_CONF = 89,
|
DPP_TEST_STOP_AT_AUTH_CONF = 89,
|
||||||
DPP_TEST_STOP_AT_CONF_REQ = 90,
|
DPP_TEST_STOP_AT_CONF_REQ = 90,
|
||||||
DPP_TEST_REJECT_CONFIG = 91,
|
DPP_TEST_REJECT_CONFIG = 91,
|
||||||
|
DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ = 92,
|
||||||
|
DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP = 93,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum dpp_test_behavior dpp_test;
|
extern enum dpp_test_behavior dpp_test;
|
||||||
@ -593,17 +601,18 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
|
|||||||
const u8 *csign_key, size_t csign_key_len,
|
const u8 *csign_key, size_t csign_key_len,
|
||||||
const u8 *peer_connector, size_t peer_connector_len,
|
const u8 *peer_connector, size_t peer_connector_len,
|
||||||
os_time_t *expiry);
|
os_time_t *expiry);
|
||||||
|
int dpp_get_connector_version(const char *connector);
|
||||||
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
||||||
const u8 *own_mac,
|
const u8 *own_mac,
|
||||||
const char *identifier,
|
const char *identifier, const char *code,
|
||||||
const char *code);
|
bool v2);
|
||||||
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
||||||
struct dpp_bootstrap_info *bi,
|
struct dpp_bootstrap_info *bi,
|
||||||
const u8 *own_mac,
|
const u8 *own_mac,
|
||||||
const u8 *peer_mac,
|
const u8 *peer_mac,
|
||||||
const char *identifier,
|
const char *identifier,
|
||||||
const char *code,
|
const char *code,
|
||||||
const u8 *buf, size_t len);
|
const u8 *buf, size_t len, bool v2);
|
||||||
struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
||||||
const u8 *peer_mac,
|
const u8 *peer_mac,
|
||||||
const u8 *buf, size_t len);
|
const u8 *buf, size_t len);
|
||||||
|
@ -1447,12 +1447,15 @@ dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
|
|||||||
struct crypto_bignum *hash_bn = NULL;
|
struct crypto_bignum *hash_bn = NULL;
|
||||||
struct crypto_ec *ec = NULL;
|
struct crypto_ec *ec = NULL;
|
||||||
|
|
||||||
/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
|
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
|
if (mac_init) {
|
||||||
addr[num_elem] = mac_init;
|
wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
|
||||||
len[num_elem] = ETH_ALEN;
|
MAC2STR(mac_init));
|
||||||
num_elem++;
|
addr[num_elem] = mac_init;
|
||||||
|
len[num_elem] = ETH_ALEN;
|
||||||
|
num_elem++;
|
||||||
|
}
|
||||||
if (identifier) {
|
if (identifier) {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
|
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
|
||||||
identifier);
|
identifier);
|
||||||
@ -1467,7 +1470,7 @@ dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
|
|||||||
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
|
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
wpa_hexdump_key(MSG_DEBUG,
|
wpa_hexdump_key(MSG_DEBUG,
|
||||||
"DPP: H(MAC-Initiator | [identifier |] code)",
|
"DPP: H([MAC-Initiator |] [identifier |] code)",
|
||||||
hash, curve->hash_len);
|
hash, curve->hash_len);
|
||||||
Pi_key = dpp_pkex_get_role_elem(curve, 1);
|
Pi_key = dpp_pkex_get_role_elem(curve, 1);
|
||||||
if (!Pi_key)
|
if (!Pi_key)
|
||||||
@ -1519,12 +1522,15 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
|
|||||||
struct crypto_bignum *hash_bn = NULL;
|
struct crypto_bignum *hash_bn = NULL;
|
||||||
struct crypto_ec *ec = NULL;
|
struct crypto_ec *ec = NULL;
|
||||||
|
|
||||||
/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
|
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
|
if (mac_resp) {
|
||||||
addr[num_elem] = mac_resp;
|
wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
|
||||||
len[num_elem] = ETH_ALEN;
|
MAC2STR(mac_resp));
|
||||||
num_elem++;
|
addr[num_elem] = mac_resp;
|
||||||
|
len[num_elem] = ETH_ALEN;
|
||||||
|
num_elem++;
|
||||||
|
}
|
||||||
if (identifier) {
|
if (identifier) {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
|
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
|
||||||
identifier);
|
identifier);
|
||||||
@ -1539,7 +1545,7 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
|
|||||||
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
|
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
wpa_hexdump_key(MSG_DEBUG,
|
wpa_hexdump_key(MSG_DEBUG,
|
||||||
"DPP: H(MAC-Responder | [identifier |] code)",
|
"DPP: H([MAC-Responder |] [identifier |] code)",
|
||||||
hash, curve->hash_len);
|
hash, curve->hash_len);
|
||||||
Pr_key = dpp_pkex_get_role_elem(curve, 0);
|
Pr_key = dpp_pkex_get_role_elem(curve, 0);
|
||||||
if (!Pr_key)
|
if (!Pr_key)
|
||||||
@ -1578,6 +1584,7 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
|
|||||||
|
|
||||||
|
|
||||||
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
||||||
|
u8 ver_init, u8 ver_resp,
|
||||||
const u8 *Mx, size_t Mx_len,
|
const u8 *Mx, size_t Mx_len,
|
||||||
const u8 *Nx, size_t Nx_len,
|
const u8 *Nx, size_t Nx_len,
|
||||||
const char *code,
|
const char *code,
|
||||||
@ -1589,7 +1596,10 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
|||||||
u8 *info, *pos;
|
u8 *info, *pos;
|
||||||
size_t info_len;
|
size_t info_len;
|
||||||
|
|
||||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
/*
|
||||||
|
* v1: info = MAC-Initiator | MAC-Responder
|
||||||
|
* v2: info = Protocol Version-Initiator | Protocol Version-Responder
|
||||||
|
* z = HKDF(<>, info | M.x | N.x | code, K.x)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* HKDF-Extract(<>, IKM=K.x) */
|
/* HKDF-Extract(<>, IKM=K.x) */
|
||||||
@ -1598,15 +1608,24 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
|||||||
return -1;
|
return -1;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
|
||||||
prk, hash_len);
|
prk, hash_len);
|
||||||
info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
|
if (mac_init && mac_resp)
|
||||||
|
info_len = 2 * ETH_ALEN;
|
||||||
|
else
|
||||||
|
info_len = 2;
|
||||||
|
info_len += Mx_len + Nx_len + os_strlen(code);
|
||||||
info = os_malloc(info_len);
|
info = os_malloc(info_len);
|
||||||
if (!info)
|
if (!info)
|
||||||
return -1;
|
return -1;
|
||||||
pos = info;
|
pos = info;
|
||||||
os_memcpy(pos, mac_init, ETH_ALEN);
|
if (mac_init && mac_resp) {
|
||||||
pos += ETH_ALEN;
|
os_memcpy(pos, mac_init, ETH_ALEN);
|
||||||
os_memcpy(pos, mac_resp, ETH_ALEN);
|
pos += ETH_ALEN;
|
||||||
pos += ETH_ALEN;
|
os_memcpy(pos, mac_resp, ETH_ALEN);
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
} else {
|
||||||
|
*pos++ = ver_init;
|
||||||
|
*pos++ = ver_resp;
|
||||||
|
}
|
||||||
os_memcpy(pos, Mx, Mx_len);
|
os_memcpy(pos, Mx, Mx_len);
|
||||||
pos += Mx_len;
|
pos += Mx_len;
|
||||||
os_memcpy(pos, Nx, Nx_len);
|
os_memcpy(pos, Nx, Nx_len);
|
||||||
|
@ -118,6 +118,7 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
|
|||||||
const char *code, const char *identifier,
|
const char *code, const char *identifier,
|
||||||
struct crypto_ec **ret_ec);
|
struct crypto_ec **ret_ec);
|
||||||
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
||||||
|
u8 ver_init, u8 ver_resp,
|
||||||
const u8 *Mx, size_t Mx_len,
|
const u8 *Mx, size_t Mx_len,
|
||||||
const u8 *Nx, size_t Nx_len,
|
const u8 *Nx, size_t Nx_len,
|
||||||
const char *code,
|
const char *code,
|
||||||
|
@ -26,7 +26,8 @@ size_t dpp_pkex_ephemeral_key_override_len = 0;
|
|||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
|
static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex,
|
||||||
|
bool v2)
|
||||||
{
|
{
|
||||||
struct crypto_ec *ec = NULL;
|
struct crypto_ec *ec = NULL;
|
||||||
const struct crypto_ec_point *X;
|
const struct crypto_ec_point *X;
|
||||||
@ -36,10 +37,11 @@ static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
|
|||||||
size_t attr_len;
|
size_t attr_len;
|
||||||
const struct dpp_curve_params *curve = pkex->own_bi->curve;
|
const struct dpp_curve_params *curve = pkex->own_bi->curve;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
|
wpa_printf(MSG_DEBUG, "DPP: Build PKEX %sExchange Request",
|
||||||
|
v2 ? "" : "Version 1 ");
|
||||||
|
|
||||||
/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
|
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
|
||||||
Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
|
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : pkex->own_mac, pkex->code,
|
||||||
pkex->identifier, &ec);
|
pkex->identifier, &ec);
|
||||||
if (!Qi)
|
if (!Qi)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -76,13 +78,27 @@ static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
|
|||||||
|
|
||||||
/* Initiator -> Responder: group, [identifier,] M */
|
/* Initiator -> Responder: group, [identifier,] M */
|
||||||
attr_len = 4 + 2;
|
attr_len = 4 + 2;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (v2)
|
||||||
|
attr_len += 4 + 1;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
if (pkex->identifier)
|
if (pkex->identifier)
|
||||||
attr_len += 4 + os_strlen(pkex->identifier);
|
attr_len += 4 + os_strlen(pkex->identifier);
|
||||||
attr_len += 4 + 2 * curve->prime_len;
|
attr_len += 4 + 2 * curve->prime_len;
|
||||||
msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
|
msg = dpp_alloc_msg(v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||||
|
DPP_PA_PKEX_V1_EXCHANGE_REQ, attr_len);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (v2) {
|
||||||
|
/* Protocol Version */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, DPP_VERSION);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
|
if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
|
||||||
wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
|
wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
|
||||||
@ -154,8 +170,8 @@ static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt)
|
|||||||
|
|
||||||
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
||||||
const u8 *own_mac,
|
const u8 *own_mac,
|
||||||
const char *identifier,
|
const char *identifier, const char *code,
|
||||||
const char *code)
|
bool v2)
|
||||||
{
|
{
|
||||||
struct dpp_pkex *pkex;
|
struct dpp_pkex *pkex;
|
||||||
|
|
||||||
@ -172,6 +188,7 @@ struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
|||||||
return NULL;
|
return NULL;
|
||||||
pkex->msg_ctx = msg_ctx;
|
pkex->msg_ctx = msg_ctx;
|
||||||
pkex->initiator = 1;
|
pkex->initiator = 1;
|
||||||
|
pkex->v2 = v2;
|
||||||
pkex->own_bi = bi;
|
pkex->own_bi = bi;
|
||||||
os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
|
os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
|
||||||
if (identifier) {
|
if (identifier) {
|
||||||
@ -182,7 +199,7 @@ struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
|||||||
pkex->code = os_strdup(code);
|
pkex->code = os_strdup(code);
|
||||||
if (!pkex->code)
|
if (!pkex->code)
|
||||||
goto fail;
|
goto fail;
|
||||||
pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
|
pkex->exchange_req = dpp_pkex_build_exchange_req(pkex, v2);
|
||||||
if (!pkex->exchange_req)
|
if (!pkex->exchange_req)
|
||||||
goto fail;
|
goto fail;
|
||||||
return pkex;
|
return pkex;
|
||||||
@ -201,8 +218,13 @@ dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
size_t attr_len;
|
size_t attr_len;
|
||||||
const struct dpp_curve_params *curve = pkex->own_bi->curve;
|
const struct dpp_curve_params *curve = pkex->own_bi->curve;
|
||||||
|
|
||||||
/* Initiator -> Responder: DPP Status, [identifier,] N */
|
/* Initiator -> Responder: DPP Status, [Protocol Version,] [identifier,]
|
||||||
|
* N */
|
||||||
attr_len = 4 + 1;
|
attr_len = 4 + 1;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (pkex->v2)
|
||||||
|
attr_len += 4 + 1;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
if (pkex->identifier)
|
if (pkex->identifier)
|
||||||
attr_len += 4 + os_strlen(pkex->identifier);
|
attr_len += 4 + os_strlen(pkex->identifier);
|
||||||
attr_len += 4 + 2 * curve->prime_len;
|
attr_len += 4 + 2 * curve->prime_len;
|
||||||
@ -229,6 +251,15 @@ dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
skip_status:
|
skip_status:
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (pkex->v2) {
|
||||||
|
/* Protocol Version */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, DPP_VERSION);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
/* Code Identifier attribute */
|
/* Code Identifier attribute */
|
||||||
if (pkex->identifier) {
|
if (pkex->identifier) {
|
||||||
wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
|
wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
|
||||||
@ -310,7 +341,7 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
const u8 *peer_mac,
|
const u8 *peer_mac,
|
||||||
const char *identifier,
|
const char *identifier,
|
||||||
const char *code,
|
const char *code,
|
||||||
const u8 *buf, size_t len)
|
const u8 *buf, size_t len, bool v2)
|
||||||
{
|
{
|
||||||
const u8 *attr_group, *attr_id, *attr_key;
|
const u8 *attr_group, *attr_id, *attr_key;
|
||||||
u16 attr_group_len, attr_id_len, attr_key_len;
|
u16 attr_group_len, attr_id_len, attr_key_len;
|
||||||
@ -325,6 +356,7 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
|
u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
|
||||||
size_t Kx_len;
|
size_t Kx_len;
|
||||||
int res;
|
int res;
|
||||||
|
u8 peer_version = 0;
|
||||||
|
|
||||||
if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
|
if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
|
||||||
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||||
@ -332,6 +364,24 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (v2) {
|
||||||
|
const u8 *version;
|
||||||
|
u16 version_len;
|
||||||
|
|
||||||
|
version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
|
||||||
|
&version_len);
|
||||||
|
if (!version || version_len < 1 || version[0] == 0) {
|
||||||
|
wpa_msg(msg_ctx, MSG_INFO,
|
||||||
|
"Missing or invalid Protocol Version attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
peer_version = version[0];
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
|
||||||
|
peer_version);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
|
if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
|
||||||
wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
|
wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
|
||||||
@ -366,6 +416,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
pkex = os_zalloc(sizeof(*pkex));
|
pkex = os_zalloc(sizeof(*pkex));
|
||||||
if (!pkex)
|
if (!pkex)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
pkex->v2 = v2;
|
||||||
|
pkex->peer_version = peer_version;
|
||||||
pkex->own_bi = bi;
|
pkex->own_bi = bi;
|
||||||
pkex->failed = 1;
|
pkex->failed = 1;
|
||||||
pkex->exchange_resp = dpp_pkex_build_exchange_resp(
|
pkex->exchange_resp = dpp_pkex_build_exchange_resp(
|
||||||
@ -385,8 +437,9 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
|
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
|
||||||
Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, &ec);
|
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, identifier,
|
||||||
|
&ec);
|
||||||
if (!Qi)
|
if (!Qi)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -411,6 +464,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
pkex = os_zalloc(sizeof(*pkex));
|
pkex = os_zalloc(sizeof(*pkex));
|
||||||
if (!pkex)
|
if (!pkex)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
pkex->v2 = v2;
|
||||||
|
pkex->peer_version = peer_version;
|
||||||
pkex->t = bi->pkex_t;
|
pkex->t = bi->pkex_t;
|
||||||
pkex->msg_ctx = msg_ctx;
|
pkex->msg_ctx = msg_ctx;
|
||||||
pkex->own_bi = bi;
|
pkex->own_bi = bi;
|
||||||
@ -438,8 +493,9 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
if (!pkex->x)
|
if (!pkex->x)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
|
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
|
||||||
Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, NULL);
|
Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, identifier,
|
||||||
|
NULL);
|
||||||
if (!Qr)
|
if (!Qr)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -487,9 +543,10 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
|
||||||
Kx, Kx_len);
|
Kx, Kx_len);
|
||||||
|
|
||||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
|
||||||
*/
|
res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->peer_mac,
|
||||||
res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
|
pkex->v2 ? NULL : pkex->own_mac,
|
||||||
|
pkex->peer_version, DPP_VERSION,
|
||||||
pkex->Mx, curve->prime_len,
|
pkex->Mx, curve->prime_len,
|
||||||
pkex->Nx, curve->prime_len, pkex->code,
|
pkex->Nx, curve->prime_len, pkex->code,
|
||||||
Kx, Kx_len, pkex->z, curve->hash_len);
|
Kx, Kx_len, pkex->z, curve->hash_len);
|
||||||
@ -645,6 +702,7 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
|
u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
|
||||||
const u8 *addr[4];
|
const u8 *addr[4];
|
||||||
size_t len[4];
|
size_t len[4];
|
||||||
|
size_t num_elem;
|
||||||
u8 u[DPP_MAX_HASH_LEN];
|
u8 u[DPP_MAX_HASH_LEN];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
@ -666,6 +724,24 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (pkex->v2) {
|
||||||
|
const u8 *version;
|
||||||
|
u16 version_len;
|
||||||
|
|
||||||
|
version = dpp_get_attr(buf, buflen, DPP_ATTR_PROTOCOL_VERSION,
|
||||||
|
&version_len);
|
||||||
|
if (!version || version_len < 1 || version[0] == 0) {
|
||||||
|
dpp_pkex_fail(pkex,
|
||||||
|
"Missing or invalid Protocol Version attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pkex->peer_version = version[0];
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
|
||||||
|
pkex->peer_version);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
|
os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
|
||||||
|
|
||||||
attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
|
attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
|
||||||
@ -710,9 +786,9 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
|
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
|
||||||
Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
|
Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac,
|
||||||
pkex->identifier, &ec);
|
pkex->code, pkex->identifier, &ec);
|
||||||
if (!Qr)
|
if (!Qr)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -751,21 +827,29 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
|
||||||
Jx, Jx_len);
|
Jx, Jx_len);
|
||||||
|
|
||||||
/* u = HMAC(J.x, MAC-Initiator | A.x | Y'.x | X.x) */
|
/* u = HMAC(J.x, [MAC-Initiator |] A.x | Y'.x | X.x) */
|
||||||
A_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
|
A_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
|
||||||
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
||||||
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
||||||
if (!A_pub || !Y_pub || !X_pub)
|
if (!A_pub || !Y_pub || !X_pub)
|
||||||
goto fail;
|
goto fail;
|
||||||
addr[0] = pkex->own_mac;
|
num_elem = 0;
|
||||||
len[0] = ETH_ALEN;
|
if (!pkex->v2) {
|
||||||
addr[1] = wpabuf_head(A_pub);
|
addr[num_elem] = pkex->own_mac;
|
||||||
len[1] = wpabuf_len(A_pub) / 2;
|
len[num_elem] = ETH_ALEN;
|
||||||
addr[2] = wpabuf_head(Y_pub);
|
num_elem++;
|
||||||
len[2] = wpabuf_len(Y_pub) / 2;
|
}
|
||||||
addr[3] = wpabuf_head(X_pub);
|
addr[num_elem] = wpabuf_head(A_pub);
|
||||||
len[3] = wpabuf_len(X_pub) / 2;
|
len[num_elem] = wpabuf_len(A_pub) / 2;
|
||||||
if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(Y_pub);
|
||||||
|
len[num_elem] = wpabuf_len(Y_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(X_pub);
|
||||||
|
len[num_elem] = wpabuf_len(X_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
|
||||||
|
< 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
|
wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
|
||||||
|
|
||||||
@ -776,9 +860,10 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
|||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
|
||||||
Kx, Kx_len);
|
Kx, Kx_len);
|
||||||
|
|
||||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
|
||||||
*/
|
res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->own_mac,
|
||||||
res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
|
pkex->v2 ? NULL : pkex->peer_mac,
|
||||||
|
DPP_VERSION, pkex->peer_version,
|
||||||
pkex->Mx, curve->prime_len,
|
pkex->Mx, curve->prime_len,
|
||||||
attr_key /* N.x */, attr_key_len / 2,
|
attr_key /* N.x */, attr_key_len / 2,
|
||||||
pkex->code, Kx, Kx_len,
|
pkex->code, Kx, Kx_len,
|
||||||
@ -933,6 +1018,7 @@ struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
|||||||
u16 wrapped_data_len, b_key_len, peer_u_len = 0;
|
u16 wrapped_data_len, b_key_len, peer_u_len = 0;
|
||||||
const u8 *addr[4];
|
const u8 *addr[4];
|
||||||
size_t len[4];
|
size_t len[4];
|
||||||
|
size_t num_elem;
|
||||||
u8 octet;
|
u8 octet;
|
||||||
u8 *unwrapped = NULL;
|
u8 *unwrapped = NULL;
|
||||||
size_t unwrapped_len = 0;
|
size_t unwrapped_len = 0;
|
||||||
@ -1015,21 +1101,29 @@ struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
|||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
|
||||||
Jx, Jx_len);
|
Jx, Jx_len);
|
||||||
|
|
||||||
/* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
|
/* u' = HMAC(J'.x, [MAC-Initiator |] A'.x | Y.x | X'.x) */
|
||||||
A_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
|
A_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
|
||||||
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
||||||
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
||||||
if (!A_pub || !Y_pub || !X_pub)
|
if (!A_pub || !Y_pub || !X_pub)
|
||||||
goto fail;
|
goto fail;
|
||||||
addr[0] = pkex->peer_mac;
|
num_elem = 0;
|
||||||
len[0] = ETH_ALEN;
|
if (!pkex->v2) {
|
||||||
addr[1] = wpabuf_head(A_pub);
|
addr[num_elem] = pkex->peer_mac;
|
||||||
len[1] = wpabuf_len(A_pub) / 2;
|
len[num_elem] = ETH_ALEN;
|
||||||
addr[2] = wpabuf_head(Y_pub);
|
num_elem++;
|
||||||
len[2] = wpabuf_len(Y_pub) / 2;
|
}
|
||||||
addr[3] = wpabuf_head(X_pub);
|
addr[num_elem] = wpabuf_head(A_pub);
|
||||||
len[3] = wpabuf_len(X_pub) / 2;
|
len[num_elem] = wpabuf_len(A_pub) / 2;
|
||||||
if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(Y_pub);
|
||||||
|
len[num_elem] = wpabuf_len(Y_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(X_pub);
|
||||||
|
len[num_elem] = wpabuf_len(X_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
|
||||||
|
< 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
|
peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
|
||||||
@ -1052,19 +1146,27 @@ struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
|||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
|
||||||
Lx, Lx_len);
|
Lx, Lx_len);
|
||||||
|
|
||||||
/* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
|
/* v = HMAC(L.x, [MAC-Responder |] B.x | X'.x | Y.x) */
|
||||||
B_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
|
B_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
|
||||||
if (!B_pub)
|
if (!B_pub)
|
||||||
goto fail;
|
goto fail;
|
||||||
addr[0] = pkex->own_mac;
|
num_elem = 0;
|
||||||
len[0] = ETH_ALEN;
|
if (!pkex->v2) {
|
||||||
addr[1] = wpabuf_head(B_pub);
|
addr[num_elem] = pkex->own_mac;
|
||||||
len[1] = wpabuf_len(B_pub) / 2;
|
len[num_elem] = ETH_ALEN;
|
||||||
addr[2] = wpabuf_head(X_pub);
|
num_elem++;
|
||||||
len[2] = wpabuf_len(X_pub) / 2;
|
}
|
||||||
addr[3] = wpabuf_head(Y_pub);
|
addr[num_elem] = wpabuf_head(B_pub);
|
||||||
len[3] = wpabuf_len(Y_pub) / 2;
|
len[num_elem] = wpabuf_len(B_pub) / 2;
|
||||||
if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(X_pub);
|
||||||
|
len[num_elem] = wpabuf_len(X_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(Y_pub);
|
||||||
|
len[num_elem] = wpabuf_len(Y_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
|
||||||
|
< 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
|
wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
|
||||||
|
|
||||||
@ -1094,6 +1196,7 @@ int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
|
|||||||
u16 wrapped_data_len, b_key_len, peer_v_len = 0;
|
u16 wrapped_data_len, b_key_len, peer_v_len = 0;
|
||||||
const u8 *addr[4];
|
const u8 *addr[4];
|
||||||
size_t len[4];
|
size_t len[4];
|
||||||
|
size_t num_elem;
|
||||||
u8 octet;
|
u8 octet;
|
||||||
u8 *unwrapped = NULL;
|
u8 *unwrapped = NULL;
|
||||||
size_t unwrapped_len = 0;
|
size_t unwrapped_len = 0;
|
||||||
@ -1177,21 +1280,29 @@ int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
|
|||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
|
||||||
Lx, Lx_len);
|
Lx, Lx_len);
|
||||||
|
|
||||||
/* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
|
/* v' = HMAC(L.x, [MAC-Responder |] B'.x | X.x | Y'.x) */
|
||||||
B_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
|
B_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
|
||||||
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
||||||
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
||||||
if (!B_pub || !X_pub || !Y_pub)
|
if (!B_pub || !X_pub || !Y_pub)
|
||||||
goto fail;
|
goto fail;
|
||||||
addr[0] = pkex->peer_mac;
|
num_elem = 0;
|
||||||
len[0] = ETH_ALEN;
|
if (!pkex->v2) {
|
||||||
addr[1] = wpabuf_head(B_pub);
|
addr[num_elem] = pkex->peer_mac;
|
||||||
len[1] = wpabuf_len(B_pub) / 2;
|
len[num_elem] = ETH_ALEN;
|
||||||
addr[2] = wpabuf_head(X_pub);
|
num_elem++;
|
||||||
len[2] = wpabuf_len(X_pub) / 2;
|
}
|
||||||
addr[3] = wpabuf_head(Y_pub);
|
addr[num_elem] = wpabuf_head(B_pub);
|
||||||
len[3] = wpabuf_len(Y_pub) / 2;
|
len[num_elem] = wpabuf_len(B_pub) / 2;
|
||||||
if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(X_pub);
|
||||||
|
len[num_elem] = wpabuf_len(X_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
addr[num_elem] = wpabuf_head(Y_pub);
|
||||||
|
len[num_elem] = wpabuf_len(Y_pub) / 2;
|
||||||
|
num_elem++;
|
||||||
|
if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
|
||||||
|
< 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
|
peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
|
||||||
|
@ -293,87 +293,12 @@ static int check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq, int start,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns:
|
|
||||||
* 0: no impact
|
|
||||||
* 1: overlapping BSS
|
|
||||||
* 2: overlapping BSS with 40 MHz intolerant advertisement
|
|
||||||
*/
|
|
||||||
int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq)
|
|
||||||
{
|
|
||||||
int affected_start, affected_end;
|
|
||||||
struct ieee802_11_elems elems;
|
|
||||||
int pri_chan, sec_chan;
|
|
||||||
int pri = bss->freq;
|
|
||||||
int sec = pri;
|
|
||||||
|
|
||||||
if (pri_freq == sec_freq)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
affected_start = (pri_freq + sec_freq) / 2 - 25;
|
|
||||||
affected_end = (pri_freq + sec_freq) / 2 + 25;
|
|
||||||
|
|
||||||
/* Check for overlapping 20 MHz BSS */
|
|
||||||
if (check_20mhz_bss(bss, pri_freq, affected_start, affected_end)) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Overlapping 20 MHz BSS is found");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_pri_sec_chan(bss, &pri_chan, &sec_chan);
|
|
||||||
|
|
||||||
if (sec_chan) {
|
|
||||||
if (sec_chan < pri_chan)
|
|
||||||
sec = pri - 20;
|
|
||||||
else
|
|
||||||
sec = pri + 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pri < affected_start || pri > affected_end) &&
|
|
||||||
(sec < affected_start || sec > affected_end))
|
|
||||||
return 0; /* not within affected channel range */
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
|
|
||||||
" freq=%d pri=%d sec=%d",
|
|
||||||
MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
|
|
||||||
|
|
||||||
if (sec_chan) {
|
|
||||||
if (pri_freq != pri || sec_freq != sec) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"40 MHz pri/sec mismatch with BSS "
|
|
||||||
MACSTR
|
|
||||||
" <%d,%d> (chan=%d%c) vs. <%d,%d>",
|
|
||||||
MAC2STR(bss->bssid),
|
|
||||||
pri, sec, pri_chan,
|
|
||||||
sec > pri ? '+' : '-',
|
|
||||||
pri_freq, sec_freq);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
|
|
||||||
if (elems.ht_capabilities) {
|
|
||||||
struct ieee80211_ht_capabilities *ht_cap =
|
|
||||||
(struct ieee80211_ht_capabilities *)
|
|
||||||
elems.ht_capabilities;
|
|
||||||
|
|
||||||
if (le_to_host16(ht_cap->ht_capabilities_info) &
|
|
||||||
HT_CAP_INFO_40MHZ_INTOLERANT) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"40 MHz Intolerant is set on channel %d in BSS "
|
|
||||||
MACSTR, pri, MAC2STR(bss->bssid));
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
||||||
struct wpa_scan_results *scan_res, int pri_chan,
|
struct wpa_scan_results *scan_res, int pri_chan,
|
||||||
int sec_chan)
|
int sec_chan)
|
||||||
{
|
{
|
||||||
int pri_freq, sec_freq;
|
int pri_freq, sec_freq;
|
||||||
|
int affected_start, affected_end;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (!mode || !scan_res || !pri_chan || !sec_chan ||
|
if (!mode || !scan_res || !pri_chan || !sec_chan ||
|
||||||
@ -383,12 +308,70 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
|||||||
pri_freq = hw_get_freq(mode, pri_chan);
|
pri_freq = hw_get_freq(mode, pri_chan);
|
||||||
sec_freq = hw_get_freq(mode, sec_chan);
|
sec_freq = hw_get_freq(mode, sec_chan);
|
||||||
|
|
||||||
|
affected_start = (pri_freq + sec_freq) / 2 - 25;
|
||||||
|
affected_end = (pri_freq + sec_freq) / 2 + 25;
|
||||||
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
|
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
|
||||||
(pri_freq + sec_freq) / 2 - 25,
|
affected_start, affected_end);
|
||||||
(pri_freq + sec_freq) / 2 + 25);
|
|
||||||
for (i = 0; i < scan_res->num; i++) {
|
for (i = 0; i < scan_res->num; i++) {
|
||||||
if (check_bss_coex_40mhz(scan_res->res[i], pri_freq, sec_freq))
|
struct wpa_scan_res *bss = scan_res->res[i];
|
||||||
|
int pri = bss->freq;
|
||||||
|
int sec = pri;
|
||||||
|
struct ieee802_11_elems elems;
|
||||||
|
|
||||||
|
/* Check for overlapping 20 MHz BSS */
|
||||||
|
if (check_20mhz_bss(bss, pri_freq, affected_start,
|
||||||
|
affected_end)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Overlapping 20 MHz BSS is found");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_pri_sec_chan(bss, &pri_chan, &sec_chan);
|
||||||
|
|
||||||
|
if (sec_chan) {
|
||||||
|
if (sec_chan < pri_chan)
|
||||||
|
sec = pri - 20;
|
||||||
|
else
|
||||||
|
sec = pri + 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pri < affected_start || pri > affected_end) &&
|
||||||
|
(sec < affected_start || sec > affected_end))
|
||||||
|
continue; /* not within affected channel range */
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
|
||||||
|
" freq=%d pri=%d sec=%d",
|
||||||
|
MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
|
||||||
|
|
||||||
|
if (sec_chan) {
|
||||||
|
if (pri_freq != pri || sec_freq != sec) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"40 MHz pri/sec mismatch with BSS "
|
||||||
|
MACSTR
|
||||||
|
" <%d,%d> (chan=%d%c) vs. <%d,%d>",
|
||||||
|
MAC2STR(bss->bssid),
|
||||||
|
pri, sec, pri_chan,
|
||||||
|
sec > pri ? '+' : '-',
|
||||||
|
pri_freq, sec_freq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
|
||||||
|
0);
|
||||||
|
if (elems.ht_capabilities) {
|
||||||
|
struct ieee80211_ht_capabilities *ht_cap =
|
||||||
|
(struct ieee80211_ht_capabilities *)
|
||||||
|
elems.ht_capabilities;
|
||||||
|
|
||||||
|
if (le_to_host16(ht_cap->ht_capabilities_info) &
|
||||||
|
HT_CAP_INFO_40MHZ_INTOLERANT) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"40 MHz Intolerant is set on channel %d in BSS "
|
||||||
|
MACSTR, pri, MAC2STR(bss->bssid));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -32,7 +32,6 @@ void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan);
|
|||||||
int check_40mhz_5g(struct wpa_scan_results *scan_res,
|
int check_40mhz_5g(struct wpa_scan_results *scan_res,
|
||||||
struct hostapd_channel_data *pri_chan,
|
struct hostapd_channel_data *pri_chan,
|
||||||
struct hostapd_channel_data *sec_chan);
|
struct hostapd_channel_data *sec_chan);
|
||||||
int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq);
|
|
||||||
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
|
||||||
struct wpa_scan_results *scan_res, int pri_chan,
|
struct wpa_scan_results *scan_res, int pri_chan,
|
||||||
int sec_chan);
|
int sec_chan);
|
||||||
|
@ -622,7 +622,14 @@ enum qca_radiotap_vendor_ids {
|
|||||||
* This new command is alternative to existing command
|
* This new command is alternative to existing command
|
||||||
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
|
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
|
||||||
* is using stream of bytes instead of structured data using vendor
|
* is using stream of bytes instead of structured data using vendor
|
||||||
* attributes.
|
* attributes. User space sends unsafe frequency ranges to the driver using
|
||||||
|
* a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On
|
||||||
|
* reception of this command, the driver shall check if an interface is
|
||||||
|
* operating on an unsafe frequency and the driver shall try to move to a
|
||||||
|
* safe channel when needed. If the driver is not able to find a safe
|
||||||
|
* channel the interface can keep operating on an unsafe channel with the
|
||||||
|
* TX power limit derived based on internal configurations like
|
||||||
|
* regulatory/SAR rules.
|
||||||
*
|
*
|
||||||
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
|
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
|
||||||
* add the STA node details in driver/firmware. Attributes for this event
|
* add the STA node details in driver/firmware. Attributes for this event
|
||||||
@ -10316,20 +10323,48 @@ enum qca_wlan_vendor_attr_oem_data_params {
|
|||||||
*
|
*
|
||||||
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
|
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
|
||||||
* Nested attribute containing multiple ranges with following attributes:
|
* Nested attribute containing multiple ranges with following attributes:
|
||||||
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
|
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
|
||||||
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
|
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and
|
||||||
|
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM.
|
||||||
*
|
*
|
||||||
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
|
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
|
||||||
* Starting center frequency in MHz.
|
* Starting center frequency in MHz.
|
||||||
*
|
*
|
||||||
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
|
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
|
||||||
* Ending center frequency in MHz.
|
* Ending center frequency in MHz.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM:
|
||||||
|
* s32 attribute, optional. It is a per frequency range attribute.
|
||||||
|
* The maximum TX power limit from user space is to be applied on an
|
||||||
|
* unrestricted interface for corresponding frequency range. It is also
|
||||||
|
* possible that the actual TX power may be even lower than this cap due to
|
||||||
|
* other considerations such as regulatory compliance, SAR, etc. In absence of
|
||||||
|
* this attribute the driver shall follow current behavior which means
|
||||||
|
* interface (SAP/P2P) function can keep operating on an unsafe channel with TX
|
||||||
|
* power derived by the driver based on regulatory/SAR during interface up.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK:
|
||||||
|
* u32 attribute, optional. Indicates all the interface types which are
|
||||||
|
* restricted for all frequency ranges provided in
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
|
||||||
|
* This attribute encapsulates bitmasks of interface types defined in
|
||||||
|
* enum nl80211_iftype. If an interface is marked as restricted the driver must
|
||||||
|
* move to a safe channel and if no safe channel is available the driver shall
|
||||||
|
* terminate that interface functionality. In absence of this attribute,
|
||||||
|
* interface (SAP/P2P) can still continue operating on an unsafe channel with
|
||||||
|
* TX power limit derived from either
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
|
||||||
|
* regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
|
||||||
|
* is not provided.
|
||||||
*/
|
*/
|
||||||
enum qca_wlan_vendor_attr_avoid_frequency_ext {
|
enum qca_wlan_vendor_attr_avoid_frequency_ext {
|
||||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
|
||||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
|
||||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
|
||||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
|
||||||
|
|
||||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
|
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
|
||||||
|
@ -1590,6 +1590,7 @@ struct wpa_driver_mesh_bss_params {
|
|||||||
#define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
|
#define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
|
||||||
#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
|
#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
|
||||||
#define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010
|
#define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010
|
||||||
|
#define WPA_DRIVER_MESH_CONF_FLAG_FORWARDING 0x00000020
|
||||||
/*
|
/*
|
||||||
* TODO: Other mesh configuration parameters would go here.
|
* TODO: Other mesh configuration parameters would go here.
|
||||||
* See NL80211_MESHCONF_* for all the mesh config parameters.
|
* See NL80211_MESHCONF_* for all the mesh config parameters.
|
||||||
@ -1599,6 +1600,7 @@ struct wpa_driver_mesh_bss_params {
|
|||||||
int peer_link_timeout;
|
int peer_link_timeout;
|
||||||
int max_peer_links;
|
int max_peer_links;
|
||||||
int rssi_threshold;
|
int rssi_threshold;
|
||||||
|
int forwarding;
|
||||||
u16 ht_opmode;
|
u16 ht_opmode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10475,6 +10475,9 @@ static int nl80211_put_mesh_config(struct nl_msg *msg,
|
|||||||
if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
|
if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
|
||||||
nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
|
nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
|
||||||
params->auto_plinks)) ||
|
params->auto_plinks)) ||
|
||||||
|
((params->flags & WPA_DRIVER_MESH_CONF_FLAG_FORWARDING) &&
|
||||||
|
nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
|
||||||
|
params->forwarding)) ||
|
||||||
((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
|
((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
|
||||||
nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
|
nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
|
||||||
params->max_peer_links)) ||
|
params->max_peer_links)) ||
|
||||||
|
49
contrib/wpa/tests/hwsim/test_dpp3.py
Normal file
49
contrib/wpa/tests/hwsim/test_dpp3.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Test cases for Device Provisioning Protocol (DPP) version 3
|
||||||
|
# Copyright (c) 2021, Qualcomm Innovation Center, Inc.
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
from test_dpp import check_dpp_capab, run_dpp_auto_connect
|
||||||
|
|
||||||
|
def test_dpp_network_intro_version(dev, apdev):
|
||||||
|
"""DPP Network Introduction and protocol version"""
|
||||||
|
check_dpp_capab(dev[0], min_ver=3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
id, hapd = run_dpp_auto_connect(dev, apdev, 1, stop_after_prov=True)
|
||||||
|
dev[0].select_network(id, freq=2412)
|
||||||
|
dev[0].wait_connected()
|
||||||
|
finally:
|
||||||
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||||
|
|
||||||
|
def test_dpp_network_intro_version_change(dev, apdev):
|
||||||
|
"""DPP Network Introduction and protocol version change"""
|
||||||
|
check_dpp_capab(dev[0], min_ver=3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("dpp_version_override", "2")
|
||||||
|
id, hapd = run_dpp_auto_connect(dev, apdev, 1, stop_after_prov=True)
|
||||||
|
dev[0].set("dpp_version_override", "3")
|
||||||
|
dev[0].select_network(id, freq=2412)
|
||||||
|
dev[0].wait_connected()
|
||||||
|
finally:
|
||||||
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||||
|
|
||||||
|
def test_dpp_network_intro_version_missing_req(dev, apdev):
|
||||||
|
"""DPP Network Introduction and protocol version missing from request"""
|
||||||
|
check_dpp_capab(dev[0], min_ver=3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("dpp_version_override", "2")
|
||||||
|
id, hapd = run_dpp_auto_connect(dev, apdev, 1, stop_after_prov=True)
|
||||||
|
dev[0].set("dpp_version_override", "3")
|
||||||
|
dev[0].set("dpp_test", "92")
|
||||||
|
dev[0].select_network(id, freq=2412)
|
||||||
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=10)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("DPP network introduction result not seen on STA")
|
||||||
|
if "status=8" not in ev:
|
||||||
|
raise Exception("Unexpected network introduction result on STA: " + ev)
|
||||||
|
finally:
|
||||||
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
@ -279,6 +279,9 @@ NEED_ASN1=y
|
|||||||
ifdef CONFIG_DPP2
|
ifdef CONFIG_DPP2
|
||||||
L_CFLAGS += -DCONFIG_DPP2
|
L_CFLAGS += -DCONFIG_DPP2
|
||||||
endif
|
endif
|
||||||
|
ifdef CONFIG_DPP3
|
||||||
|
L_CFLAGS += -DCONFIG_DPP3
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_OWE
|
ifdef CONFIG_OWE
|
||||||
|
@ -294,6 +294,9 @@ NEED_ASN1=y
|
|||||||
ifdef CONFIG_DPP2
|
ifdef CONFIG_DPP2
|
||||||
CFLAGS += -DCONFIG_DPP2
|
CFLAGS += -DCONFIG_DPP2
|
||||||
endif
|
endif
|
||||||
|
ifdef CONFIG_DPP3
|
||||||
|
CFLAGS += -DCONFIG_DPP3
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_OWE
|
ifdef CONFIG_OWE
|
||||||
|
@ -286,6 +286,12 @@ Credentials can be pre-configured for automatic network selection:
|
|||||||
#
|
#
|
||||||
# sim_num: Identifier for which SIM to use in multi-SIM devices
|
# sim_num: Identifier for which SIM to use in multi-SIM devices
|
||||||
#
|
#
|
||||||
|
# engine: Whether to use an engine for private key operations (0/1)
|
||||||
|
# engine_id: String identifying the engine to use
|
||||||
|
# ca_cert_id: The CA certificate identifier when using an engine
|
||||||
|
# cert_id: The certificate identifier when using an engine
|
||||||
|
# key_id: The private key identifier when using an engine
|
||||||
|
#
|
||||||
# for example:
|
# for example:
|
||||||
#
|
#
|
||||||
#cred={
|
#cred={
|
||||||
|
@ -2527,6 +2527,7 @@ static const struct parse_data ssid_fields[] = {
|
|||||||
#ifdef CONFIG_MESH
|
#ifdef CONFIG_MESH
|
||||||
{ INT_RANGE(mode, 0, 5) },
|
{ INT_RANGE(mode, 0, 5) },
|
||||||
{ INT_RANGE(no_auto_peer, 0, 1) },
|
{ INT_RANGE(no_auto_peer, 0, 1) },
|
||||||
|
{ INT_RANGE(mesh_fwding, 0, 1) },
|
||||||
{ INT_RANGE(mesh_rssi_threshold, -255, 1) },
|
{ INT_RANGE(mesh_rssi_threshold, -255, 1) },
|
||||||
#else /* CONFIG_MESH */
|
#else /* CONFIG_MESH */
|
||||||
{ INT_RANGE(mode, 0, 4) },
|
{ INT_RANGE(mode, 0, 4) },
|
||||||
@ -2855,6 +2856,10 @@ void wpa_config_free_cred(struct wpa_cred *cred)
|
|||||||
os_free(cred->client_cert);
|
os_free(cred->client_cert);
|
||||||
os_free(cred->private_key);
|
os_free(cred->private_key);
|
||||||
str_clear_free(cred->private_key_passwd);
|
str_clear_free(cred->private_key_passwd);
|
||||||
|
os_free(cred->engine_id);
|
||||||
|
os_free(cred->ca_cert_id);
|
||||||
|
os_free(cred->cert_id);
|
||||||
|
os_free(cred->key_id);
|
||||||
os_free(cred->imsi);
|
os_free(cred->imsi);
|
||||||
str_clear_free(cred->milenage);
|
str_clear_free(cred->milenage);
|
||||||
for (i = 0; i < cred->num_domain; i++)
|
for (i = 0; i < cred->num_domain; i++)
|
||||||
@ -3107,6 +3112,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
|
|||||||
ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
|
ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
|
||||||
ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
|
ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
|
||||||
ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
|
ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
|
||||||
|
ssid->mesh_fwding = DEFAULT_MESH_FWDING;
|
||||||
ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
|
ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
#ifdef CONFIG_HT_OVERRIDES
|
#ifdef CONFIG_HT_OVERRIDES
|
||||||
@ -3618,6 +3624,11 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "engine") == 0) {
|
||||||
|
cred->engine = atoi(value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
val = wpa_config_parse_string(value, &len);
|
val = wpa_config_parse_string(value, &len);
|
||||||
if (val == NULL ||
|
if (val == NULL ||
|
||||||
(os_strcmp(var, "excluded_ssid") != 0 &&
|
(os_strcmp(var, "excluded_ssid") != 0 &&
|
||||||
@ -3673,6 +3684,30 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "engine_id") == 0) {
|
||||||
|
os_free(cred->engine_id);
|
||||||
|
cred->engine_id = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "ca_cert_id") == 0) {
|
||||||
|
os_free(cred->ca_cert_id);
|
||||||
|
cred->ca_cert_id = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "cert_id") == 0) {
|
||||||
|
os_free(cred->cert_id);
|
||||||
|
cred->cert_id = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(var, "key_id") == 0) {
|
||||||
|
os_free(cred->key_id);
|
||||||
|
cred->key_id = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (os_strcmp(var, "imsi") == 0) {
|
if (os_strcmp(var, "imsi") == 0) {
|
||||||
os_free(cred->imsi);
|
os_free(cred->imsi);
|
||||||
cred->imsi = val;
|
cred->imsi = val;
|
||||||
@ -4349,6 +4384,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
|
|||||||
config->user_mpm = DEFAULT_USER_MPM;
|
config->user_mpm = DEFAULT_USER_MPM;
|
||||||
config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
|
config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
|
||||||
config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
|
config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
|
||||||
|
config->mesh_fwding = DEFAULT_MESH_FWDING;
|
||||||
config->dot11RSNASAERetransPeriod =
|
config->dot11RSNASAERetransPeriod =
|
||||||
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
|
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
|
||||||
config->fast_reauth = DEFAULT_FAST_REAUTH;
|
config->fast_reauth = DEFAULT_FAST_REAUTH;
|
||||||
@ -5062,6 +5098,7 @@ static const struct global_parse_data global_fields[] = {
|
|||||||
{ INT(user_mpm), 0 },
|
{ INT(user_mpm), 0 },
|
||||||
{ INT_RANGE(max_peer_links, 0, 255), 0 },
|
{ INT_RANGE(max_peer_links, 0, 255), 0 },
|
||||||
{ INT(mesh_max_inactivity), 0 },
|
{ INT(mesh_max_inactivity), 0 },
|
||||||
|
{ INT_RANGE(mesh_fwding, 0, 1), 0 },
|
||||||
{ INT(dot11RSNASAERetransPeriod), 0 },
|
{ INT(dot11RSNASAERetransPeriod), 0 },
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
{ INT(disable_scan_offload), 0 },
|
{ INT(disable_scan_offload), 0 },
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#define DEFAULT_USER_MPM 1
|
#define DEFAULT_USER_MPM 1
|
||||||
#define DEFAULT_MAX_PEER_LINKS 99
|
#define DEFAULT_MAX_PEER_LINKS 99
|
||||||
#define DEFAULT_MESH_MAX_INACTIVITY 300
|
#define DEFAULT_MESH_MAX_INACTIVITY 300
|
||||||
|
#define DEFAULT_MESH_FWDING 1
|
||||||
/*
|
/*
|
||||||
* The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard,
|
* The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard,
|
||||||
* but use 1000 ms in practice to avoid issues on low power CPUs.
|
* but use 1000 ms in practice to avoid issues on low power CPUs.
|
||||||
@ -179,6 +180,31 @@ struct wpa_cred {
|
|||||||
*/
|
*/
|
||||||
char *milenage;
|
char *milenage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* engine - Use an engine for private key operations
|
||||||
|
*/
|
||||||
|
int engine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* engine_id - String identifying the engine to use
|
||||||
|
*/
|
||||||
|
char *engine_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ca_cert_id - The CA certificate identifier when using an engine
|
||||||
|
*/
|
||||||
|
char *ca_cert_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cert_id - The certificate identifier when using an engine
|
||||||
|
*/
|
||||||
|
char *cert_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key_id - The private key identifier when using an engine
|
||||||
|
*/
|
||||||
|
char *key_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* domain_suffix_match - Constraint for server domain name
|
* domain_suffix_match - Constraint for server domain name
|
||||||
*
|
*
|
||||||
@ -1388,6 +1414,14 @@ struct wpa_config {
|
|||||||
*/
|
*/
|
||||||
int mesh_max_inactivity;
|
int mesh_max_inactivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mesh_fwding - Mesh network layer-2 forwarding (dot11MeshForwarding)
|
||||||
|
*
|
||||||
|
* This controls whether to enable layer-2 forwarding.
|
||||||
|
* By default: 1: enabled
|
||||||
|
*/
|
||||||
|
int mesh_fwding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame
|
* dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame
|
||||||
*
|
*
|
||||||
|
@ -769,6 +769,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
|||||||
#endif /* IEEE8021X_EAPOL */
|
#endif /* IEEE8021X_EAPOL */
|
||||||
INT(mode);
|
INT(mode);
|
||||||
INT(no_auto_peer);
|
INT(no_auto_peer);
|
||||||
|
INT(mesh_fwding);
|
||||||
INT(frequency);
|
INT(frequency);
|
||||||
INT(enable_edmg);
|
INT(enable_edmg);
|
||||||
INT(edmg_channel);
|
INT(edmg_channel);
|
||||||
@ -1026,6 +1027,17 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
|
|||||||
|
|
||||||
if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
|
if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
|
||||||
fprintf(f, "\tsim_num=%d\n", cred->sim_num);
|
fprintf(f, "\tsim_num=%d\n", cred->sim_num);
|
||||||
|
|
||||||
|
if (cred->engine)
|
||||||
|
fprintf(f, "\tengine=%d\n", cred->engine);
|
||||||
|
if (cred->engine_id)
|
||||||
|
fprintf(f, "\tengine_id=\"%s\"\n", cred->engine_id);
|
||||||
|
if (cred->key_id)
|
||||||
|
fprintf(f, "\tkey_id=\"%s\"\n", cred->key_id);
|
||||||
|
if (cred->cert_id)
|
||||||
|
fprintf(f, "\tcert_id=\"%s\"\n", cred->cert_id);
|
||||||
|
if (cred->ca_cert_id)
|
||||||
|
fprintf(f, "\tca_cert_id=\"%s\"\n", cred->ca_cert_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1462,6 +1474,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
|
|||||||
fprintf(f, "mesh_max_inactivity=%d\n",
|
fprintf(f, "mesh_max_inactivity=%d\n",
|
||||||
config->mesh_max_inactivity);
|
config->mesh_max_inactivity);
|
||||||
|
|
||||||
|
if (config->mesh_fwding != DEFAULT_MESH_FWDING)
|
||||||
|
fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding);
|
||||||
|
|
||||||
if (config->dot11RSNASAERetransPeriod !=
|
if (config->dot11RSNASAERetransPeriod !=
|
||||||
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
|
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
|
||||||
fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
|
fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
|
||||||
|
@ -549,6 +549,11 @@ struct wpa_ssid {
|
|||||||
int dot11MeshConfirmTimeout; /* msec */
|
int dot11MeshConfirmTimeout; /* msec */
|
||||||
int dot11MeshHoldingTimeout; /* msec */
|
int dot11MeshHoldingTimeout; /* msec */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mesh network layer-2 forwarding (dot11MeshForwarding)
|
||||||
|
*/
|
||||||
|
int mesh_fwding;
|
||||||
|
|
||||||
int ht;
|
int ht;
|
||||||
int ht40;
|
int ht40;
|
||||||
|
|
||||||
|
@ -3793,47 +3793,6 @@ static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
|
|
||||||
struct wpa_cred *cred)
|
|
||||||
{
|
|
||||||
struct wpa_ssid *ssid;
|
|
||||||
char str[20];
|
|
||||||
int id;
|
|
||||||
|
|
||||||
if (cred == NULL) {
|
|
||||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = cred->id;
|
|
||||||
if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
|
|
||||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
|
|
||||||
|
|
||||||
/* Remove any network entry created based on the removed credential */
|
|
||||||
ssid = wpa_s->conf->ssid;
|
|
||||||
while (ssid) {
|
|
||||||
if (ssid->parent_cred == cred) {
|
|
||||||
int res;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "Remove network id %d since it "
|
|
||||||
"used the removed credential", ssid->id);
|
|
||||||
res = os_snprintf(str, sizeof(str), "%d", ssid->id);
|
|
||||||
if (os_snprintf_error(sizeof(str), res))
|
|
||||||
str[sizeof(str) - 1] = '\0';
|
|
||||||
ssid = ssid->next;
|
|
||||||
wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
|
|
||||||
} else
|
|
||||||
ssid = ssid->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
||||||
char *cmd)
|
char *cmd)
|
||||||
{
|
{
|
||||||
@ -3844,13 +3803,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
|||||||
* "provisioning_sp=<FQDN> */
|
* "provisioning_sp=<FQDN> */
|
||||||
if (os_strcmp(cmd, "all") == 0) {
|
if (os_strcmp(cmd, "all") == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
|
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
|
||||||
cred = wpa_s->conf->cred;
|
return wpas_remove_all_creds(wpa_s);
|
||||||
while (cred) {
|
|
||||||
prev = cred;
|
|
||||||
cred = cred->next;
|
|
||||||
wpas_ctrl_remove_cred(wpa_s, prev);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
|
if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
|
||||||
@ -3866,7 +3819,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
|||||||
if (os_strcmp(prev->domain[i], cmd + 8)
|
if (os_strcmp(prev->domain[i], cmd + 8)
|
||||||
!= 0)
|
!= 0)
|
||||||
continue;
|
continue;
|
||||||
wpas_ctrl_remove_cred(wpa_s, prev);
|
wpas_remove_cred(wpa_s, prev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3883,7 +3836,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
|||||||
cred = cred->next;
|
cred = cred->next;
|
||||||
if (prev->provisioning_sp &&
|
if (prev->provisioning_sp &&
|
||||||
os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
|
os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
|
||||||
wpas_ctrl_remove_cred(wpa_s, prev);
|
wpas_remove_cred(wpa_s, prev);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3892,7 +3845,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
|||||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
|
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
|
||||||
|
|
||||||
cred = wpa_config_get_cred(wpa_s->conf, id);
|
cred = wpa_config_get_cred(wpa_s->conf, id);
|
||||||
return wpas_ctrl_remove_cred(wpa_s, cred);
|
return wpas_remove_cred(wpa_s, cred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4826,7 +4779,9 @@ static int wpa_supplicant_ctrl_iface_get_capability(
|
|||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
if (os_strcmp(field, "dpp") == 0) {
|
if (os_strcmp(field, "dpp") == 0) {
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP3
|
||||||
|
res = os_snprintf(buf, buflen, "DPP=3");
|
||||||
|
#elif defined(CONFIG_DPP2)
|
||||||
res = os_snprintf(buf, buflen, "DPP=2");
|
res = os_snprintf(buf, buflen, "DPP=2");
|
||||||
#else /* CONFIG_DPP2 */
|
#else /* CONFIG_DPP2 */
|
||||||
res = os_snprintf(buf, buflen, "DPP=1");
|
res = os_snprintf(buf, buflen, "DPP=1");
|
||||||
@ -8477,7 +8432,9 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
|
|||||||
dpp_pkex_ephemeral_key_override_len = 0;
|
dpp_pkex_ephemeral_key_override_len = 0;
|
||||||
dpp_protocol_key_override_len = 0;
|
dpp_protocol_key_override_len = 0;
|
||||||
dpp_nonce_override_len = 0;
|
dpp_nonce_override_len = 0;
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP3
|
||||||
|
dpp_version_override = 3;
|
||||||
|
#elif defined(CONFIG_DPP2)
|
||||||
dpp_version_override = 2;
|
dpp_version_override = 2;
|
||||||
#else /* CONFIG_DPP2 */
|
#else /* CONFIG_DPP2 */
|
||||||
dpp_version_override = 1;
|
dpp_version_override = 1;
|
||||||
|
@ -937,6 +937,95 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
|||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
|
||||||
|
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss,
|
||||||
|
struct wpa_cred *cred,
|
||||||
|
const char *type,
|
||||||
|
int excluded,
|
||||||
|
int bh,
|
||||||
|
int bss_load,
|
||||||
|
int conn_capab)
|
||||||
|
{
|
||||||
|
struct wpas_dbus_priv *iface;
|
||||||
|
DBusMessage *msg;
|
||||||
|
DBusMessageIter iter, dict_iter;
|
||||||
|
char bss_path[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path;
|
||||||
|
char cred_path[WPAS_DBUS_OBJECT_PATH_MAX], *cred_obj_path;
|
||||||
|
|
||||||
|
iface = wpa_s->global->dbus;
|
||||||
|
|
||||||
|
/* Do nothing if the control interface is not turned on */
|
||||||
|
if (!iface || !wpa_s->dbus_new_path)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg = dbus_message_new_signal(wpa_s->dbus_new_path,
|
||||||
|
WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
"InterworkingAPAdded");
|
||||||
|
if (!msg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
os_snprintf(bss_path, WPAS_DBUS_OBJECT_PATH_MAX,
|
||||||
|
"%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
|
||||||
|
wpa_s->dbus_new_path, bss->id);
|
||||||
|
bss_obj_path = bss_path;
|
||||||
|
|
||||||
|
os_snprintf(cred_path, WPAS_DBUS_OBJECT_PATH_MAX,
|
||||||
|
"%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%u",
|
||||||
|
wpa_s->dbus_new_path, cred->id);
|
||||||
|
cred_obj_path = cred_path;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(msg, &iter);
|
||||||
|
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
|
||||||
|
&bss_obj_path) ||
|
||||||
|
!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
|
||||||
|
&cred_obj_path) ||
|
||||||
|
!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
|
||||||
|
!wpa_dbus_dict_append_string(&dict_iter, "type", type) ||
|
||||||
|
!wpa_dbus_dict_append_int32(&dict_iter, "excluded", excluded) ||
|
||||||
|
!wpa_dbus_dict_append_int32(&dict_iter, "priority",
|
||||||
|
cred->priority) ||
|
||||||
|
!wpa_dbus_dict_append_int32(&dict_iter, "sp_priority",
|
||||||
|
cred->sp_priority) ||
|
||||||
|
!wpa_dbus_dict_append_int32(&dict_iter, "below_min_backhaul", bh) ||
|
||||||
|
!wpa_dbus_dict_append_int32(&dict_iter, "over_max_bss_load",
|
||||||
|
bss_load) ||
|
||||||
|
!wpa_dbus_dict_append_int32(&dict_iter, "conn_capab_missing",
|
||||||
|
conn_capab) ||
|
||||||
|
!wpa_dbus_dict_close_write(&iter, &dict_iter))
|
||||||
|
wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
|
||||||
|
else
|
||||||
|
dbus_connection_send(iface->con, msg, NULL);
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpas_dbus_priv *iface;
|
||||||
|
DBusMessage *msg;
|
||||||
|
|
||||||
|
iface = wpa_s->global->dbus;
|
||||||
|
|
||||||
|
/* Do nothing if the control interface is not turned on */
|
||||||
|
if (!iface || !wpa_s->dbus_new_path)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg = dbus_message_new_signal(wpa_s->dbus_new_path,
|
||||||
|
WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
"InterworkingSelectDone");
|
||||||
|
if (!msg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dbus_connection_send(iface->con, msg, NULL);
|
||||||
|
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
|
|
||||||
void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
|
void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
|
||||||
int depth, const char *subject,
|
int depth, const char *subject,
|
||||||
const char *altsubject[],
|
const char *altsubject[],
|
||||||
@ -3570,6 +3659,35 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
|
|||||||
END_ARGS
|
END_ARGS
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
{ "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
(WPADBusMethodHandler) wpas_dbus_handler_add_cred,
|
||||||
|
{
|
||||||
|
{ "args", "a{sv}", ARG_IN },
|
||||||
|
{ "path", "o", ARG_OUT },
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
(WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
|
||||||
|
{
|
||||||
|
{ "path", "o", ARG_IN },
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
(WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
|
||||||
|
{
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
(WPADBusMethodHandler) wpas_dbus_handler_interworking_select,
|
||||||
|
{
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
{ NULL, NULL, NULL, { END_ARGS } }
|
{ NULL, NULL, NULL, { END_ARGS } }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4137,6 +4255,21 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
{ "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
{
|
||||||
|
{ "bss", "o", ARG_OUT },
|
||||||
|
{ "cred", "o", ARG_OUT },
|
||||||
|
{ "properties", "a{sv}", ARG_OUT },
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
{
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
{ NULL, NULL, { END_ARGS } }
|
{ NULL, NULL, { END_ARGS } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
struct wpa_global;
|
struct wpa_global;
|
||||||
struct wpa_supplicant;
|
struct wpa_supplicant;
|
||||||
struct wpa_ssid;
|
struct wpa_ssid;
|
||||||
|
struct wpa_cred;
|
||||||
|
struct wpa_bss;
|
||||||
struct wps_event_m2d;
|
struct wps_event_m2d;
|
||||||
struct wps_event_fail;
|
struct wps_event_fail;
|
||||||
struct wps_credential;
|
struct wps_credential;
|
||||||
@ -96,6 +98,9 @@ enum wpas_dbus_sta_prop {
|
|||||||
#define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers"
|
#define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers"
|
||||||
#define WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
|
#define WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
|
||||||
|
|
||||||
|
#define WPAS_DBUS_NEW_CREDENTIALS_PART "Credentials"
|
||||||
|
#define WPAS_DBUS_NEW_IFACE_CREDENTIAL WPAS_DBUS_NEW_INTERFACE ".Credential"
|
||||||
|
|
||||||
/* Top-level Errors */
|
/* Top-level Errors */
|
||||||
#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
|
#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
|
||||||
WPAS_DBUS_NEW_INTERFACE ".UnknownError"
|
WPAS_DBUS_NEW_INTERFACE ".UnknownError"
|
||||||
@ -264,6 +269,13 @@ void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
|
|||||||
const u8 *peer_addr);
|
const u8 *peer_addr);
|
||||||
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *peer_addr, int reason);
|
const u8 *peer_addr, int reason);
|
||||||
|
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss,
|
||||||
|
struct wpa_cred *cred,
|
||||||
|
const char *type, int excluded,
|
||||||
|
int bh, int bss_load,
|
||||||
|
int conn_capab);
|
||||||
|
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||||
|
|
||||||
@ -616,6 +628,21 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss,
|
||||||
|
struct wpa_cred *cred,
|
||||||
|
const char *type, int excluded,
|
||||||
|
int bh, int bss_load,
|
||||||
|
int conn_capab)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||||
|
|
||||||
#endif /* CTRL_IFACE_DBUS_H_NEW */
|
#endif /* CTRL_IFACE_DBUS_H_NEW */
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "../scan.h"
|
#include "../scan.h"
|
||||||
#include "../autoscan.h"
|
#include "../autoscan.h"
|
||||||
#include "../ap.h"
|
#include "../ap.h"
|
||||||
|
#include "../interworking.h"
|
||||||
#include "dbus_new_helpers.h"
|
#include "dbus_new_helpers.h"
|
||||||
#include "dbus_new.h"
|
#include "dbus_new.h"
|
||||||
#include "dbus_new_handlers.h"
|
#include "dbus_new_handlers.h"
|
||||||
@ -148,6 +149,9 @@ static const char * const dont_quote[] = {
|
|||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
|
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
"roaming_consortium", "required_roaming_consortium",
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -328,6 +332,110 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set_cred_properties - Set the properties of a configured credential
|
||||||
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
* @cred: wpa_cred structure for a configured credential
|
||||||
|
* @iter: DBus message iterator containing dictionary of network
|
||||||
|
* properties to set.
|
||||||
|
* @error: On failure, an error describing the failure
|
||||||
|
* Returns: TRUE if the request succeeds, FALSE if it failed
|
||||||
|
*/
|
||||||
|
static dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_cred *cred,
|
||||||
|
DBusMessageIter *iter,
|
||||||
|
DBusError *error)
|
||||||
|
{
|
||||||
|
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
|
||||||
|
DBusMessageIter iter_dict;
|
||||||
|
char *value = NULL;
|
||||||
|
|
||||||
|
if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
|
||||||
|
size_t size = 50;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
value = NULL;
|
||||||
|
if (entry.type == DBUS_TYPE_ARRAY &&
|
||||||
|
entry.array_type == DBUS_TYPE_BYTE) {
|
||||||
|
if (entry.array_len <= 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
size = entry.array_len * 2 + 1;
|
||||||
|
value = os_zalloc(size);
|
||||||
|
if (!value)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = wpa_snprintf_hex(value, size,
|
||||||
|
(u8 *) entry.bytearray_value,
|
||||||
|
entry.array_len);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto error;
|
||||||
|
} else if (entry.type == DBUS_TYPE_STRING) {
|
||||||
|
if (should_quote_opt(entry.key)) {
|
||||||
|
size = os_strlen(entry.str_value);
|
||||||
|
|
||||||
|
size += 3;
|
||||||
|
value = os_zalloc(size);
|
||||||
|
if (!value)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = os_snprintf(value, size, "\"%s\"",
|
||||||
|
entry.str_value);
|
||||||
|
if (os_snprintf_error(size, ret))
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
value = os_strdup(entry.str_value);
|
||||||
|
if (!value)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (entry.type == DBUS_TYPE_UINT32) {
|
||||||
|
value = os_zalloc(size);
|
||||||
|
if (!value)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = os_snprintf(value, size, "%u",
|
||||||
|
entry.uint32_value);
|
||||||
|
if (os_snprintf_error(size, ret))
|
||||||
|
goto error;
|
||||||
|
} else if (entry.type == DBUS_TYPE_INT32) {
|
||||||
|
value = os_zalloc(size);
|
||||||
|
if (!value)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = os_snprintf(value, size, "%d",
|
||||||
|
entry.int32_value);
|
||||||
|
if (os_snprintf_error(size, ret))
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wpa_config_set_cred(cred, entry.key, value, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
os_free(value);
|
||||||
|
value = NULL;
|
||||||
|
wpa_dbus_dict_entry_clear(&entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
os_free(value);
|
||||||
|
wpa_dbus_dict_entry_clear(&entry);
|
||||||
|
dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"invalid message format");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpas_dbus_simple_property_getter - Get basic type property
|
* wpas_dbus_simple_property_getter - Get basic type property
|
||||||
* @iter: Message iter to use when appending arguments
|
* @iter: Message iter to use when appending arguments
|
||||||
@ -1515,6 +1623,185 @@ DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpas_dbus_new_iface_add_cred - Add a new credential
|
||||||
|
* @message: Pointer to incoming dbus message
|
||||||
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
* Returns: A dbus message containing the object path of the new credential
|
||||||
|
*
|
||||||
|
* Handler function for "AddCred" method call of a network interface.
|
||||||
|
*/
|
||||||
|
DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
DBusMessage *reply = NULL;
|
||||||
|
DBusMessageIter iter;
|
||||||
|
struct wpa_cred *cred = NULL;
|
||||||
|
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
|
||||||
|
DBusError error;
|
||||||
|
|
||||||
|
dbus_message_iter_init(message, &iter);
|
||||||
|
|
||||||
|
if (wpa_s->dbus_new_path)
|
||||||
|
cred = wpa_config_add_cred(wpa_s->conf);
|
||||||
|
if (!cred) {
|
||||||
|
wpa_printf(MSG_ERROR, "%s[dbus]: can't add new credential.",
|
||||||
|
__func__);
|
||||||
|
reply = wpas_dbus_error_unknown_error(
|
||||||
|
message,
|
||||||
|
"wpa_supplicant could not add a credential on this interface.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_error_init(&error);
|
||||||
|
if (!set_cred_properties(wpa_s, cred, &iter, &error)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"%s[dbus]: control interface couldn't set credential properties",
|
||||||
|
__func__);
|
||||||
|
reply = wpas_dbus_reply_new_from_error(message, &error,
|
||||||
|
DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Failed to add credential");
|
||||||
|
dbus_error_free(&error);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct the object path for this network. */
|
||||||
|
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
|
||||||
|
"%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%d",
|
||||||
|
wpa_s->dbus_new_path, cred->id);
|
||||||
|
|
||||||
|
reply = dbus_message_new_method_return(message);
|
||||||
|
if (!reply) {
|
||||||
|
reply = wpas_dbus_error_no_memory(message);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
|
||||||
|
DBUS_TYPE_INVALID)) {
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
reply = wpas_dbus_error_no_memory(message);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (cred)
|
||||||
|
wpa_config_remove_cred(wpa_s->conf, cred->id);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpas_dbus_handler_remove_cred - Remove a configured credential
|
||||||
|
* @message: Pointer to incoming dbus message
|
||||||
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
* Returns: NULL on success or dbus error on failure
|
||||||
|
*
|
||||||
|
* Handler function for "RemoveCred" method call of a network interface.
|
||||||
|
*/
|
||||||
|
DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
DBusMessage *reply = NULL;
|
||||||
|
const char *op;
|
||||||
|
char *iface, *cred_id;
|
||||||
|
int id;
|
||||||
|
struct wpa_cred *cred;
|
||||||
|
|
||||||
|
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
|
||||||
|
/* Extract the network ID and ensure the network is actually a child of
|
||||||
|
* this interface */
|
||||||
|
iface = wpas_dbus_new_decompose_object_path(
|
||||||
|
op, WPAS_DBUS_NEW_CREDENTIALS_PART, &cred_id);
|
||||||
|
if (!iface || !cred_id || !wpa_s->dbus_new_path ||
|
||||||
|
os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
|
||||||
|
reply = wpas_dbus_error_invalid_args(message, op);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
id = strtoul(cred_id, NULL, 10);
|
||||||
|
if (errno != 0) {
|
||||||
|
reply = wpas_dbus_error_invalid_args(message, op);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
cred = wpa_config_get_cred(wpa_s->conf, id);
|
||||||
|
if (!cred) {
|
||||||
|
wpa_printf(MSG_ERROR, "%s[dbus]: could not find credential %s",
|
||||||
|
__func__, op);
|
||||||
|
reply = wpas_dbus_error_invalid_args(
|
||||||
|
message, "could not find credential");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpas_remove_cred(wpa_s, cred) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"%s[dbus]: error occurred when removing cred %d",
|
||||||
|
__func__, id);
|
||||||
|
reply = wpas_dbus_error_unknown_error(
|
||||||
|
message,
|
||||||
|
"error removing the specified credential on its interface.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
os_free(iface);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpas_dbus_handler_remove_all_creds - Remove all the configured credentials
|
||||||
|
* @message: Pointer to incoming dbus message
|
||||||
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
* Returns: NULL indicating success or DBus error message on failure
|
||||||
|
*
|
||||||
|
* Handler function for "RemoveAllCreds" method call of a network interface.
|
||||||
|
*/
|
||||||
|
DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
DBusMessage *reply = NULL;
|
||||||
|
|
||||||
|
res = wpas_remove_all_creds(wpa_s);
|
||||||
|
if (res < 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"%s[dbus]: failed to remove all credentials",
|
||||||
|
__func__);
|
||||||
|
reply = wpas_dbus_error_unknown_error(
|
||||||
|
message, "failed to remove all credentials");
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DBusMessage *
|
||||||
|
wpas_dbus_handler_interworking_select(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
DBusMessage *reply = NULL;
|
||||||
|
|
||||||
|
/* Automatic selection is disabled and no constraint on channels */
|
||||||
|
result = interworking_select(wpa_s, 0, NULL);
|
||||||
|
if (result < 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"%s[dbus]: failed to start Interworking selection",
|
||||||
|
__func__);
|
||||||
|
reply = wpas_dbus_error_scan_error(
|
||||||
|
message,
|
||||||
|
"error starting Interworking selection.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpas_dbus_handler_signal_poll - Request immediate signal properties
|
* wpas_dbus_handler_signal_poll - Request immediate signal properties
|
||||||
* @message: Pointer to incoming dbus message
|
* @message: Pointer to incoming dbus message
|
||||||
|
@ -144,6 +144,19 @@ DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
|
|||||||
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
|
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
|
||||||
struct wpa_supplicant *wpa_s);
|
struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
DBusMessage *
|
||||||
|
wpas_dbus_handler_interworking_select(DBusMessage *message,
|
||||||
|
struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
|
DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
|
||||||
DECLARE_ACCESSOR(wpas_dbus_getter_state);
|
DECLARE_ACCESSOR(wpas_dbus_getter_state);
|
||||||
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
|
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
|
||||||
|
@ -744,6 +744,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
|
|||||||
unsigned int group_id = 0;
|
unsigned int group_id = 0;
|
||||||
int persistent = 0;
|
int persistent = 0;
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
|
const char *group_ifname;
|
||||||
|
|
||||||
if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
|
if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
|
||||||
return reply;
|
return reply;
|
||||||
@ -777,6 +778,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
|
|||||||
!p2p_peer_known(wpa_s->global->p2p, peer_addr))
|
!p2p_peer_known(wpa_s->global->p2p, peer_addr))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* Capture the interface name for the group first */
|
||||||
|
group_ifname = wpa_s->ifname;
|
||||||
wpa_s = wpa_s->global->p2p_init_wpa_s;
|
wpa_s = wpa_s->global->p2p_init_wpa_s;
|
||||||
|
|
||||||
if (persistent) {
|
if (persistent) {
|
||||||
@ -821,7 +824,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
|
|||||||
/*
|
/*
|
||||||
* No group ID means propose to a peer to join my active group
|
* No group ID means propose to a peer to join my active group
|
||||||
*/
|
*/
|
||||||
if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
|
if (wpas_p2p_invite_group(wpa_s, group_ifname,
|
||||||
peer_addr, NULL, false)) {
|
peer_addr, NULL, false)) {
|
||||||
reply = wpas_dbus_error_unknown_error(
|
reply = wpas_dbus_error_unknown_error(
|
||||||
message, "Failed to join to an active group");
|
message, "Failed to join to an active group");
|
||||||
|
@ -603,8 +603,13 @@ CONFIG_BGSCAN_SIMPLE=y
|
|||||||
# Experimental implementation of draft-harkins-owe-07.txt
|
# Experimental implementation of draft-harkins-owe-07.txt
|
||||||
#CONFIG_OWE=y
|
#CONFIG_OWE=y
|
||||||
|
|
||||||
# Device Provisioning Protocol (DPP)
|
# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
|
||||||
CONFIG_DPP=y
|
CONFIG_DPP=y
|
||||||
|
# DPP version 2 support
|
||||||
|
CONFIG_DPP2=y
|
||||||
|
# DPP version 3 support (experimental and still changing; do not enable for
|
||||||
|
# production use)
|
||||||
|
#CONFIG_DPP3=y
|
||||||
|
|
||||||
# Wired equivalent privacy (WEP)
|
# Wired equivalent privacy (WEP)
|
||||||
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
|
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
|
||||||
|
@ -1021,6 +1021,7 @@ void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
|
|||||||
wpa_drv_dpp_listen(wpa_s, false);
|
wpa_drv_dpp_listen(wpa_s, false);
|
||||||
wpa_s->dpp_listen_freq = 0;
|
wpa_s->dpp_listen_freq = 0;
|
||||||
wpas_dpp_listen_work_done(wpa_s);
|
wpas_dpp_listen_work_done(wpa_s);
|
||||||
|
radio_remove_works(wpa_s, "dpp-listen", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2462,6 +2463,16 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
|
|||||||
&version_len);
|
&version_len);
|
||||||
if (version && version_len >= 1)
|
if (version && version_len >= 1)
|
||||||
peer_version = version[0];
|
peer_version = version[0];
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
if (intro.peer_version && intro.peer_version >= 2 &&
|
||||||
|
peer_version != intro.peer_version) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"DPP: Protocol version mismatch (Connector: %d Attribute: %d",
|
||||||
|
intro.peer_version, peer_version);
|
||||||
|
wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
entry->dpp_pfs = peer_version >= 2;
|
entry->dpp_pfs = peer_version >= 2;
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
if (expiry) {
|
if (expiry) {
|
||||||
@ -2568,7 +2579,9 @@ static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
|
|||||||
wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
|
wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
|
||||||
pkex->exch_req_tries);
|
pkex->exch_req_tries);
|
||||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
|
||||||
MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
|
MAC2STR(broadcast), pkex->freq,
|
||||||
|
pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||||
|
DPP_PA_PKEX_V1_EXCHANGE_REQ);
|
||||||
offchannel_send_action(wpa_s, pkex->freq, broadcast,
|
offchannel_send_action(wpa_s, pkex->freq, broadcast,
|
||||||
wpa_s->own_addr, broadcast,
|
wpa_s->own_addr, broadcast,
|
||||||
wpabuf_head(pkex->exchange_req),
|
wpabuf_head(pkex->exchange_req),
|
||||||
@ -2627,7 +2640,8 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
|
wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
const u8 *buf, size_t len, unsigned int freq)
|
const u8 *buf, size_t len, unsigned int freq,
|
||||||
|
bool v2)
|
||||||
{
|
{
|
||||||
struct wpabuf *msg;
|
struct wpabuf *msg;
|
||||||
unsigned int wait_time;
|
unsigned int wait_time;
|
||||||
@ -2655,7 +2669,7 @@ wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||||||
wpa_s->own_addr, src,
|
wpa_s->own_addr, src,
|
||||||
wpa_s->dpp_pkex_identifier,
|
wpa_s->dpp_pkex_identifier,
|
||||||
wpa_s->dpp_pkex_code,
|
wpa_s->dpp_pkex_code,
|
||||||
buf, len);
|
buf, len, v2);
|
||||||
if (!wpa_s->dpp_pkex) {
|
if (!wpa_s->dpp_pkex) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"DPP: Failed to process the request - ignore it");
|
"DPP: Failed to process the request - ignore it");
|
||||||
@ -2878,8 +2892,17 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||||||
case DPP_PA_PEER_DISCOVERY_RESP:
|
case DPP_PA_PEER_DISCOVERY_RESP:
|
||||||
wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
|
wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
case DPP_PA_PKEX_EXCHANGE_REQ:
|
case DPP_PA_PKEX_EXCHANGE_REQ:
|
||||||
wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
|
/* This is for PKEXv2, but for now, process only with
|
||||||
|
* CONFIG_DPP3 to avoid issues with a capability that has not
|
||||||
|
* been tested with other implementations. */
|
||||||
|
wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
case DPP_PA_PKEX_V1_EXCHANGE_REQ:
|
||||||
|
wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
|
||||||
|
false);
|
||||||
break;
|
break;
|
||||||
case DPP_PA_PKEX_EXCHANGE_RESP:
|
case DPP_PA_PKEX_EXCHANGE_RESP:
|
||||||
wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
|
wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
|
||||||
@ -3192,17 +3215,38 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
|
|||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
skip_connector:
|
skip_connector:
|
||||||
|
if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
|
||||||
|
goto skip_proto_ver;
|
||||||
|
}
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
if (DPP_VERSION > 1) {
|
if (DPP_VERSION > 1) {
|
||||||
|
u8 ver = DPP_VERSION;
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
int conn_ver;
|
||||||
|
|
||||||
|
conn_ver = dpp_get_connector_version(ssid->dpp_connector);
|
||||||
|
if (conn_ver > 0 && ver != conn_ver) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Use Connector version %d instead of current protocol version %d",
|
||||||
|
conn_ver, ver);
|
||||||
|
ver = conn_ver;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
/* Protocol Version */
|
/* Protocol Version */
|
||||||
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
wpabuf_put_le16(msg, 1);
|
wpabuf_put_le16(msg, 1);
|
||||||
wpabuf_put_u8(msg, DPP_VERSION);
|
wpabuf_put_u8(msg, ver);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
skip_proto_ver:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
/* TODO: Timeout on AP response */
|
/* TODO: Timeout on AP response */
|
||||||
wait_time = wpa_s->max_remain_on_chan;
|
wait_time = wpa_s->max_remain_on_chan;
|
||||||
if (wait_time > 2000)
|
if (wait_time > 2000)
|
||||||
@ -3270,15 +3314,16 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|||||||
if (!wpa_s->dpp_pkex_code)
|
if (!wpa_s->dpp_pkex_code)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (os_strstr(cmd, " init=1")) {
|
if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) {
|
||||||
struct dpp_pkex *pkex;
|
struct dpp_pkex *pkex;
|
||||||
struct wpabuf *msg;
|
struct wpabuf *msg;
|
||||||
|
bool v2 = os_strstr(cmd, " init=2") != NULL;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
||||||
dpp_pkex_free(wpa_s->dpp_pkex);
|
dpp_pkex_free(wpa_s->dpp_pkex);
|
||||||
wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
|
wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
|
||||||
wpa_s->dpp_pkex_identifier,
|
wpa_s->dpp_pkex_identifier,
|
||||||
wpa_s->dpp_pkex_code);
|
wpa_s->dpp_pkex_code, v2);
|
||||||
pkex = wpa_s->dpp_pkex;
|
pkex = wpa_s->dpp_pkex;
|
||||||
if (!pkex)
|
if (!pkex)
|
||||||
return -1;
|
return -1;
|
||||||
@ -3291,7 +3336,8 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
|
|||||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
" freq=%u type=%d",
|
" freq=%u type=%d",
|
||||||
MAC2STR(broadcast), pkex->freq,
|
MAC2STR(broadcast), pkex->freq,
|
||||||
DPP_PA_PKEX_EXCHANGE_REQ);
|
v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
|
||||||
|
DPP_PA_PKEX_V1_EXCHANGE_REQ);
|
||||||
offchannel_send_action(wpa_s, pkex->freq, broadcast,
|
offchannel_send_action(wpa_s, pkex->freq, broadcast,
|
||||||
wpa_s->own_addr, broadcast,
|
wpa_s->own_addr, broadcast,
|
||||||
wpabuf_head(msg), wpabuf_len(msg),
|
wpabuf_head(msg), wpabuf_len(msg),
|
||||||
|
@ -2177,7 +2177,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
|
|||||||
if (wnm_scan_process(wpa_s, 1) > 0)
|
if (wnm_scan_process(wpa_s, 1) > 0)
|
||||||
goto scan_work_done;
|
goto scan_work_done;
|
||||||
|
|
||||||
if (sme_proc_obss_scan(wpa_s, scan_res) > 0)
|
if (sme_proc_obss_scan(wpa_s) > 0)
|
||||||
goto scan_work_done;
|
goto scan_work_done;
|
||||||
|
|
||||||
if (own_request && data &&
|
if (own_request && data &&
|
||||||
|
@ -702,12 +702,14 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
|
|||||||
((cred->password == NULL ||
|
((cred->password == NULL ||
|
||||||
cred->password[0] == '\0') &&
|
cred->password[0] == '\0') &&
|
||||||
(cred->private_key == NULL ||
|
(cred->private_key == NULL ||
|
||||||
cred->private_key[0] == '\0'))) {
|
cred->private_key[0] == '\0') &&
|
||||||
|
(!cred->key_id || cred->key_id[0] == '\0'))) {
|
||||||
wpa_msg(wpa_s, MSG_DEBUG,
|
wpa_msg(wpa_s, MSG_DEBUG,
|
||||||
"nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s",
|
"nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s key_id: %s",
|
||||||
cred->username ? cred->username : "NULL",
|
cred->username ? cred->username : "NULL",
|
||||||
cred->password ? cred->password : "NULL",
|
cred->password ? cred->password : "NULL",
|
||||||
cred->private_key ? cred->private_key : "NULL");
|
cred->private_key ? cred->private_key : "NULL",
|
||||||
|
cred->key_id ? cred->key_id : "NULL");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,7 +718,8 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
|
|||||||
if (cred->password && cred->password[0] &&
|
if (cred->password && cred->password[0] &&
|
||||||
nai_realm_cred_username(wpa_s, eap))
|
nai_realm_cred_username(wpa_s, eap))
|
||||||
return eap;
|
return eap;
|
||||||
if (cred->private_key && cred->private_key[0] &&
|
if (((cred->private_key && cred->private_key[0]) ||
|
||||||
|
(cred->key_id && cred->key_id[0])) &&
|
||||||
nai_realm_cred_cert(wpa_s, eap))
|
nai_realm_cred_cert(wpa_s, eap))
|
||||||
return eap;
|
return eap;
|
||||||
}
|
}
|
||||||
@ -1539,6 +1542,24 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
|
|||||||
cred->private_key_passwd) < 0)
|
cred->private_key_passwd) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (cred->ca_cert_id && cred->ca_cert_id[0] &&
|
||||||
|
wpa_config_set_quoted(ssid, "ca_cert_id", cred->ca_cert_id) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (cred->cert_id && cred->cert_id[0] &&
|
||||||
|
wpa_config_set_quoted(ssid, "cert_id", cred->cert_id) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (cred->key_id && cred->key_id[0] &&
|
||||||
|
wpa_config_set_quoted(ssid, "key_id", cred->key_id) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (cred->engine_id && cred->engine_id[0] &&
|
||||||
|
wpa_config_set_quoted(ssid, "engine_id", cred->engine_id) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ssid->eap.cert.engine = cred->engine;
|
||||||
|
|
||||||
if (cred->phase1) {
|
if (cred->phase1) {
|
||||||
os_free(ssid->eap.phase1);
|
os_free(ssid->eap.phase1);
|
||||||
ssid->eap.phase1 = os_strdup(cred->phase1);
|
ssid->eap.phase1 = os_strdup(cred->phase1);
|
||||||
@ -2481,13 +2502,9 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
|
|||||||
bh = cred_below_min_backhaul(wpa_s, cred, bss);
|
bh = cred_below_min_backhaul(wpa_s, cred, bss);
|
||||||
bss_load = cred_over_max_bss_load(wpa_s, cred, bss);
|
bss_load = cred_over_max_bss_load(wpa_s, cred, bss);
|
||||||
conn_capab = cred_conn_capab_missing(wpa_s, cred, bss);
|
conn_capab = cred_conn_capab_missing(wpa_s, cred, bss);
|
||||||
wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d",
|
wpas_notify_interworking_ap_added(wpa_s, bss, cred, excluded,
|
||||||
excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP,
|
type, bh, bss_load,
|
||||||
MAC2STR(bss->bssid), type,
|
conn_capab);
|
||||||
bh ? " below_min_backhaul=1" : "",
|
|
||||||
bss_load ? " over_max_bss_load=1" : "",
|
|
||||||
conn_capab ? " conn_capab_missing=1" : "",
|
|
||||||
cred->id, cred->priority, cred->sp_priority);
|
|
||||||
if (excluded)
|
if (excluded)
|
||||||
continue;
|
continue;
|
||||||
if (wpa_s->auto_select ||
|
if (wpa_s->auto_select ||
|
||||||
@ -2578,6 +2595,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
|
|||||||
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wpas_notify_interworking_select_done(wpa_s);
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR,
|
wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR,
|
||||||
MAC2STR(selected->bssid));
|
MAC2STR(selected->bssid));
|
||||||
|
@ -140,6 +140,7 @@ static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
|
|||||||
conf->mesh_cc_id = 0;
|
conf->mesh_cc_id = 0;
|
||||||
conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
|
conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
|
||||||
conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
|
conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
|
||||||
|
conf->mesh_fwding = ssid->mesh_fwding;
|
||||||
conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
|
conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
|
||||||
conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
|
conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
|
||||||
conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
|
conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
|
||||||
@ -472,6 +473,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
|
|||||||
bss->conf->start_disabled = 1;
|
bss->conf->start_disabled = 1;
|
||||||
bss->conf->mesh = MESH_ENABLED;
|
bss->conf->mesh = MESH_ENABLED;
|
||||||
bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
|
bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
|
||||||
|
bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding;
|
||||||
|
|
||||||
if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
|
if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
|
||||||
wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
|
wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
|
||||||
@ -686,6 +688,10 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
|
params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
|
||||||
|
|
||||||
|
/* Always explicitely set forwarding to on or off for now */
|
||||||
|
params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING;
|
||||||
|
params->conf.forwarding = ssid->mesh_fwding;
|
||||||
|
|
||||||
os_free(wpa_s->mesh_params);
|
os_free(wpa_s->mesh_params);
|
||||||
wpa_s->mesh_params = params;
|
wpa_s->mesh_params = params;
|
||||||
if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) {
|
if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) {
|
||||||
|
@ -306,9 +306,10 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
|
|||||||
info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1;
|
info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1;
|
||||||
/* TODO: Add Connected to Mesh Gate/AS subfields */
|
/* TODO: Add Connected to Mesh Gate/AS subfields */
|
||||||
wpabuf_put_u8(buf, info);
|
wpabuf_put_u8(buf, info);
|
||||||
/* always forwarding & accepting plinks for now */
|
/* Set forwarding based on configuration and always accept
|
||||||
|
* plinks for now */
|
||||||
wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER |
|
wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER |
|
||||||
MESH_CAP_FORWARDING);
|
(conf->mesh_fwding ? MESH_CAP_FORWARDING : 0));
|
||||||
} else { /* Peer closing frame */
|
} else { /* Peer closing frame */
|
||||||
/* IE: Mesh ID */
|
/* IE: Mesh ID */
|
||||||
wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
|
wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "rsn_supp/wpa.h"
|
#include "rsn_supp/wpa.h"
|
||||||
#include "fst/fst.h"
|
#include "fst/fst.h"
|
||||||
#include "crypto/tls.h"
|
#include "crypto/tls.h"
|
||||||
|
#include "bss.h"
|
||||||
#include "driver_i.h"
|
#include "driver_i.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
#include "p2p_supplicant.h"
|
#include "p2p_supplicant.h"
|
||||||
@ -943,3 +944,32 @@ void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
|
||||||
|
void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss,
|
||||||
|
struct wpa_cred *cred, int excluded,
|
||||||
|
const char *type, int bh, int bss_load,
|
||||||
|
int conn_capab)
|
||||||
|
{
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d",
|
||||||
|
excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP,
|
||||||
|
MAC2STR(bss->bssid), type,
|
||||||
|
bh ? " below_min_backhaul=1" : "",
|
||||||
|
bss_load ? " over_max_bss_load=1" : "",
|
||||||
|
conn_capab ? " conn_capab_missing=1" : "",
|
||||||
|
cred->id, cred->priority, cred->sp_priority);
|
||||||
|
|
||||||
|
wpas_dbus_signal_interworking_ap_added(wpa_s, bss, cred, type, excluded,
|
||||||
|
bh, bss_load, conn_capab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpas_dbus_signal_interworking_select_done(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
@ -15,6 +15,7 @@ struct wps_credential;
|
|||||||
struct wps_event_m2d;
|
struct wps_event_m2d;
|
||||||
struct wps_event_fail;
|
struct wps_event_fail;
|
||||||
struct tls_cert_data;
|
struct tls_cert_data;
|
||||||
|
struct wpa_cred;
|
||||||
|
|
||||||
int wpas_notify_supplicant_initialized(struct wpa_global *global);
|
int wpas_notify_supplicant_initialized(struct wpa_global *global);
|
||||||
void wpas_notify_supplicant_deinitialized(struct wpa_global *global);
|
void wpas_notify_supplicant_deinitialized(struct wpa_global *global);
|
||||||
@ -156,5 +157,11 @@ void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s,
|
|||||||
const u8 *peer_addr);
|
const u8 *peer_addr);
|
||||||
void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *peer_addr, u16 reason_code);
|
const u8 *peer_addr, u16 reason_code);
|
||||||
|
void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss,
|
||||||
|
struct wpa_cred *cred, int excluded,
|
||||||
|
const char *type, int bh, int bss_load,
|
||||||
|
int conn_capab);
|
||||||
|
void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#endif /* NOTIFY_H */
|
#endif /* NOTIFY_H */
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/ocv.h"
|
#include "common/ocv.h"
|
||||||
#include "common/hw_features_common.h"
|
|
||||||
#include "eapol_supp/eapol_supp_sm.h"
|
#include "eapol_supp/eapol_supp_sm.h"
|
||||||
#include "common/wpa_common.h"
|
#include "common/wpa_common.h"
|
||||||
#include "common/sae.h"
|
#include "common/sae.h"
|
||||||
@ -138,6 +137,12 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
|
bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
|
||||||
|
if (!bss) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"SAE: BSS not available, update scan result to get BSS");
|
||||||
|
wpa_supplicant_update_scan_results(wpa_s);
|
||||||
|
bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
|
||||||
|
}
|
||||||
if (bss) {
|
if (bss) {
|
||||||
const u8 *rsnxe;
|
const u8 *rsnxe;
|
||||||
|
|
||||||
@ -2380,14 +2385,13 @@ static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
|
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
|
||||||
struct wpa_scan_results *scan_res)
|
|
||||||
{
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
|
u16 ht_cap;
|
||||||
u8 chan_list[P2P_MAX_CHANNELS], channel;
|
u8 chan_list[P2P_MAX_CHANNELS], channel;
|
||||||
u8 num_channels = 0, num_intol = 0, i;
|
u8 num_channels = 0, num_intol = 0, i;
|
||||||
size_t j;
|
|
||||||
int pri_freq, sec_freq;
|
|
||||||
|
|
||||||
if (!wpa_s->sme.sched_obss_scan)
|
if (!wpa_s->sme.sched_obss_scan)
|
||||||
return 0;
|
return 0;
|
||||||
@ -2415,36 +2419,22 @@ int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
|
|||||||
|
|
||||||
os_memset(chan_list, 0, sizeof(chan_list));
|
os_memset(chan_list, 0, sizeof(chan_list));
|
||||||
|
|
||||||
pri_freq = wpa_s->assoc_freq;
|
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
|
|
||||||
switch (wpa_s->sme.ht_sec_chan) {
|
|
||||||
case HT_SEC_CHAN_ABOVE:
|
|
||||||
sec_freq = pri_freq + 20;
|
|
||||||
break;
|
|
||||||
case HT_SEC_CHAN_BELOW:
|
|
||||||
sec_freq = pri_freq - 20;
|
|
||||||
break;
|
|
||||||
case HT_SEC_CHAN_UNKNOWN:
|
|
||||||
default:
|
|
||||||
wpa_msg(wpa_s, MSG_WARNING,
|
|
||||||
"Undefined secondary channel: drop OBSS scan results");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < scan_res->num; j++) {
|
|
||||||
struct wpa_scan_res *bss = scan_res->res[j];
|
|
||||||
enum hostapd_hw_mode mode;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
/* Skip other band bss */
|
/* Skip other band bss */
|
||||||
|
enum hostapd_hw_mode mode;
|
||||||
mode = ieee80211_freq_to_chan(bss->freq, &channel);
|
mode = ieee80211_freq_to_chan(bss->freq, &channel);
|
||||||
if (mode != HOSTAPD_MODE_IEEE80211G &&
|
if (mode != HOSTAPD_MODE_IEEE80211G &&
|
||||||
mode != HOSTAPD_MODE_IEEE80211B)
|
mode != HOSTAPD_MODE_IEEE80211B)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
res = check_bss_coex_40mhz(bss, pri_freq, sec_freq);
|
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
|
||||||
if (res) {
|
ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
|
||||||
if (res == 2)
|
wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
|
||||||
|
" freq=%u chan=%u ht_cap=0x%x",
|
||||||
|
MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
|
||||||
|
|
||||||
|
if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
|
||||||
|
if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
|
||||||
num_intol++;
|
num_intol++;
|
||||||
|
|
||||||
/* Check whether the channel is already considered */
|
/* Check whether the channel is already considered */
|
||||||
@ -2583,6 +2573,12 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
|
|||||||
ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
|
ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HT_OVERRIDES
|
||||||
|
/* No need for OBSS scan if HT40 is explicitly disabled */
|
||||||
|
if (ssid->disable_ht40)
|
||||||
|
return;
|
||||||
|
#endif /* CONFIG_HT_OVERRIDES */
|
||||||
|
|
||||||
if (!wpa_s->hw.modes)
|
if (!wpa_s->hw.modes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -37,8 +37,7 @@ void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
|
|||||||
void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s);
|
void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s);
|
||||||
void sme_deinit(struct wpa_supplicant *wpa_s);
|
void sme_deinit(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
|
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s);
|
||||||
struct wpa_scan_results *scan_res);
|
|
||||||
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
|
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
|
||||||
void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
|
void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
|
||||||
union wpa_event_data *data);
|
union wpa_event_data *data);
|
||||||
@ -113,8 +112,7 @@ static inline void sme_deinit(struct wpa_supplicant *wpa_s)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
|
static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
|
||||||
struct wpa_scan_results *scan_res)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1591,6 +1591,7 @@ static const char * const cred_fields[] = {
|
|||||||
"min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
|
"min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
|
||||||
"req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
|
"req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
|
||||||
"ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
|
"ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
|
||||||
|
"ca_cert_id", "cert_id", "key_id", "engine_id", "engine",
|
||||||
"milenage", "domain_suffix_match", "domain", "phase1", "phase2",
|
"milenage", "domain_suffix_match", "domain", "phase1", "phase2",
|
||||||
"roaming_consortium", "required_roaming_consortium", "excluded_ssid",
|
"roaming_consortium", "required_roaming_consortium", "excluded_ssid",
|
||||||
"roaming_partner", "provisioning_sp"
|
"roaming_partner", "provisioning_sp"
|
||||||
|
@ -4512,6 +4512,82 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpas_remove_cred - Remove the specified credential and all the network
|
||||||
|
* entries created based on the removed credential
|
||||||
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
* @cred: The credential to remove
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
|
||||||
|
{
|
||||||
|
struct wpa_ssid *ssid, *next;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
if (!cred) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Could not find cred");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = cred->id;
|
||||||
|
if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
|
||||||
|
|
||||||
|
/* Remove any network entry created based on the removed credential */
|
||||||
|
ssid = wpa_s->conf->ssid;
|
||||||
|
while (ssid) {
|
||||||
|
next = ssid->next;
|
||||||
|
|
||||||
|
if (ssid->parent_cred == cred) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Remove network id %d since it used the removed credential",
|
||||||
|
ssid->id);
|
||||||
|
if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
|
||||||
|
-1) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Could not find network id=%d",
|
||||||
|
ssid->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssid = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpas_remove_cred - Remove all the Interworking credentials
|
||||||
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
int res, ret = 0;
|
||||||
|
struct wpa_cred *cred, *prev;
|
||||||
|
|
||||||
|
cred = wpa_s->conf->cred;
|
||||||
|
while (cred) {
|
||||||
|
prev = cred;
|
||||||
|
cred = cred->next;
|
||||||
|
res = wpas_remove_cred(wpa_s, prev);
|
||||||
|
if (res < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Removal of all credentials failed - failed to remove credential id=%d",
|
||||||
|
prev->id);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
|
* wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
|
||||||
* @wpa_s: wpa_supplicant structure for a network interface
|
* @wpa_s: wpa_supplicant structure for a network interface
|
||||||
|
@ -150,6 +150,9 @@ ap_scan=1
|
|||||||
# This timeout value is used in mesh STA to clean up inactive stations.
|
# This timeout value is used in mesh STA to clean up inactive stations.
|
||||||
#mesh_max_inactivity=300
|
#mesh_max_inactivity=300
|
||||||
|
|
||||||
|
# Enable 802.11s layer-2 routing and forwarding (dot11MeshForwarding)
|
||||||
|
#mesh_fwding=1
|
||||||
|
|
||||||
# cert_in_cb - Whether to include a peer certificate dump in events
|
# cert_in_cb - Whether to include a peer certificate dump in events
|
||||||
# This controls whether peer certificates for authentication server and
|
# This controls whether peer certificates for authentication server and
|
||||||
# its certificate chain are included in EAP peer certificate events. This is
|
# its certificate chain are included in EAP peer certificate events. This is
|
||||||
|
@ -38,6 +38,7 @@ struct wpa_bss;
|
|||||||
struct wpa_scan_results;
|
struct wpa_scan_results;
|
||||||
struct hostapd_hw_modes;
|
struct hostapd_hw_modes;
|
||||||
struct wpa_driver_associate_params;
|
struct wpa_driver_associate_params;
|
||||||
|
struct wpa_cred;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declarations of private structures used within the ctrl_iface
|
* Forward declarations of private structures used within the ctrl_iface
|
||||||
@ -1578,6 +1579,8 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
|
|||||||
struct wpa_ssid *ssid);
|
struct wpa_ssid *ssid);
|
||||||
void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
|
void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_ssid *ssid);
|
struct wpa_ssid *ssid);
|
||||||
|
int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred);
|
||||||
|
int wpas_remove_all_creds(struct wpa_supplicant *wpa_s);
|
||||||
int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
|
int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
|
||||||
const char *pkcs11_engine_path,
|
const char *pkcs11_engine_path,
|
||||||
const char *pkcs11_module_path);
|
const char *pkcs11_module_path);
|
||||||
|
Loading…
Reference in New Issue
Block a user