wpa: Import wpa_supplicant/hostapd commit b26f5c0fe
This is the December/January update to vendor/wpa committed upstream 2021-12-13.
This commit is contained in:
parent
56f32b0e4c
commit
7b54fad807
@ -552,6 +552,32 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
||||
<h3>AbortScan ( ) --> nothing</h3>
|
||||
<p>Abort ongoing scan operation.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>AddCred ( a{sv} : args ) --> o : path</h3>
|
||||
<p>Add an Interworking/Hotspot 2.0 credential.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>a{sv} : args</dt>
|
||||
<dd>A dictionary with credential configuration. Dictionary entries are equivalent to entries in the "cred" block in wpa_supplicant configuration file.</dd>
|
||||
</dl>
|
||||
<h4>Returns</h4>
|
||||
<dl>
|
||||
<dt>o : path</dt>
|
||||
<dd>A D-Bus path to an object representing the added credential</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>RemoveCred ( o : path ) --> nothing</h3>
|
||||
<p>Remove the specified Interworking/Hotspot 2.0 credential.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>RemoveAllCreds ( ) --> nothing</h3>
|
||||
<p>Remove all configured Interworking/Hotspot 2.0 credentials.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>InterworkingSelect ( ) --> nothing</h3>
|
||||
<p>Perform Interworking (Hotspot 2.0) network selection.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>EAPLogoff ( ) --> nothing</h3>
|
||||
<p>IEEE 802.1X EAPOL state machine logoff.</p>
|
||||
@ -1261,6 +1287,14 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
||||
<dd>A dictionary with pairs of field names and their values. Possible dictionary keys are: "addr", "dst", "bssid", "ies", "signal".</dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<h3>InterworkingAPAdded ( o : bss, o : cred, a{sv} : args )</h3>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<h3>InterworkingSelectDone ( )</h3>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
@ -567,6 +567,9 @@ NEED_ASN1=y
|
||||
ifdef CONFIG_DPP2
|
||||
L_CFLAGS += -DCONFIG_DPP2
|
||||
endif
|
||||
ifdef CONFIG_DPP3
|
||||
L_CFLAGS += -DCONFIG_DPP3
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PASN
|
||||
|
@ -593,6 +593,9 @@ NEED_ASN1=y
|
||||
ifdef CONFIG_DPP2
|
||||
CFLAGS += -DCONFIG_DPP2
|
||||
endif
|
||||
ifdef CONFIG_DPP3
|
||||
CFLAGS += -DCONFIG_DPP3
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PASN
|
||||
|
@ -3193,6 +3193,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||
conf->acs_freq_list_present = 1;
|
||||
} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
|
||||
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) {
|
||||
int val = atoi(pos);
|
||||
/* 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;
|
||||
|
||||
val = atoi(value);
|
||||
if (val < 0 || val > 1)
|
||||
if (val < 0 || val > MBO_ASSOC_DISALLOW_REASON_LOW_RSSI)
|
||||
return -1;
|
||||
|
||||
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) {
|
||||
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");
|
||||
#else /* CONFIG_DPP2 */
|
||||
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_DPP
|
||||
dpp_test = DPP_TEST_DISABLED;
|
||||
#ifdef CONFIG_DPP2
|
||||
#ifdef CONFIG_DPP3
|
||||
dpp_version_override = 3;
|
||||
#elif defined(CONFIG_DPP2)
|
||||
dpp_version_override = 2;
|
||||
#else /* CONFIG_DPP2 */
|
||||
dpp_version_override = 1;
|
||||
|
@ -402,3 +402,11 @@ CONFIG_IPV6=y
|
||||
# production use.
|
||||
# This requires CONFIG_IEEE80211W=y to be enabled, too.
|
||||
#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.
|
||||
#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_int=100
|
||||
|
||||
|
@ -546,6 +546,9 @@ static void acs_survey_mode_interference_factor(
|
||||
if (!is_in_freqlist(iface, chan))
|
||||
continue;
|
||||
|
||||
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
|
||||
chan->chan, chan->freq);
|
||||
|
||||
@ -673,6 +676,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||
if (!is_in_freqlist(iface, chan))
|
||||
continue;
|
||||
|
||||
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||
continue;
|
||||
|
||||
if (!chan_bw_allowed(chan, bw, 1, 1)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"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))
|
||||
continue;
|
||||
|
||||
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||
continue;
|
||||
|
||||
*freq++ = chan->freq;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ struct mesh_conf {
|
||||
int dot11MeshRetryTimeout; /* msec */
|
||||
int dot11MeshConfirmTimeout; /* msec */
|
||||
int dot11MeshHoldingTimeout; /* msec */
|
||||
int mesh_fwding;
|
||||
};
|
||||
|
||||
#define MAX_STA_COUNT 2007
|
||||
@ -696,6 +697,7 @@ struct hostapd_bss_config {
|
||||
|
||||
#define MESH_ENABLED BIT(0)
|
||||
int mesh;
|
||||
int mesh_fwding;
|
||||
|
||||
u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
|
||||
|
||||
@ -953,6 +955,7 @@ struct hostapd_config {
|
||||
struct wpa_freq_range_list acs_freq_list;
|
||||
u8 acs_freq_list_present;
|
||||
int acs_exclude_dfs;
|
||||
u8 min_tx_power;
|
||||
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
|
||||
int acs_exclude_6ghz_non_psc;
|
||||
enum {
|
||||
|
@ -888,7 +888,8 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
|
||||
continue;
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
!(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);
|
||||
}
|
||||
}
|
||||
|
@ -570,9 +570,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
||||
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
|
||||
(hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
|
||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
|
||||
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);
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
|
||||
(hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
|
||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
||||
|
||||
tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON);
|
||||
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
|
||||
|
@ -246,6 +246,9 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chan->max_tx_power < iface->conf->min_tx_power)
|
||||
continue;
|
||||
|
||||
if (ret_chan && idx == channel_idx) {
|
||||
wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
|
||||
chan->freq, chan->chan);
|
||||
|
@ -1554,17 +1554,38 @@ static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
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 */
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
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 */
|
||||
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||
wpabuf_put_le16(msg, 1);
|
||||
wpabuf_put_u8(msg, DPP_VERSION);
|
||||
wpabuf_put_u8(msg, ver);
|
||||
}
|
||||
#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
|
||||
" status=%d", MAC2STR(src), status);
|
||||
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;
|
||||
}
|
||||
|
||||
#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)
|
||||
expire = hapd->conf->dpp_netaccesskey_expiry;
|
||||
if (expire)
|
||||
@ -1670,7 +1713,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
|
||||
static void
|
||||
hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
|
||||
const u8 *buf, size_t len,
|
||||
unsigned int freq)
|
||||
unsigned int freq, bool v2)
|
||||
{
|
||||
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->dpp_pkex_identifier,
|
||||
hapd->dpp_pkex_code,
|
||||
buf, len);
|
||||
buf, len, v2);
|
||||
if (!hapd->dpp_pkex) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"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:
|
||||
hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
|
||||
break;
|
||||
#ifdef CONFIG_DPP3
|
||||
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;
|
||||
case DPP_PA_PKEX_EXCHANGE_RESP:
|
||||
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)
|
||||
return -1;
|
||||
|
||||
if (os_strstr(cmd, " init=1")) {
|
||||
if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) {
|
||||
struct wpabuf *msg;
|
||||
bool v2 = os_strstr(cmd, " init=2") != NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
|
||||
dpp_pkex_free(hapd->dpp_pkex);
|
||||
hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
|
||||
hapd->own_addr,
|
||||
hapd->dpp_pkex_identifier,
|
||||
hapd->dpp_pkex_code);
|
||||
hapd->dpp_pkex_code, v2);
|
||||
if (!hapd->dpp_pkex)
|
||||
return -1;
|
||||
|
||||
@ -2134,7 +2188,8 @@ int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
|
||||
/* TODO: Which channel to use? */
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||
" 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,
|
||||
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_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;
|
||||
hostapd_set_oper_chwidth(hapd->iconf, chwidth);
|
||||
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))
|
||||
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) {
|
||||
case 0:
|
||||
case 20:
|
||||
@ -3482,6 +3496,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
|
||||
|
||||
conf->channel = channel;
|
||||
conf->ieee80211n = params->ht_enabled;
|
||||
conf->ieee80211ac = params->vht_enabled;
|
||||
conf->secondary_channel = params->sec_channel_offset;
|
||||
ieee80211_freq_to_chan(params->center_freq1,
|
||||
&seg0);
|
||||
|
@ -28,7 +28,9 @@
|
||||
static const char * dpp_netrole_str(enum dpp_netrole netrole);
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
#ifdef CONFIG_DPP2
|
||||
#ifdef CONFIG_DPP3
|
||||
int dpp_version_override = 3;
|
||||
#elif defined(CONFIG_DPP2)
|
||||
int dpp_version_override = 2;
|
||||
#else
|
||||
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;
|
||||
else if (*version == '2')
|
||||
bi->version = 2;
|
||||
else if (*version == '3')
|
||||
bi->version = 3;
|
||||
else
|
||||
wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
|
||||
|
||||
@ -628,7 +632,8 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
|
||||
macstr,
|
||||
bi->info ? "I:" : "", bi->info ? bi->info : "",
|
||||
bi->info ? ";" : "",
|
||||
DPP_VERSION == 2 ? "V:2;" : "",
|
||||
DPP_VERSION == 3 ? "V:3;" :
|
||||
(DPP_VERSION == 2 ? "V:2;" : ""),
|
||||
bi->pk);
|
||||
return 0;
|
||||
}
|
||||
@ -1499,6 +1504,10 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
|
||||
json_value_sep(dppcon);
|
||||
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);
|
||||
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
|
||||
(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");
|
||||
if (!netkey || netkey->type != JSON_OBJECT) {
|
||||
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)
|
||||
{
|
||||
struct dpp_bootstrap_info *bi;
|
||||
|
@ -25,7 +25,9 @@ struct dpp_reconfig_id;
|
||||
#define DPP_VERSION (dpp_version_override)
|
||||
extern int dpp_version_override;
|
||||
#else /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_DPP2
|
||||
#ifdef CONFIG_DPP3
|
||||
#define DPP_VERSION 3
|
||||
#elif defined(CONFIG_DPP2)
|
||||
#define DPP_VERSION 2
|
||||
#else
|
||||
#define DPP_VERSION 1
|
||||
@ -41,7 +43,7 @@ enum dpp_public_action_frame_type {
|
||||
DPP_PA_AUTHENTICATION_CONF = 2,
|
||||
DPP_PA_PEER_DISCOVERY_REQ = 5,
|
||||
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_COMMIT_REVEAL_REQ = 9,
|
||||
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_RESP = 16,
|
||||
DPP_PA_RECONFIG_AUTH_CONF = 17,
|
||||
DPP_PA_PKEX_EXCHANGE_REQ = 18,
|
||||
};
|
||||
|
||||
enum dpp_attribute_id {
|
||||
@ -173,6 +176,7 @@ struct dpp_pkex {
|
||||
unsigned int initiator:1;
|
||||
unsigned int exchange_done:1;
|
||||
unsigned int failed:1;
|
||||
unsigned int v2:1;
|
||||
struct dpp_bootstrap_info *own_bi;
|
||||
u8 own_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_tries;
|
||||
unsigned int freq;
|
||||
u8 peer_version;
|
||||
};
|
||||
|
||||
enum dpp_akm {
|
||||
@ -372,6 +377,7 @@ struct dpp_introduction {
|
||||
u8 pmkid[PMKID_LEN];
|
||||
u8 pmk[PMK_LEN_MAX];
|
||||
size_t pmk_len;
|
||||
int peer_version;
|
||||
};
|
||||
|
||||
struct dpp_relay_config {
|
||||
@ -491,6 +497,8 @@ enum dpp_test_behavior {
|
||||
DPP_TEST_STOP_AT_AUTH_CONF = 89,
|
||||
DPP_TEST_STOP_AT_CONF_REQ = 90,
|
||||
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;
|
||||
@ -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 *peer_connector, size_t peer_connector_len,
|
||||
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,
|
||||
const u8 *own_mac,
|
||||
const char *identifier,
|
||||
const char *code);
|
||||
const char *identifier, const char *code,
|
||||
bool v2);
|
||||
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
||||
struct dpp_bootstrap_info *bi,
|
||||
const u8 *own_mac,
|
||||
const u8 *peer_mac,
|
||||
const char *identifier,
|
||||
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,
|
||||
const u8 *peer_mac,
|
||||
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_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));
|
||||
addr[num_elem] = mac_init;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
if (mac_init) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
|
||||
MAC2STR(mac_init));
|
||||
addr[num_elem] = mac_init;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
}
|
||||
if (identifier) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
|
||||
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)
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG,
|
||||
"DPP: H(MAC-Initiator | [identifier |] code)",
|
||||
"DPP: H([MAC-Initiator |] [identifier |] code)",
|
||||
hash, curve->hash_len);
|
||||
Pi_key = dpp_pkex_get_role_elem(curve, 1);
|
||||
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_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));
|
||||
addr[num_elem] = mac_resp;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
if (mac_resp) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
|
||||
MAC2STR(mac_resp));
|
||||
addr[num_elem] = mac_resp;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
}
|
||||
if (identifier) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
|
||||
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)
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG,
|
||||
"DPP: H(MAC-Responder | [identifier |] code)",
|
||||
"DPP: H([MAC-Responder |] [identifier |] code)",
|
||||
hash, curve->hash_len);
|
||||
Pr_key = dpp_pkex_get_role_elem(curve, 0);
|
||||
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,
|
||||
u8 ver_init, u8 ver_resp,
|
||||
const u8 *Mx, size_t Mx_len,
|
||||
const u8 *Nx, size_t Nx_len,
|
||||
const char *code,
|
||||
@ -1589,7 +1596,10 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
||||
u8 *info, *pos;
|
||||
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) */
|
||||
@ -1598,15 +1608,24 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
|
||||
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);
|
||||
if (!info)
|
||||
return -1;
|
||||
pos = info;
|
||||
os_memcpy(pos, mac_init, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
os_memcpy(pos, mac_resp, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
if (mac_init && mac_resp) {
|
||||
os_memcpy(pos, mac_init, 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);
|
||||
pos += Mx_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,
|
||||
struct crypto_ec **ret_ec);
|
||||
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 *Nx, size_t Nx_len,
|
||||
const char *code,
|
||||
|
@ -26,7 +26,8 @@ size_t dpp_pkex_ephemeral_key_override_len = 0;
|
||||
#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;
|
||||
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;
|
||||
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 = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
|
||||
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
|
||||
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : pkex->own_mac, pkex->code,
|
||||
pkex->identifier, &ec);
|
||||
if (!Qi)
|
||||
goto fail;
|
||||
@ -76,13 +78,27 @@ static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
|
||||
|
||||
/* Initiator -> Responder: group, [identifier,] M */
|
||||
attr_len = 4 + 2;
|
||||
#ifdef CONFIG_DPP2
|
||||
if (v2)
|
||||
attr_len += 4 + 1;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
if (pkex->identifier)
|
||||
attr_len += 4 + os_strlen(pkex->identifier);
|
||||
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)
|
||||
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
|
||||
if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
|
||||
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,
|
||||
const u8 *own_mac,
|
||||
const char *identifier,
|
||||
const char *code)
|
||||
const char *identifier, const char *code,
|
||||
bool v2)
|
||||
{
|
||||
struct dpp_pkex *pkex;
|
||||
|
||||
@ -172,6 +188,7 @@ struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
|
||||
return NULL;
|
||||
pkex->msg_ctx = msg_ctx;
|
||||
pkex->initiator = 1;
|
||||
pkex->v2 = v2;
|
||||
pkex->own_bi = bi;
|
||||
os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
|
||||
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);
|
||||
if (!pkex->code)
|
||||
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)
|
||||
goto fail;
|
||||
return pkex;
|
||||
@ -201,8 +218,13 @@ dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
|
||||
size_t attr_len;
|
||||
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;
|
||||
#ifdef CONFIG_DPP2
|
||||
if (pkex->v2)
|
||||
attr_len += 4 + 1;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
if (pkex->identifier)
|
||||
attr_len += 4 + os_strlen(pkex->identifier);
|
||||
attr_len += 4 + 2 * curve->prime_len;
|
||||
@ -229,6 +251,15 @@ dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
|
||||
skip_status:
|
||||
#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 */
|
||||
if (pkex->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 char *identifier,
|
||||
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;
|
||||
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];
|
||||
size_t Kx_len;
|
||||
int res;
|
||||
u8 peer_version = 0;
|
||||
|
||||
if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
|
||||
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;
|
||||
}
|
||||
|
||||
#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
|
||||
if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
|
||||
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));
|
||||
if (!pkex)
|
||||
goto fail;
|
||||
pkex->v2 = v2;
|
||||
pkex->peer_version = peer_version;
|
||||
pkex->own_bi = bi;
|
||||
pkex->failed = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
|
||||
Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, &ec);
|
||||
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
|
||||
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, identifier,
|
||||
&ec);
|
||||
if (!Qi)
|
||||
goto fail;
|
||||
|
||||
@ -411,6 +464,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
||||
pkex = os_zalloc(sizeof(*pkex));
|
||||
if (!pkex)
|
||||
goto fail;
|
||||
pkex->v2 = v2;
|
||||
pkex->peer_version = peer_version;
|
||||
pkex->t = bi->pkex_t;
|
||||
pkex->msg_ctx = msg_ctx;
|
||||
pkex->own_bi = bi;
|
||||
@ -438,8 +493,9 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
||||
if (!pkex->x)
|
||||
goto fail;
|
||||
|
||||
/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
|
||||
Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, NULL);
|
||||
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
|
||||
Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, identifier,
|
||||
NULL);
|
||||
if (!Qr)
|
||||
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)",
|
||||
Kx, Kx_len);
|
||||
|
||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
||||
*/
|
||||
res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
|
||||
/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
|
||||
res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->peer_mac,
|
||||
pkex->v2 ? NULL : pkex->own_mac,
|
||||
pkex->peer_version, DPP_VERSION,
|
||||
pkex->Mx, curve->prime_len,
|
||||
pkex->Nx, curve->prime_len, pkex->code,
|
||||
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];
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
size_t num_elem;
|
||||
u8 u[DPP_MAX_HASH_LEN];
|
||||
int res;
|
||||
|
||||
@ -666,6 +724,24 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
|
||||
}
|
||||
#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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
|
||||
Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
|
||||
pkex->identifier, &ec);
|
||||
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
|
||||
Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac,
|
||||
pkex->code, pkex->identifier, &ec);
|
||||
if (!Qr)
|
||||
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)",
|
||||
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);
|
||||
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
||||
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
||||
if (!A_pub || !Y_pub || !X_pub)
|
||||
goto fail;
|
||||
addr[0] = pkex->own_mac;
|
||||
len[0] = ETH_ALEN;
|
||||
addr[1] = wpabuf_head(A_pub);
|
||||
len[1] = wpabuf_len(A_pub) / 2;
|
||||
addr[2] = wpabuf_head(Y_pub);
|
||||
len[2] = wpabuf_len(Y_pub) / 2;
|
||||
addr[3] = wpabuf_head(X_pub);
|
||||
len[3] = wpabuf_len(X_pub) / 2;
|
||||
if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
|
||||
num_elem = 0;
|
||||
if (!pkex->v2) {
|
||||
addr[num_elem] = pkex->own_mac;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
}
|
||||
addr[num_elem] = wpabuf_head(A_pub);
|
||||
len[num_elem] = wpabuf_len(A_pub) / 2;
|
||||
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;
|
||||
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)",
|
||||
Kx, Kx_len);
|
||||
|
||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
||||
*/
|
||||
res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
|
||||
/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
|
||||
res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->own_mac,
|
||||
pkex->v2 ? NULL : pkex->peer_mac,
|
||||
DPP_VERSION, pkex->peer_version,
|
||||
pkex->Mx, curve->prime_len,
|
||||
attr_key /* N.x */, attr_key_len / 2,
|
||||
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;
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
size_t num_elem;
|
||||
u8 octet;
|
||||
u8 *unwrapped = NULL;
|
||||
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)",
|
||||
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);
|
||||
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
||||
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
||||
if (!A_pub || !Y_pub || !X_pub)
|
||||
goto fail;
|
||||
addr[0] = pkex->peer_mac;
|
||||
len[0] = ETH_ALEN;
|
||||
addr[1] = wpabuf_head(A_pub);
|
||||
len[1] = wpabuf_len(A_pub) / 2;
|
||||
addr[2] = wpabuf_head(Y_pub);
|
||||
len[2] = wpabuf_len(Y_pub) / 2;
|
||||
addr[3] = wpabuf_head(X_pub);
|
||||
len[3] = wpabuf_len(X_pub) / 2;
|
||||
if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
|
||||
num_elem = 0;
|
||||
if (!pkex->v2) {
|
||||
addr[num_elem] = pkex->peer_mac;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
}
|
||||
addr[num_elem] = wpabuf_head(A_pub);
|
||||
len[num_elem] = wpabuf_len(A_pub) / 2;
|
||||
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;
|
||||
|
||||
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)",
|
||||
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);
|
||||
if (!B_pub)
|
||||
goto fail;
|
||||
addr[0] = pkex->own_mac;
|
||||
len[0] = ETH_ALEN;
|
||||
addr[1] = wpabuf_head(B_pub);
|
||||
len[1] = wpabuf_len(B_pub) / 2;
|
||||
addr[2] = wpabuf_head(X_pub);
|
||||
len[2] = wpabuf_len(X_pub) / 2;
|
||||
addr[3] = wpabuf_head(Y_pub);
|
||||
len[3] = wpabuf_len(Y_pub) / 2;
|
||||
if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
|
||||
num_elem = 0;
|
||||
if (!pkex->v2) {
|
||||
addr[num_elem] = pkex->own_mac;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
}
|
||||
addr[num_elem] = wpabuf_head(B_pub);
|
||||
len[num_elem] = wpabuf_len(B_pub) / 2;
|
||||
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;
|
||||
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;
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
size_t num_elem;
|
||||
u8 octet;
|
||||
u8 *unwrapped = NULL;
|
||||
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)",
|
||||
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);
|
||||
X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
|
||||
Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
|
||||
if (!B_pub || !X_pub || !Y_pub)
|
||||
goto fail;
|
||||
addr[0] = pkex->peer_mac;
|
||||
len[0] = ETH_ALEN;
|
||||
addr[1] = wpabuf_head(B_pub);
|
||||
len[1] = wpabuf_len(B_pub) / 2;
|
||||
addr[2] = wpabuf_head(X_pub);
|
||||
len[2] = wpabuf_len(X_pub) / 2;
|
||||
addr[3] = wpabuf_head(Y_pub);
|
||||
len[3] = wpabuf_len(Y_pub) / 2;
|
||||
if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
|
||||
num_elem = 0;
|
||||
if (!pkex->v2) {
|
||||
addr[num_elem] = pkex->peer_mac;
|
||||
len[num_elem] = ETH_ALEN;
|
||||
num_elem++;
|
||||
}
|
||||
addr[num_elem] = wpabuf_head(B_pub);
|
||||
len[num_elem] = wpabuf_len(B_pub) / 2;
|
||||
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;
|
||||
|
||||
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,
|
||||
struct wpa_scan_results *scan_res, int pri_chan,
|
||||
int sec_chan)
|
||||
{
|
||||
int pri_freq, sec_freq;
|
||||
int affected_start, affected_end;
|
||||
size_t i;
|
||||
|
||||
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);
|
||||
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",
|
||||
(pri_freq + sec_freq) / 2 - 25,
|
||||
(pri_freq + sec_freq) / 2 + 25);
|
||||
affected_start, affected_end);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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,
|
||||
struct hostapd_channel_data *pri_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,
|
||||
struct wpa_scan_results *scan_res, int pri_chan,
|
||||
int sec_chan);
|
||||
|
@ -622,7 +622,14 @@ enum qca_radiotap_vendor_ids {
|
||||
* This new command is alternative to existing command
|
||||
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
|
||||
* 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
|
||||
* 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
|
||||
* Nested attribute containing multiple ranges with following attributes:
|
||||
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
|
||||
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
|
||||
* QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
|
||||
* 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)
|
||||
* Starting center frequency in MHz.
|
||||
*
|
||||
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
|
||||
* 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 {
|
||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
|
||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
|
||||
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
|
||||
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_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_HT_OP_MODE 0x00000008
|
||||
#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.
|
||||
* See NL80211_MESHCONF_* for all the mesh config parameters.
|
||||
@ -1599,6 +1600,7 @@ struct wpa_driver_mesh_bss_params {
|
||||
int peer_link_timeout;
|
||||
int max_peer_links;
|
||||
int rssi_threshold;
|
||||
int forwarding;
|
||||
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) &&
|
||||
nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_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) &&
|
||||
nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
|
||||
params->max_peer_links)) ||
|
||||
|
@ -508,7 +508,7 @@ def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
|
||||
raise Exception("Failed to initiate DPP Authentication")
|
||||
|
||||
def dpp_pkex_init(self, identifier, code, role=None, key=None, curve=None,
|
||||
extra=None, use_id=None):
|
||||
extra=None, use_id=None, v2=False):
|
||||
if use_id is None:
|
||||
id1 = self.dpp_bootstrap_gen(type="pkex", key=key, curve=curve)
|
||||
else:
|
||||
@ -516,7 +516,10 @@ def dpp_pkex_init(self, identifier, code, role=None, key=None, curve=None,
|
||||
cmd = "own=%d " % id1
|
||||
if identifier:
|
||||
cmd += "identifier=%s " % identifier
|
||||
cmd += "init=1 "
|
||||
if v2:
|
||||
cmd += "init=2 "
|
||||
else:
|
||||
cmd += "init=1 "
|
||||
if role:
|
||||
cmd += "role=%s " % role
|
||||
if extra:
|
||||
|
@ -24,7 +24,7 @@ def execute_thread(command, reply):
|
||||
err = tempfile.TemporaryFile()
|
||||
try:
|
||||
status = 0
|
||||
buf = subprocess.check_output(command, stderr=err).decode()
|
||||
buf = subprocess.check_output(command, stderr=err, bufsize=0).decode()
|
||||
except subprocess.CalledProcessError as e:
|
||||
status = e.returncode
|
||||
err.seek(0)
|
||||
@ -181,7 +181,8 @@ def proc_run(self, command):
|
||||
_cmd = self.name + " proc_run: " + ' '.join(cmd)
|
||||
logger.debug(_cmd)
|
||||
err = tempfile.TemporaryFile()
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=err)
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=err,
|
||||
bufsize=0)
|
||||
proc.reaper_file = filename
|
||||
return proc
|
||||
|
||||
|
@ -4180,12 +4180,12 @@ def test_ap_hs20_multi_network_and_cred_removal(dev, apdev):
|
||||
interworking_connect(dev[0], bssid, "PEAP")
|
||||
dev[0].add_network()
|
||||
if len(dev[0].list_networks()) != 5:
|
||||
raise Exception("Unexpected number of networks prior to remove_crec")
|
||||
raise Exception("Unexpected number of networks prior to remove_cred")
|
||||
|
||||
dev[0].dump_monitor()
|
||||
dev[0].remove_cred(id)
|
||||
if len(dev[0].list_networks()) != 3:
|
||||
raise Exception("Unexpected number of networks after to remove_crec")
|
||||
raise Exception("Unexpected number of networks after to remove_cred")
|
||||
dev[0].wait_disconnected(timeout=10)
|
||||
|
||||
def test_ap_hs20_interworking_add_network(dev, apdev):
|
||||
|
@ -6091,3 +6091,114 @@ def success(self):
|
||||
with TestDbusConnect(bus) as t:
|
||||
if not t.success():
|
||||
raise Exception("Expected signals not seen")
|
||||
|
||||
def test_dbus_creds(dev, apdev):
|
||||
"D-Bus interworking credentials"
|
||||
(bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0])
|
||||
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
|
||||
|
||||
args = {'domain': 'server.w1.fi',
|
||||
'realm': 'server.w1.fi',
|
||||
'roaming_consortium': '50a9bf',
|
||||
'required_roaming_consortium': '23bf50',
|
||||
'eap': 'TTLS',
|
||||
'phase2': 'auth=MSCHAPV2',
|
||||
'username': 'user',
|
||||
'password': 'password',
|
||||
'domain_suffix_match': 'server.w1.fi',
|
||||
'ca_cert': 'auth_serv/ca.pem'}
|
||||
|
||||
path = iface.AddCred(dbus.Dictionary(args, signature='sv'))
|
||||
for k, v in args.items():
|
||||
if k == 'password':
|
||||
continue
|
||||
prop = dev[0].get_cred(0, k)
|
||||
if prop != v:
|
||||
raise Exception('Credential add failed: %s does not match %s' % (prop, v))
|
||||
|
||||
iface.RemoveCred(path)
|
||||
if not "FAIL" in dev[0].get_cred(0, 'domain'):
|
||||
raise Exception("Credential remove failed")
|
||||
|
||||
# Removal of multiple credentials
|
||||
cred1 = {'domain': 'server1.w1.fi','realm': 'server1.w1.fi','eap': 'TTLS'}
|
||||
iface.AddCred(dbus.Dictionary(cred1, signature='sv'))
|
||||
if "FAIL" in dev[0].get_cred(0, 'domain'):
|
||||
raise Exception("Failed to add credential")
|
||||
|
||||
cred2 = {'domain': 'server2.w1.fi','realm': 'server2.w1.fi','eap': 'TTLS'}
|
||||
iface.AddCred(dbus.Dictionary(cred2, signature='sv'))
|
||||
if "FAIL" in dev[0].get_cred(1, 'domain'):
|
||||
raise Exception("Failed to add credential")
|
||||
|
||||
iface.RemoveAllCreds()
|
||||
if not "FAIL" in dev[0].get_cred(0, 'domain'):
|
||||
raise Exception("Credential remove failed")
|
||||
if not "FAIL" in dev[0].get_cred(1, 'domain'):
|
||||
raise Exception("Credential remove failed")
|
||||
|
||||
def test_dbus_interworking(dev, apdev):
|
||||
"D-Bus interworking selection"
|
||||
(bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0])
|
||||
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
|
||||
|
||||
params = {"ssid": "test-interworking", "wpa": "2",
|
||||
"wpa_key_mgmt": "WPA-EAP", "rsn_pairwise": "CCMP",
|
||||
"ieee8021x": "1", "eapol_version": "2",
|
||||
"eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
|
||||
"ca_cert": "auth_serv/ca.pem",
|
||||
"server_cert": "auth_serv/server.pem",
|
||||
"private_key": "auth_serv/server.key",
|
||||
"interworking": "1",
|
||||
"domain_name": "server.w1.fi",
|
||||
"nai_realm": "0,server.w1.fi,21[2:4][5:7]",
|
||||
"roaming_consortium": "2233445566",
|
||||
"hs20": "1", "anqp_domain_id": "1234"}
|
||||
|
||||
hapd = hostapd.add_ap(apdev[0], params)
|
||||
|
||||
class TestDbusInterworking(TestDbus):
|
||||
def __init__(self, bus):
|
||||
TestDbus.__init__(self, bus)
|
||||
self.interworking_ap_seen = False
|
||||
self.interworking_select_done = False
|
||||
|
||||
def __enter__(self):
|
||||
gobject.timeout_add(1, self.run_select)
|
||||
gobject.timeout_add(15000, self.timeout)
|
||||
self.add_signal(self.interworkingAPAdded, WPAS_DBUS_IFACE,
|
||||
"InterworkingAPAdded")
|
||||
self.add_signal(self.interworkingSelectDone, WPAS_DBUS_IFACE,
|
||||
"InterworkingSelectDone")
|
||||
self.loop.run()
|
||||
return self
|
||||
|
||||
def interworkingAPAdded(self, bss, cred, properties):
|
||||
logger.debug("interworkingAPAdded: bss=%s cred=%s %s" % (bss, cred, str(properties)))
|
||||
if self.cred == cred:
|
||||
self.interworking_ap_seen = True
|
||||
|
||||
def interworkingSelectDone(self):
|
||||
logger.debug("interworkingSelectDone")
|
||||
self.interworking_select_done = True
|
||||
self.loop.quit()
|
||||
|
||||
def run_select(self, *args):
|
||||
args = {"domain": "server.w1.fi",
|
||||
"realm": "server.w1.fi",
|
||||
"eap": "TTLS",
|
||||
"phase2": "auth=MSCHAPV2",
|
||||
"username": "user",
|
||||
"password": "password",
|
||||
"domain_suffix_match": "server.w1.fi",
|
||||
"ca_cert": "auth_serv/ca.pem"}
|
||||
self.cred = iface.AddCred(dbus.Dictionary(args, signature='sv'))
|
||||
iface.InterworkingSelect()
|
||||
return False
|
||||
|
||||
def success(self):
|
||||
return self.interworking_ap_seen and self.interworking_select_done
|
||||
|
||||
with TestDbusInterworking(bus) as t:
|
||||
if not t.success():
|
||||
raise Exception("Expected signals not seen")
|
||||
|
@ -126,8 +126,12 @@ def test_dpp_uri_version(dev, apdev):
|
||||
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
||||
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id1)
|
||||
logger.info("Parsed URI info:\n" + info)
|
||||
if "version=2" not in info.splitlines():
|
||||
raise Exception("Unexpected version information (v2)")
|
||||
capa = dev[0].request("GET_CAPABILITY dpp")
|
||||
ver = 1
|
||||
if capa.startswith("DPP="):
|
||||
ver = int(capa[4:])
|
||||
if "version=%d" % ver not in info.splitlines():
|
||||
raise Exception("Unexpected version information (with indication)")
|
||||
|
||||
dev[0].set("dpp_version_override", "1")
|
||||
id0 = dev[0].dpp_bootstrap_gen()
|
||||
@ -1877,7 +1881,7 @@ def test_dpp_auto_connect_2_conf_ver1(dev, apdev):
|
||||
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||
|
||||
def run_dpp_auto_connect(dev, apdev, processing, ap_version=0, sta_version=0,
|
||||
sta1_version=0):
|
||||
sta1_version=0, stop_after_prov=False):
|
||||
check_dpp_capab(dev[0])
|
||||
check_dpp_capab(dev[1])
|
||||
|
||||
@ -1916,6 +1920,8 @@ def run_dpp_auto_connect(dev, apdev, processing, ap_version=0, sta_version=0,
|
||||
if ev is None:
|
||||
raise Exception("DPP network profile not generated")
|
||||
id = ev.split(' ')[1]
|
||||
if stop_after_prov:
|
||||
return id, hapd
|
||||
|
||||
if processing == 1:
|
||||
dev[0].select_network(id, freq=2412)
|
||||
@ -2262,6 +2268,10 @@ def test_dpp_pkex(dev, apdev):
|
||||
"""DPP and PKEX"""
|
||||
run_dpp_pkex(dev, apdev)
|
||||
|
||||
def test_dpp_pkex_v2(dev, apdev):
|
||||
"""DPP and PKEXv2"""
|
||||
run_dpp_pkex(dev, apdev, v2=True)
|
||||
|
||||
def test_dpp_pkex_p256(dev, apdev):
|
||||
"""DPP and PKEX (P-256)"""
|
||||
run_dpp_pkex(dev, apdev, "P-256")
|
||||
@ -2315,13 +2325,14 @@ def test_dpp_pkex_identifier_mismatch3(dev, apdev):
|
||||
|
||||
def run_dpp_pkex(dev, apdev, curve=None, init_extra=None, check_config=False,
|
||||
identifier_i="test", identifier_r="test",
|
||||
expect_no_resp=False):
|
||||
check_dpp_capab(dev[0], curve and "brainpool" in curve)
|
||||
check_dpp_capab(dev[1], curve and "brainpool" in curve)
|
||||
expect_no_resp=False, v2=False):
|
||||
min_ver = 3 if v2 else 1
|
||||
check_dpp_capab(dev[0], curve and "brainpool" in curve, min_ver=min_ver)
|
||||
check_dpp_capab(dev[1], curve and "brainpool" in curve, min_ver=min_ver)
|
||||
dev[0].dpp_pkex_resp(2437, identifier=identifier_r, code="secret",
|
||||
curve=curve)
|
||||
dev[1].dpp_pkex_init(identifier=identifier_i, code="secret", curve=curve,
|
||||
extra=init_extra)
|
||||
extra=init_extra, v2=v2)
|
||||
|
||||
if expect_no_resp:
|
||||
ev = dev[0].wait_event(["DPP-RX"], timeout=10)
|
||||
@ -2545,6 +2556,19 @@ def test_dpp_pkex_hostapd_responder(dev, apdev):
|
||||
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
||||
stop_initiator=True)
|
||||
|
||||
def test_dpp_pkex_v2_hostapd_responder(dev, apdev):
|
||||
"""DPP PKEXv2 with hostapd as responder"""
|
||||
check_dpp_capab(dev[0], min_ver=3)
|
||||
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||
"channel": "6"})
|
||||
check_dpp_capab(hapd, min_ver=3)
|
||||
hapd.dpp_pkex_resp(2437, identifier="test", code="secret")
|
||||
conf_id = dev[0].dpp_configurator_add()
|
||||
dev[0].dpp_pkex_init(identifier="test", code="secret",
|
||||
extra="conf=ap-dpp configurator=%d" % conf_id, v2=True)
|
||||
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
||||
stop_initiator=True)
|
||||
|
||||
def test_dpp_pkex_hostapd_initiator(dev, apdev):
|
||||
"""DPP PKEX with hostapd as initiator"""
|
||||
check_dpp_capab(dev[0])
|
||||
@ -2560,6 +2584,22 @@ def test_dpp_pkex_hostapd_initiator(dev, apdev):
|
||||
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
||||
stop_initiator=True)
|
||||
|
||||
def test_dpp_pkex_v2_hostapd_initiator(dev, apdev):
|
||||
"""DPP PKEXv2 with hostapd as initiator"""
|
||||
check_dpp_capab(dev[0], min_ver=3)
|
||||
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||
"channel": "6"})
|
||||
check_dpp_capab(hapd, min_ver=3)
|
||||
conf_id = dev[0].dpp_configurator_add()
|
||||
dev[0].set("dpp_configurator_params",
|
||||
" conf=ap-dpp configurator=%d" % conf_id)
|
||||
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret",
|
||||
listen_role="configurator")
|
||||
hapd.dpp_pkex_init(identifier="test", code="secret", role="enrollee",
|
||||
v2=True)
|
||||
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
||||
stop_initiator=True)
|
||||
|
||||
def test_dpp_pkex_hostapd_errors(dev, apdev):
|
||||
"""DPP PKEX errors with hostapd"""
|
||||
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||
|
49
tests/hwsim/test_dpp3.py
Normal file
49
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)
|
@ -203,8 +203,8 @@ def test_mbo_assoc_disallow(dev, apdev, params):
|
||||
hapd2 = hostapd.add_ap(apdev[1], {"ssid": "MBO", "mbo": "1"})
|
||||
|
||||
logger.debug("Set mbo_assoc_disallow with invalid value")
|
||||
if "FAIL" not in hapd1.request("SET mbo_assoc_disallow 2"):
|
||||
raise Exception("Set mbo_assoc_disallow for AP1 succeeded unexpectedly with value 2")
|
||||
if "FAIL" not in hapd1.request("SET mbo_assoc_disallow 6"):
|
||||
raise Exception("Set mbo_assoc_disallow for AP1 succeeded unexpectedly with value 6")
|
||||
|
||||
logger.debug("Disallow associations to AP1 and allow association to AP2")
|
||||
if "OK" not in hapd1.request("SET mbo_assoc_disallow 1"):
|
||||
|
@ -1577,7 +1577,7 @@ def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
|
||||
return int(peer)
|
||||
|
||||
def dpp_pkex_init(self, identifier, code, role=None, key=None, curve=None,
|
||||
extra=None, use_id=None, allow_fail=False):
|
||||
extra=None, use_id=None, allow_fail=False, v2=False):
|
||||
if use_id is None:
|
||||
id1 = self.dpp_bootstrap_gen(type="pkex", key=key, curve=curve)
|
||||
else:
|
||||
@ -1585,7 +1585,10 @@ def dpp_pkex_init(self, identifier, code, role=None, key=None, curve=None,
|
||||
cmd = "own=%d " % id1
|
||||
if identifier:
|
||||
cmd += "identifier=%s " % identifier
|
||||
cmd += "init=1 "
|
||||
if v2:
|
||||
cmd += "init=2 "
|
||||
else:
|
||||
cmd += "init=1 "
|
||||
if role:
|
||||
cmd += "role=%s " % role
|
||||
if extra:
|
||||
|
@ -64,6 +64,7 @@ TOBJS += gcmp.o
|
||||
|
||||
|
||||
OBJS_cli = wlantest_cli.o
|
||||
OBJS_cli += ../src/common/cli.o
|
||||
|
||||
_OBJS_VAR := OBJS
|
||||
include ../src/objs.mk
|
||||
|
@ -27,7 +27,7 @@ static void usage(void)
|
||||
"[-P<RADIUS shared secret>]\n"
|
||||
" [-n<write pcapng file>]\n"
|
||||
" [-w<write pcap file>] [-f<MSK/PMK file>]\n"
|
||||
" [-L<log file>] [-T<PTK file>]\n");
|
||||
" [-L<log file>] [-T<PTK file>] [-W<WEP key>]\n");
|
||||
}
|
||||
|
||||
|
||||
@ -77,6 +77,13 @@ static void ptk_deinit(struct wlantest_ptk *ptk)
|
||||
}
|
||||
|
||||
|
||||
static void wep_deinit(struct wlantest_wep *wep)
|
||||
{
|
||||
dl_list_del(&wep->list);
|
||||
os_free(wep);
|
||||
}
|
||||
|
||||
|
||||
static void wlantest_deinit(struct wlantest *wt)
|
||||
{
|
||||
struct wlantest_passphrase *p, *pn;
|
||||
@ -104,7 +111,7 @@ static void wlantest_deinit(struct wlantest *wt)
|
||||
dl_list_for_each_safe(ptk, npt, &wt->ptk, struct wlantest_ptk, list)
|
||||
ptk_deinit(ptk);
|
||||
dl_list_for_each_safe(wep, nw, &wt->wep, struct wlantest_wep, list)
|
||||
os_free(wep);
|
||||
wep_deinit(wep);
|
||||
write_pcap_deinit(wt);
|
||||
write_pcapng_deinit(wt);
|
||||
clear_notes(wt);
|
||||
@ -364,7 +371,7 @@ int wlantest_relog(struct wlantest *wt)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
int c, ret = 0;
|
||||
const char *read_file = NULL;
|
||||
const char *read_wired_file = NULL;
|
||||
const char *ifname = NULL;
|
||||
@ -372,6 +379,7 @@ int main(int argc, char *argv[])
|
||||
const char *logfile = NULL;
|
||||
struct wlantest wt;
|
||||
int ctrl_iface = 0;
|
||||
bool eloop_init_done = false;
|
||||
|
||||
wpa_debug_level = MSG_INFO;
|
||||
wpa_debug_show_keys = 1;
|
||||
@ -397,15 +405,18 @@ int main(int argc, char *argv[])
|
||||
wt.ethernet = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (add_pmk_file(&wt, optarg) < 0)
|
||||
return -1;
|
||||
if (add_pmk_file(&wt, optarg) < 0) {
|
||||
ret = -1;
|
||||
goto deinit;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
wt.assume_fcs = 1;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto deinit;
|
||||
case 'i':
|
||||
ifname = optarg;
|
||||
break;
|
||||
@ -440,54 +451,54 @@ int main(int argc, char *argv[])
|
||||
wpa_debug_timestamp = 1;
|
||||
break;
|
||||
case 'T':
|
||||
if (add_ptk_file(&wt, optarg) < 0)
|
||||
return -1;
|
||||
if (add_ptk_file(&wt, optarg) < 0) {
|
||||
ret = -1;
|
||||
goto deinit;
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
wt.write_file = optarg;
|
||||
break;
|
||||
case 'W':
|
||||
if (add_wep(&wt, optarg) < 0)
|
||||
return -1;
|
||||
if (add_wep(&wt, optarg) < 0) {
|
||||
ret = -1;
|
||||
goto deinit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto deinit;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifname == NULL && ifname_wired == NULL &&
|
||||
read_file == NULL && read_wired_file == NULL) {
|
||||
usage();
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
if (eloop_init())
|
||||
return -1;
|
||||
if (eloop_init()) {
|
||||
ret = -1;
|
||||
goto deinit;
|
||||
}
|
||||
eloop_init_done = true;
|
||||
|
||||
if (logfile)
|
||||
wpa_debug_open_file(logfile);
|
||||
|
||||
if (wt.write_file && write_pcap_init(&wt, wt.write_file) < 0)
|
||||
return -1;
|
||||
|
||||
if (wt.pcapng_file && write_pcapng_init(&wt, wt.pcapng_file) < 0)
|
||||
return -1;
|
||||
|
||||
if (read_wired_file && read_wired_cap_file(&wt, read_wired_file) < 0)
|
||||
return -1;
|
||||
|
||||
if (read_file && read_cap_file(&wt, read_file) < 0)
|
||||
return -1;
|
||||
|
||||
if (ifname && monitor_init(&wt, ifname) < 0)
|
||||
return -1;
|
||||
|
||||
if (ifname_wired && monitor_init_wired(&wt, ifname_wired) < 0)
|
||||
return -1;
|
||||
|
||||
if (ctrl_iface && ctrl_init(&wt) < 0)
|
||||
return -1;
|
||||
if ((wt.write_file && write_pcap_init(&wt, wt.write_file) < 0) ||
|
||||
(wt.pcapng_file && write_pcapng_init(&wt, wt.pcapng_file) < 0) ||
|
||||
(read_wired_file &&
|
||||
read_wired_cap_file(&wt, read_wired_file) < 0) ||
|
||||
(read_file && read_cap_file(&wt, read_file) < 0) ||
|
||||
(ifname && monitor_init(&wt, ifname) < 0) ||
|
||||
(ifname_wired && monitor_init_wired(&wt, ifname_wired) < 0) ||
|
||||
(ctrl_iface && ctrl_init(&wt) < 0)) {
|
||||
ret = -1;
|
||||
goto deinit;
|
||||
}
|
||||
|
||||
eloop_register_signal_terminate(wlantest_terminate, &wt);
|
||||
|
||||
@ -497,11 +508,13 @@ int main(int argc, char *argv[])
|
||||
"fcs_error=%u",
|
||||
wt.rx_mgmt, wt.rx_ctrl, wt.rx_data, wt.fcs_error);
|
||||
|
||||
deinit:
|
||||
wlantest_deinit(&wt);
|
||||
|
||||
wpa_debug_close_file();
|
||||
eloop_destroy();
|
||||
if (eloop_init_done)
|
||||
eloop_destroy();
|
||||
os_program_deinit();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
@ -12,25 +12,11 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/edit.h"
|
||||
#include "common/cli.h"
|
||||
#include "wlantest_ctrl.h"
|
||||
|
||||
|
||||
static int get_cmd_arg_num(const char *str, int pos)
|
||||
{
|
||||
int arg = 0, i;
|
||||
|
||||
for (i = 0; i <= pos; i++) {
|
||||
if (str[i] != ' ') {
|
||||
arg++;
|
||||
while (i <= pos && str[i] != ' ')
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg > 0)
|
||||
arg--;
|
||||
return arg;
|
||||
}
|
||||
static void print_help(FILE *stream, const char *cmd);
|
||||
static char ** wlantest_cli_cmd_list(void);
|
||||
|
||||
|
||||
static int get_prev_arg_pos(const char *str, int pos)
|
||||
@ -1566,6 +1552,28 @@ static char ** complete_get_tid(int s, const char *str, int pos)
|
||||
}
|
||||
|
||||
|
||||
static int wlantest_cli_cmd_help(int s, int argc, char *argv[])
|
||||
{
|
||||
print_help(stdout, argc > 0 ? argv[0] : NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char ** wlantest_cli_complete_help(int s, const char *str, int pos)
|
||||
{
|
||||
int arg = get_cmd_arg_num(str, pos);
|
||||
char **res = NULL;
|
||||
|
||||
switch (arg) {
|
||||
case 1:
|
||||
res = wlantest_cli_cmd_list();
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
struct wlantest_cli_cmd {
|
||||
const char *cmd;
|
||||
int (*handler)(int s, int argc, char *argv[]);
|
||||
@ -1623,10 +1631,45 @@ static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
|
||||
{ "get_rx_tid", cmd_get_rx_tid,
|
||||
"<BSSID> <STA> <TID> = get STA RX TID counter value",
|
||||
complete_get_tid },
|
||||
{ "help", wlantest_cli_cmd_help,
|
||||
"= show this usage help", wlantest_cli_complete_help },
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Prints command usage, lines are padded with the specified string.
|
||||
*/
|
||||
static void print_cmd_help(FILE *stream, const struct wlantest_cli_cmd *cmd,
|
||||
const char *pad)
|
||||
{
|
||||
char c;
|
||||
size_t n;
|
||||
|
||||
if (!cmd->usage)
|
||||
return;
|
||||
fprintf(stream, "%s%s ", pad, cmd->cmd);
|
||||
for (n = 0; (c = cmd->usage[n]); n++) {
|
||||
fprintf(stream, "%c", c);
|
||||
if (c == '\n')
|
||||
fprintf(stream, "%s", pad);
|
||||
}
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
|
||||
|
||||
static void print_help(FILE *stream, const char *cmd)
|
||||
{
|
||||
int n;
|
||||
|
||||
fprintf(stream, "commands:\n");
|
||||
for (n = 0; wlantest_cli_commands[n].cmd; n++) {
|
||||
if (!cmd || str_starts(wlantest_cli_commands[n].cmd, cmd))
|
||||
print_cmd_help(stream, &wlantest_cli_commands[n], " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ctrl_command(int s, int argc, char *argv[])
|
||||
{
|
||||
const struct wlantest_cli_cmd *cmd, *match = NULL;
|
||||
@ -1672,38 +1715,6 @@ struct wlantest_cli {
|
||||
};
|
||||
|
||||
|
||||
#define max_args 10
|
||||
|
||||
static int tokenize_cmd(char *cmd, char *argv[])
|
||||
{
|
||||
char *pos;
|
||||
int argc = 0;
|
||||
|
||||
pos = cmd;
|
||||
for (;;) {
|
||||
while (*pos == ' ')
|
||||
pos++;
|
||||
if (*pos == '\0')
|
||||
break;
|
||||
argv[argc] = pos;
|
||||
argc++;
|
||||
if (argc == max_args)
|
||||
break;
|
||||
if (*pos == '"') {
|
||||
char *pos2 = os_strrchr(pos, '"');
|
||||
if (pos2)
|
||||
pos = pos2 + 1;
|
||||
}
|
||||
while (*pos != '\0' && *pos != ' ')
|
||||
pos++;
|
||||
if (*pos == ' ')
|
||||
*pos++ = '\0';
|
||||
}
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
|
||||
static void wlantest_cli_edit_cmd_cb(void *ctx, char *cmd)
|
||||
{
|
||||
struct wlantest_cli *cli = ctx;
|
||||
|
@ -279,6 +279,9 @@ NEED_ASN1=y
|
||||
ifdef CONFIG_DPP2
|
||||
L_CFLAGS += -DCONFIG_DPP2
|
||||
endif
|
||||
ifdef CONFIG_DPP3
|
||||
L_CFLAGS += -DCONFIG_DPP3
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_OWE
|
||||
|
@ -294,6 +294,9 @@ NEED_ASN1=y
|
||||
ifdef CONFIG_DPP2
|
||||
CFLAGS += -DCONFIG_DPP2
|
||||
endif
|
||||
ifdef CONFIG_DPP3
|
||||
CFLAGS += -DCONFIG_DPP3
|
||||
endif
|
||||
endif
|
||||
|
||||
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
|
||||
#
|
||||
# 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:
|
||||
#
|
||||
#cred={
|
||||
|
@ -2527,6 +2527,7 @@ static const struct parse_data ssid_fields[] = {
|
||||
#ifdef CONFIG_MESH
|
||||
{ INT_RANGE(mode, 0, 5) },
|
||||
{ INT_RANGE(no_auto_peer, 0, 1) },
|
||||
{ INT_RANGE(mesh_fwding, 0, 1) },
|
||||
{ INT_RANGE(mesh_rssi_threshold, -255, 1) },
|
||||
#else /* CONFIG_MESH */
|
||||
{ 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->private_key);
|
||||
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);
|
||||
str_clear_free(cred->milenage);
|
||||
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->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
|
||||
ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
|
||||
ssid->mesh_fwding = DEFAULT_MESH_FWDING;
|
||||
ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
|
||||
#endif /* CONFIG_MESH */
|
||||
#ifdef CONFIG_HT_OVERRIDES
|
||||
@ -3618,6 +3624,11 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (os_strcmp(var, "engine") == 0) {
|
||||
cred->engine = atoi(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = wpa_config_parse_string(value, &len);
|
||||
if (val == NULL ||
|
||||
(os_strcmp(var, "excluded_ssid") != 0 &&
|
||||
@ -3673,6 +3684,30 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
|
||||
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) {
|
||||
os_free(cred->imsi);
|
||||
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->max_peer_links = DEFAULT_MAX_PEER_LINKS;
|
||||
config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
|
||||
config->mesh_fwding = DEFAULT_MESH_FWDING;
|
||||
config->dot11RSNASAERetransPeriod =
|
||||
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
|
||||
config->fast_reauth = DEFAULT_FAST_REAUTH;
|
||||
@ -5062,6 +5098,7 @@ static const struct global_parse_data global_fields[] = {
|
||||
{ INT(user_mpm), 0 },
|
||||
{ INT_RANGE(max_peer_links, 0, 255), 0 },
|
||||
{ INT(mesh_max_inactivity), 0 },
|
||||
{ INT_RANGE(mesh_fwding, 0, 1), 0 },
|
||||
{ INT(dot11RSNASAERetransPeriod), 0 },
|
||||
#endif /* CONFIG_MESH */
|
||||
{ INT(disable_scan_offload), 0 },
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define DEFAULT_USER_MPM 1
|
||||
#define DEFAULT_MAX_PEER_LINKS 99
|
||||
#define DEFAULT_MESH_MAX_INACTIVITY 300
|
||||
#define DEFAULT_MESH_FWDING 1
|
||||
/*
|
||||
* The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard,
|
||||
* but use 1000 ms in practice to avoid issues on low power CPUs.
|
||||
@ -179,6 +180,31 @@ struct wpa_cred {
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -1388,6 +1414,14 @@ struct wpa_config {
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
@ -769,6 +769,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
||||
#endif /* IEEE8021X_EAPOL */
|
||||
INT(mode);
|
||||
INT(no_auto_peer);
|
||||
INT(mesh_fwding);
|
||||
INT(frequency);
|
||||
INT(enable_edmg);
|
||||
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)
|
||||
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",
|
||||
config->mesh_max_inactivity);
|
||||
|
||||
if (config->mesh_fwding != DEFAULT_MESH_FWDING)
|
||||
fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding);
|
||||
|
||||
if (config->dot11RSNASAERetransPeriod !=
|
||||
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
|
||||
fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
|
||||
|
@ -549,6 +549,11 @@ struct wpa_ssid {
|
||||
int dot11MeshConfirmTimeout; /* msec */
|
||||
int dot11MeshHoldingTimeout; /* msec */
|
||||
|
||||
/**
|
||||
* Mesh network layer-2 forwarding (dot11MeshForwarding)
|
||||
*/
|
||||
int mesh_fwding;
|
||||
|
||||
int ht;
|
||||
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,
|
||||
char *cmd)
|
||||
{
|
||||
@ -3844,13 +3803,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
||||
* "provisioning_sp=<FQDN> */
|
||||
if (os_strcmp(cmd, "all") == 0) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
|
||||
cred = wpa_s->conf->cred;
|
||||
while (cred) {
|
||||
prev = cred;
|
||||
cred = cred->next;
|
||||
wpas_ctrl_remove_cred(wpa_s, prev);
|
||||
}
|
||||
return 0;
|
||||
return wpas_remove_all_creds(wpa_s);
|
||||
}
|
||||
|
||||
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)
|
||||
!= 0)
|
||||
continue;
|
||||
wpas_ctrl_remove_cred(wpa_s, prev);
|
||||
wpas_remove_cred(wpa_s, prev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3883,7 +3836,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
|
||||
cred = cred->next;
|
||||
if (prev->provisioning_sp &&
|
||||
os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
|
||||
wpas_ctrl_remove_cred(wpa_s, prev);
|
||||
wpas_remove_cred(wpa_s, prev);
|
||||
}
|
||||
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);
|
||||
|
||||
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
|
||||
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");
|
||||
#else /* CONFIG_DPP2 */
|
||||
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_protocol_key_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;
|
||||
#else /* CONFIG_DPP2 */
|
||||
dpp_version_override = 1;
|
||||
|
@ -937,6 +937,95 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
#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,
|
||||
int depth, const char *subject,
|
||||
const char *altsubject[],
|
||||
@ -3570,6 +3659,35 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
|
||||
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 } }
|
||||
};
|
||||
|
||||
@ -4137,6 +4255,21 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
|
||||
}
|
||||
},
|
||||
#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 } }
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
struct wpa_global;
|
||||
struct wpa_supplicant;
|
||||
struct wpa_ssid;
|
||||
struct wpa_cred;
|
||||
struct wpa_bss;
|
||||
struct wps_event_m2d;
|
||||
struct wps_event_fail;
|
||||
struct wps_credential;
|
||||
@ -96,6 +98,9 @@ enum wpas_dbus_sta_prop {
|
||||
#define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers"
|
||||
#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 */
|
||||
#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
|
||||
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);
|
||||
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
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 */
|
||||
|
||||
@ -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 /* CTRL_IFACE_DBUS_H_NEW */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "../scan.h"
|
||||
#include "../autoscan.h"
|
||||
#include "../ap.h"
|
||||
#include "../interworking.h"
|
||||
#include "dbus_new_helpers.h"
|
||||
#include "dbus_new.h"
|
||||
#include "dbus_new_handlers.h"
|
||||
@ -148,6 +149,9 @@ static const char * const dont_quote[] = {
|
||||
#ifdef CONFIG_P2P
|
||||
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
"roaming_consortium", "required_roaming_consortium",
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
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
|
||||
* @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
|
||||
* @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,
|
||||
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_state);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
|
||||
|
@ -744,6 +744,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
|
||||
unsigned int group_id = 0;
|
||||
int persistent = 0;
|
||||
struct wpa_ssid *ssid;
|
||||
const char *group_ifname;
|
||||
|
||||
if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
|
||||
return reply;
|
||||
@ -777,6 +778,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
|
||||
!p2p_peer_known(wpa_s->global->p2p, peer_addr))
|
||||
goto err;
|
||||
|
||||
/* Capture the interface name for the group first */
|
||||
group_ifname = wpa_s->ifname;
|
||||
wpa_s = wpa_s->global->p2p_init_wpa_s;
|
||||
|
||||
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
|
||||
*/
|
||||
if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
|
||||
if (wpas_p2p_invite_group(wpa_s, group_ifname,
|
||||
peer_addr, NULL, false)) {
|
||||
reply = wpas_dbus_error_unknown_error(
|
||||
message, "Failed to join to an active group");
|
||||
|
@ -603,8 +603,13 @@ CONFIG_BGSCAN_SIMPLE=y
|
||||
# Experimental implementation of draft-harkins-owe-07.txt
|
||||
#CONFIG_OWE=y
|
||||
|
||||
# Device Provisioning Protocol (DPP)
|
||||
# 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
|
||||
|
||||
# Wired equivalent privacy (WEP)
|
||||
# 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_s->dpp_listen_freq = 0;
|
||||
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);
|
||||
if (version && version_len >= 1)
|
||||
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;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
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)",
|
||||
pkex->exch_req_tries);
|
||||
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,
|
||||
wpa_s->own_addr, broadcast,
|
||||
wpabuf_head(pkex->exchange_req),
|
||||
@ -2627,7 +2640,8 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
||||
|
||||
static void
|
||||
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;
|
||||
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->dpp_pkex_identifier,
|
||||
wpa_s->dpp_pkex_code,
|
||||
buf, len);
|
||||
buf, len, v2);
|
||||
if (!wpa_s->dpp_pkex) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"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:
|
||||
wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
|
||||
break;
|
||||
#ifdef CONFIG_DPP3
|
||||
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;
|
||||
case DPP_PA_PKEX_EXCHANGE_RESP:
|
||||
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
|
||||
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 */
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
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 */
|
||||
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||
wpabuf_put_le16(msg, 1);
|
||||
wpabuf_put_u8(msg, DPP_VERSION);
|
||||
wpabuf_put_u8(msg, ver);
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
skip_proto_ver:
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
/* TODO: Timeout on AP response */
|
||||
wait_time = wpa_s->max_remain_on_chan;
|
||||
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)
|
||||
return -1;
|
||||
|
||||
if (os_strstr(cmd, " init=1")) {
|
||||
if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) {
|
||||
struct dpp_pkex *pkex;
|
||||
struct wpabuf *msg;
|
||||
bool v2 = os_strstr(cmd, " init=2") != NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Initiating 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_identifier,
|
||||
wpa_s->dpp_pkex_code);
|
||||
wpa_s->dpp_pkex_code, v2);
|
||||
pkex = wpa_s->dpp_pkex;
|
||||
if (!pkex)
|
||||
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
|
||||
" freq=%u type=%d",
|
||||
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,
|
||||
wpa_s->own_addr, broadcast,
|
||||
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)
|
||||
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;
|
||||
|
||||
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[0] == '\0') &&
|
||||
(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,
|
||||
"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->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;
|
||||
}
|
||||
|
||||
@ -716,7 +718,8 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
|
||||
if (cred->password && cred->password[0] &&
|
||||
nai_realm_cred_username(wpa_s, 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))
|
||||
return eap;
|
||||
}
|
||||
@ -1539,6 +1542,24 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
|
||||
cred->private_key_passwd) < 0)
|
||||
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) {
|
||||
os_free(ssid->eap.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);
|
||||
bss_load = cred_over_max_bss_load(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",
|
||||
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_notify_interworking_ap_added(wpa_s, bss, cred, excluded,
|
||||
type, bh, bss_load,
|
||||
conn_capab);
|
||||
if (excluded)
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
|
||||
wpas_notify_interworking_select_done(wpa_s);
|
||||
|
||||
if (selected) {
|
||||
wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR,
|
||||
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_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
|
||||
conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
|
||||
conf->mesh_fwding = ssid->mesh_fwding;
|
||||
conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
|
||||
conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
|
||||
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->mesh = MESH_ENABLED;
|
||||
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,
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
wpa_s->mesh_params = params;
|
||||
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;
|
||||
/* TODO: Add Connected to Mesh Gate/AS subfields */
|
||||
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 |
|
||||
MESH_CAP_FORWARDING);
|
||||
(conf->mesh_fwding ? MESH_CAP_FORWARDING : 0));
|
||||
} else { /* Peer closing frame */
|
||||
/* IE: Mesh ID */
|
||||
wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "rsn_supp/wpa.h"
|
||||
#include "fst/fst.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "bss.h"
|
||||
#include "driver_i.h"
|
||||
#include "scan.h"
|
||||
#include "p2p_supplicant.h"
|
||||
@ -943,3 +944,32 @@ void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
}
|
||||
|
||||
#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_fail;
|
||||
struct tls_cert_data;
|
||||
struct wpa_cred;
|
||||
|
||||
int wpas_notify_supplicant_initialized(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);
|
||||
void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
|
||||
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 */
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/ocv.h"
|
||||
#include "common/hw_features_common.h"
|
||||
#include "eapol_supp/eapol_supp_sm.h"
|
||||
#include "common/wpa_common.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);
|
||||
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) {
|
||||
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,
|
||||
struct wpa_scan_results *scan_res)
|
||||
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wpa_bss *bss;
|
||||
const u8 *ie;
|
||||
u16 ht_cap;
|
||||
u8 chan_list[P2P_MAX_CHANNELS], channel;
|
||||
u8 num_channels = 0, num_intol = 0, i;
|
||||
size_t j;
|
||||
int pri_freq, sec_freq;
|
||||
|
||||
if (!wpa_s->sme.sched_obss_scan)
|
||||
return 0;
|
||||
@ -2415,36 +2419,22 @@ int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
|
||||
|
||||
os_memset(chan_list, 0, sizeof(chan_list));
|
||||
|
||||
pri_freq = wpa_s->assoc_freq;
|
||||
|
||||
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;
|
||||
|
||||
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||
/* Skip other band bss */
|
||||
enum hostapd_hw_mode mode;
|
||||
mode = ieee80211_freq_to_chan(bss->freq, &channel);
|
||||
if (mode != HOSTAPD_MODE_IEEE80211G &&
|
||||
mode != HOSTAPD_MODE_IEEE80211B)
|
||||
continue;
|
||||
|
||||
res = check_bss_coex_40mhz(bss, pri_freq, sec_freq);
|
||||
if (res) {
|
||||
if (res == 2)
|
||||
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
|
||||
ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
|
||||
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++;
|
||||
|
||||
/* 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)
|
||||
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)
|
||||
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_deinit(struct wpa_supplicant *wpa_s);
|
||||
|
||||
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_scan_results *scan_res);
|
||||
int sme_proc_obss_scan(struct wpa_supplicant *wpa_s);
|
||||
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
|
||||
void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
|
||||
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,
|
||||
struct wpa_scan_results *scan_res)
|
||||
static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1591,6 +1591,7 @@ static const char * const cred_fields[] = {
|
||||
"min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
|
||||
"req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
|
||||
"ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
|
||||
"ca_cert_id", "cert_id", "key_id", "engine_id", "engine",
|
||||
"milenage", "domain_suffix_match", "domain", "phase1", "phase2",
|
||||
"roaming_consortium", "required_roaming_consortium", "excluded_ssid",
|
||||
"roaming_partner", "provisioning_sp"
|
||||
|
@ -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
|
||||
* @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.
|
||||
#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
|
||||
# This controls whether peer certificates for authentication server and
|
||||
# its certificate chain are included in EAP peer certificate events. This is
|
||||
|
@ -38,6 +38,7 @@ struct wpa_bss;
|
||||
struct wpa_scan_results;
|
||||
struct hostapd_hw_modes;
|
||||
struct wpa_driver_associate_params;
|
||||
struct wpa_cred;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
|
||||
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,
|
||||
const char *pkcs11_engine_path,
|
||||
const char *pkcs11_module_path);
|
||||
|
Loading…
Reference in New Issue
Block a user