aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa/wpa_supplicant
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/wpa_supplicant')
-rw-r--r--contrib/wpa/wpa_supplicant/Android.mk3
-rw-r--r--contrib/wpa/wpa_supplicant/Makefile3
-rw-r--r--contrib/wpa/wpa_supplicant/README-HS206
-rw-r--r--contrib/wpa/wpa_supplicant/config.c37
-rw-r--r--contrib/wpa/wpa_supplicant/config.h34
-rw-r--r--contrib/wpa/wpa_supplicant/config_file.c15
-rw-r--r--contrib/wpa/wpa_supplicant/config_ssid.h5
-rw-r--r--contrib/wpa/wpa_supplicant/ctrl_iface.c63
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new.c133
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new.h27
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c287
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h13
-rw-r--r--contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c5
-rw-r--r--contrib/wpa/wpa_supplicant/defconfig7
-rw-r--r--contrib/wpa/wpa_supplicant/dpp_supplicant.c62
-rw-r--r--contrib/wpa/wpa_supplicant/events.c2
-rw-r--r--contrib/wpa/wpa_supplicant/interworking.c41
-rw-r--r--contrib/wpa/wpa_supplicant/mesh.c6
-rw-r--r--contrib/wpa/wpa_supplicant/mesh_mpm.c5
-rw-r--r--contrib/wpa/wpa_supplicant/notify.c30
-rw-r--r--contrib/wpa/wpa_supplicant/notify.h7
-rw-r--r--contrib/wpa/wpa_supplicant/sme.c54
-rw-r--r--contrib/wpa/wpa_supplicant/sme.h6
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_cli.c1
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant.c76
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant.conf3
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant_i.h3
27 files changed, 824 insertions, 110 deletions
diff --git a/contrib/wpa/wpa_supplicant/Android.mk b/contrib/wpa/wpa_supplicant/Android.mk
index 0aacafd4ab96..7e597f396a07 100644
--- a/contrib/wpa/wpa_supplicant/Android.mk
+++ b/contrib/wpa/wpa_supplicant/Android.mk
@@ -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
diff --git a/contrib/wpa/wpa_supplicant/Makefile b/contrib/wpa/wpa_supplicant/Makefile
index ce1c8b2e3366..cb66defac7c8 100644
--- a/contrib/wpa/wpa_supplicant/Makefile
+++ b/contrib/wpa/wpa_supplicant/Makefile
@@ -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
diff --git a/contrib/wpa/wpa_supplicant/README-HS20 b/contrib/wpa/wpa_supplicant/README-HS20
index 484e4cbf4724..b076621db527 100644
--- a/contrib/wpa/wpa_supplicant/README-HS20
+++ b/contrib/wpa/wpa_supplicant/README-HS20
@@ -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={
diff --git a/contrib/wpa/wpa_supplicant/config.c b/contrib/wpa/wpa_supplicant/config.c
index c5177d915524..bf062b0792b7 100644
--- a/contrib/wpa/wpa_supplicant/config.c
+++ b/contrib/wpa/wpa_supplicant/config.c
@@ -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 },
diff --git a/contrib/wpa/wpa_supplicant/config.h b/contrib/wpa/wpa_supplicant/config.h
index 0320d9eebb57..d22ef05fb8ba 100644
--- a/contrib/wpa/wpa_supplicant/config.h
+++ b/contrib/wpa/wpa_supplicant/config.h
@@ -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.
@@ -180,6 +181,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
*
* If set, this FQDN is used as a suffix match requirement for the AAA
@@ -1389,6 +1415,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
*
* This timeout value is used in mesh STA to retransmit
diff --git a/contrib/wpa/wpa_supplicant/config_file.c b/contrib/wpa/wpa_supplicant/config_file.c
index 54fb72d8c1f7..6db5010db3a7 100644
--- a/contrib/wpa/wpa_supplicant/config_file.c
+++ b/contrib/wpa/wpa_supplicant/config_file.c
@@ -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",
diff --git a/contrib/wpa/wpa_supplicant/config_ssid.h b/contrib/wpa/wpa_supplicant/config_ssid.h
index 339eead1c333..724534dd0123 100644
--- a/contrib/wpa/wpa_supplicant/config_ssid.h
+++ b/contrib/wpa/wpa_supplicant/config_ssid.h
@@ -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;
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface.c b/contrib/wpa/wpa_supplicant/ctrl_iface.c
index 9dc17f5eef85..bcd67fca3e12 100644
--- a/contrib/wpa/wpa_supplicant/ctrl_iface.c
+++ b/contrib/wpa/wpa_supplicant/ctrl_iface.c
@@ -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;
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new.c
index 2c01943f754e..9279ae4d5847 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new.c
@@ -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 } }
};
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
index 42db3892ed77..26bdcb548de8 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new.h
@@ -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 */
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c
index db9f30c9aabf..545e9f64295a 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -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
};
@@ -329,6 +333,110 @@ error:
/**
+ * 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
* @type: DBus type of property (must be basic type)
@@ -1516,6 +1624,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
* @wpa_s: wpa_supplicant structure for a network interface
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h
index c36383f05668..a421083f7fe2 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -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);
diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 565ced0fd7e2..de79178f4655 100644
--- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -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");
diff --git a/contrib/wpa/wpa_supplicant/defconfig b/contrib/wpa/wpa_supplicant/defconfig
index 708a82385170..a4719dbb543d 100644
--- a/contrib/wpa/wpa_supplicant/defconfig
+++ b/contrib/wpa/wpa_supplicant/defconfig
@@ -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
diff --git a/contrib/wpa/wpa_supplicant/dpp_supplicant.c b/contrib/wpa/wpa_supplicant/dpp_supplicant.c
index 40ef8aeb510f..584654a6cb2c 100644
--- a/contrib/wpa/wpa_supplicant/dpp_supplicant.c
+++ b/contrib/wpa/wpa_supplicant/dpp_supplicant.c
@@ -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 @@ skip_trans_id:
#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),
diff --git a/contrib/wpa/wpa_supplicant/events.c b/contrib/wpa/wpa_supplicant/events.c
index 5f5c50ba9754..f55e1846e205 100644
--- a/contrib/wpa/wpa_supplicant/events.c
+++ b/contrib/wpa/wpa_supplicant/events.c
@@ -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 &&
diff --git a/contrib/wpa/wpa_supplicant/interworking.c b/contrib/wpa/wpa_supplicant/interworking.c
index 1c82d2117ab0..71a5c16510d4 100644
--- a/contrib/wpa/wpa_supplicant/interworking.c
+++ b/contrib/wpa/wpa_supplicant/interworking.c
@@ -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));
diff --git a/contrib/wpa/wpa_supplicant/mesh.c b/contrib/wpa/wpa_supplicant/mesh.c
index 7938b8b4903e..d6b8a1ad9e36 100644
--- a/contrib/wpa/wpa_supplicant/mesh.c
+++ b/contrib/wpa/wpa_supplicant/mesh.c
@@ -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, &params->freq)) {
diff --git a/contrib/wpa/wpa_supplicant/mesh_mpm.c b/contrib/wpa/wpa_supplicant/mesh_mpm.c
index 38f0d641a03b..2eb9a7ef6182 100644
--- a/contrib/wpa/wpa_supplicant/mesh_mpm.c
+++ b/contrib/wpa/wpa_supplicant/mesh_mpm.c
@@ -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);
diff --git a/contrib/wpa/wpa_supplicant/notify.c b/contrib/wpa/wpa_supplicant/notify.c
index fe5e072c24c2..821c916c153f 100644
--- a/contrib/wpa/wpa_supplicant/notify.c
+++ b/contrib/wpa/wpa_supplicant/notify.c
@@ -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 */
diff --git a/contrib/wpa/wpa_supplicant/notify.h b/contrib/wpa/wpa_supplicant/notify.h
index e843aa124b39..c46e7986e3b3 100644
--- a/contrib/wpa/wpa_supplicant/notify.h
+++ b/contrib/wpa/wpa_supplicant/notify.h
@@ -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 */
diff --git a/contrib/wpa/wpa_supplicant/sme.c b/contrib/wpa/wpa_supplicant/sme.c
index f2c42ff354e7..1dc7001a7305 100644
--- a/contrib/wpa/wpa_supplicant/sme.c
+++ b/contrib/wpa/wpa_supplicant/sme.c
@@ -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;
diff --git a/contrib/wpa/wpa_supplicant/sme.h b/contrib/wpa/wpa_supplicant/sme.h
index ecbc16dacd9d..c797d2e9e796 100644
--- a/contrib/wpa/wpa_supplicant/sme.h
+++ b/contrib/wpa/wpa_supplicant/sme.h
@@ -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;
}
diff --git a/contrib/wpa/wpa_supplicant/wpa_cli.c b/contrib/wpa/wpa_supplicant/wpa_cli.c
index 075d587be2f1..5bbc4535e364 100644
--- a/contrib/wpa/wpa_supplicant/wpa_cli.c
+++ b/contrib/wpa/wpa_supplicant/wpa_cli.c
@@ -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"
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/contrib/wpa/wpa_supplicant/wpa_supplicant.c
index 71bf95f951a1..53b44035f16e 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant.c
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.c
@@ -4513,6 +4513,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
* @pkcs11_engine_path: PKCS #11 engine path or NULL
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
index fa257f3dec1b..6619d6ba7fb1 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
@@ -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
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
index cbc955159bbe..5fa765fda25c 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
@@ -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);