From patchwork Wed Oct 3 01:34:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Igor Mitsyanko X-Patchwork-Id: 978101 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=quantenna.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="IlVupRTW"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42PzM25xxFz9s3x for ; Wed, 3 Oct 2018 11:43:42 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=v1/XugStl6HsMAdUT7jIMENbLV0lGAX0m90p7dmyK78=; b=IlVupRTWSOq7tw Nx8F3he7GKKqeeNjFidJMs/49mn+SR9l08YPzHteU2iC6xYU9aQWQKG2DGycZAtBuRMQbE3fJMi7G d2w1Q+tqmRZKpJpD4rjMqHMWlgb1+ZmcCrUyVC8ZWu56nk2OvFdgiNKr6+5YsA3+a/GR2fGP5X6aI CbUIlB9ycrGlDnVuOtCHUANOSPhT+8nT+lvBOz0LCG0Ef5b+L8HMJj8VBiwHrZ2KUDCOTnTLC+gZf d8hadmhKj7mPrkvF4Im/BPvaUNdZ+2KZZomE9m5wPYrMfITdendKOk7BOuU55AsnI3HykANUrwBW0 E7KD+10Ne0MMoMdb/sUw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g7WC8-0001mV-VG; Wed, 03 Oct 2018 01:43:20 +0000 Received: from [12.131.200.82] (helo=fm-smtp01.quantenna.com) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g7WC6-0001kC-8S for hostap@lists.infradead.org; Wed, 03 Oct 2018 01:43:20 +0000 Received: from dodo-dell.quantenna.com ([10.10.23.208]) by fm-smtp01.quantenna.com (8.14.4/8.14.4) with ESMTP id w931YWM6003902; Tue, 2 Oct 2018 18:34:32 -0700 From: Igor Mitsyanko To: hostap@lists.infradead.org Subject: [PATCH] easymesh: add backhaul BSS support for WPS M8 Date: Tue, 2 Oct 2018 18:34:14 -0700 Message-Id: <20181003013414.32234-1-igor.mitsyanko.os@quantenna.com> X-Mailer: git-send-email 2.9.5 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181002_184318_354218_C8228F0A X-CRM114-Status: GOOD ( 20.04 ) X-Spam-Score: 1.3 (+) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (1.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Igor Mitsyanko , mcarrera@quantenna.com, wouter@e2big.org, arnout@mind.be, ylu@quantenna.com Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Ying Lu This patch adds a feature similar to the existing “Additional Credential attribute(s)” (extra_cred), relating to the requirements of Wi-Fi Alliance Multi-AP Specification v1.0 (WFA EasyMesh). These specs can be found at https://www.wi-fi.org/file/multi-ap-specification-v10. They mandate that a “fronthaul” BSS, that is pairing a client that has bit 7 of the Multi-AP Extension subelement in the Wi-Fi Alliance Vendor Extension attribute in the WSC M1 message, shall configure such client with credentials pertaining to the “backhaul” BSS. Therefore we introduce two new configuration options (wps_cred_processing_easymesh and easymesh_backhaul_ap_settings) that behave like the existing extra_cred, except for the additional check on the content of M1. Configuring these options will be done by a “MultiAP Agent”, an open-source implementation of such agent is work in progress at https://github.com/prplfoundation/prplMesh. Signed-off-by: Davina Lu Signed-off-by: Igor Mitsyanko reviewed-by: Marianna Carrera --- hostapd/config_file.c | 12 ++++++++++++ hostapd/hostapd.conf | 11 +++++++++++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 3 +++ src/wps/wps.h | 36 ++++++++++++++++++++++++++++++++++++ src/wps/wps_attr_parse.c | 10 ++++++++++ src/wps/wps_attr_parse.h | 1 + src/wps/wps_defs.h | 9 ++++++++- src/wps/wps_dev_attr.c | 5 +++++ src/wps/wps_dev_attr.h | 1 + src/wps/wps_registrar.c | 17 +++++++++++++++++ 11 files changed, 105 insertions(+), 1 deletion(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index b1ab13e..581c634 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3457,6 +3457,18 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, pos); return 1; } + } else if (os_strcmp(buf, "easymesh_backhaul_ap_settings") == 0) { + os_free(bss->easymesh_backhaul_ap_settings); + bss->easymesh_backhaul_ap_settings = + (u8 *) os_readfile(pos, &bss->easymesh_backhaul_ap_settings_len); + if (bss->easymesh_backhaul_ap_settings == NULL) { + wpa_printf(MSG_ERROR, + "Line %d: couldn't read EASYMESH backhaul AP Settings from '%s'", + line, pos); + return 1; + } + } else if (os_strcmp(buf, "wps_cred_processing_easymesh") == 0) { + bss->wps_cred_processing_easymesh = atoi(pos); } else if (os_strcmp(buf, "upnp_iface") == 0) { os_free(bss->upnp_iface); bss->upnp_iface = os_strdup(pos); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 70f9713..c7946e6 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1845,6 +1845,17 @@ own_ip_addr=127.0.0.1 # attribute. #ap_settings=hostapd.ap_settings +# Easy mesh AP config +# when set to 1, hostapd uses the credentials in the file specified by +# easymesh_backhaul_ap_settings config, only for those STAs that advertise +# "backhaul STA" in M1's EASYMESH Extension subelement. +#wps_cred_processing_easymesh=0 + +# Easy mesh AP backhaul BSS config +# Used when wps_cred_processing_easymesh is set. Contains "backhaul BSS" +# credentials. +#easymesh_backhaul_ap_settings=hostapd.easymesh_settings + # WPS UPnP interface # If set, support for external Registrars is enabled. #upnp_iface=br0 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 820cba9..197f229 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -582,6 +582,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) os_free(conf->ap_pin); os_free(conf->extra_cred); os_free(conf->ap_settings); + os_free(conf->easymesh_backhaul_ap_settings); os_free(conf->upnp_iface); os_free(conf->friendly_name); os_free(conf->manufacturer_url); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 5b71126..c7b903d 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -455,6 +455,9 @@ struct hostapd_bss_config { int force_per_enrollee_psk; u8 *ap_settings; size_t ap_settings_len; + u8 *easymesh_backhaul_ap_settings; + size_t easymesh_backhaul_ap_settings_len; + int wps_cred_processing_easymesh; char *upnp_iface; char *friendly_name; char *manufacturer_url; diff --git a/src/wps/wps.h b/src/wps/wps.h index 2505d2d..2a685b2 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -100,6 +100,7 @@ struct wps_device_data { struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; int p2p; + u8 easymesh_ext; }; /** @@ -395,6 +396,16 @@ struct wps_registrar_config { * PSK is set for a network. */ int force_per_enrollee_psk; + + /** + * wps_cred_processing_easymesh: build credential with backhaul BSS + * + * This option can be used to disable internal code that builds + * Credential attribute into M8 based on the current network + * configuration and Enrollee capabilities. The extra_cred data will + * then be used as the Credential(s). + */ + int wps_cred_processing_easymesh; }; @@ -799,6 +810,31 @@ struct wps_context { struct wpabuf *ap_nfc_dh_pubkey; struct wpabuf *ap_nfc_dh_privkey; struct wpabuf *ap_nfc_dev_pw; + + /** + * wps_cred_processing_easymesh: build credential with backhaul BSS + * + * This option can be used to disable internal code that builds + * Credential attribute into M8 based on the current network + * configuration and Enrollee capabilities. The extra_cred data will + * then be used as the Credential(s). + */ + int wps_cred_processing_easymesh; + + /** + * easymesh_backhaul_ap_settings: EASY mesh backhaul BSS config + * + * This optional data (set to NULL to disable) can be used to add + * Credential attribute(s) for other networks into M8. If + * wps_cred_processing_easymesh is set, this will also override the automatically + * generated Credential attribute. + */ + const u8 *easymesh_backhaul_ap_settings; + + /** + * easymesh_backhaul_ap_settings_len: Length of easymesh_backhaul_ap_settings in octets + */ + size_t easymesh_backhaul_ap_settings_len; }; struct wps_registrar * diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c index 756d57e..4cb7db6 100644 --- a/src/wps/wps_attr_parse.c +++ b/src/wps/wps_attr_parse.c @@ -67,6 +67,16 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, } attr->registrar_configuration_methods = pos; break; + case WFA_ELEM_EASYMESH_EXTENSION: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid EASYMESH Extension length " + "%u", len); + return -1; + } + attr->easymesh_ext = *pos; + wpa_printf(MSG_DEBUG, "WPS: EASYMESH Extension " + "%x", attr->easymesh_ext); + break; default: wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor " "Extension subelement %u", id); diff --git a/src/wps/wps_attr_parse.h b/src/wps/wps_attr_parse.h index 8188fe9..a47fd62 100644 --- a/src/wps/wps_attr_parse.h +++ b/src/wps/wps_attr_parse.h @@ -97,6 +97,7 @@ struct wps_parse_attr { const u8 *cred[MAX_CRED_COUNT]; const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT]; + u8 easymesh_ext; }; int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h index 301864d..ef76571 100644 --- a/src/wps/wps_defs.h +++ b/src/wps/wps_defs.h @@ -152,9 +152,16 @@ enum { WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02, WFA_ELEM_REQUEST_TO_ENROLL = 0x03, WFA_ELEM_SETTINGS_DELAY_TIME = 0x04, - WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05 + WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05, + WFA_ELEM_EASYMESH_EXTENSION = 0x06 }; +/* Multi-AP extension subelement value */ +#define EASYMESH_TEAR_DOWN 0x10 +#define EASYMESH_FRONTHAUL_BSS 0x20 +#define EASYMESH_BACKHAUL_BSS 0x40 +#define EASYMESH_BACKHAUL_STA 0x80 + /* Device Password ID */ enum wps_dev_password_id { DEV_PW_DEFAULT = 0x0000, diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c index 0d01211..ccea68d 100644 --- a/src/wps/wps_dev_attr.c +++ b/src/wps/wps_dev_attr.c @@ -389,6 +389,11 @@ int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) return 0; } +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext) +{ + dev->easymesh_ext = ext; + wpa_printf(MSG_DEBUG, "WPS: EASYMESH extension value %02x", dev->easymesh_ext); +} int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) { diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h index c9034ad..a4b4173 100644 --- a/src/wps/wps_dev_attr.h +++ b/src/wps/wps_dev_attr.h @@ -29,6 +29,7 @@ int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr); int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext); int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); void wps_device_data_free(struct wps_device_data *dev); int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 379925e..93e4b8a 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -188,6 +188,7 @@ struct wps_registrar { #ifdef WPS_WORKAROUNDS struct os_reltime pbc_ignore_start; #endif /* WPS_WORKAROUNDS */ + int wps_cred_processing_easymesh; }; @@ -666,6 +667,7 @@ wps_registrar_init(struct wps_context *wps, reg->static_wep_only = cfg->static_wep_only; reg->dualband = cfg->dualband; reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk; + reg->wps_cred_processing_easymesh = cfg->wps_cred_processing_easymesh; if (wps_set_ie(reg)) { wps_registrar_deinit(reg); @@ -1588,6 +1590,15 @@ int wps_build_credential_wrap(struct wpabuf *msg, return 0; } +static int wps_build_easymesh_backhual_ap_settings(struct wps_data *wps, struct wpabuf *msg) +{ + wpabuf_put_data(msg, wps->wps->easymesh_backhaul_ap_settings, + wps->wps->easymesh_backhaul_ap_settings_len); + wpa_printf(MSG_DEBUG, "WPS: EASYMESH mesh backhaul BSS config len %lu=%lu\n", + wpabuf_len(msg), + wps->wps->easymesh_backhaul_ap_settings_len); + return 0; +} int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) { @@ -1596,6 +1607,11 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) if (wps->wps->registrar->skip_cred_build) goto skip_cred_build; + if (wps->wps->registrar->wps_cred_processing_easymesh && + wps->peer_dev.easymesh_ext == EASYMESH_BACKHAUL_STA && + wps->wps->easymesh_backhaul_ap_settings) + return wps_build_easymesh_backhual_ap_settings(wps, msg); + wpa_printf(MSG_DEBUG, "WPS: * Credential"); if (wps->use_cred) { os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred)); @@ -2705,6 +2721,7 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, wps->use_psk_key = 1; } #endif /* WPS_WORKAROUNDS */ + wps_process_vendor_ext_m1(&wps->peer_dev, attr->easymesh_ext); wps->state = SEND_M2; return WPS_CONTINUE;