From patchwork Mon Jul 14 05:19:07 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bob Copeland X-Patchwork-Id: 369493 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) by ozlabs.org (Postfix) with ESMTP id 85E1B14008F for ; Mon, 14 Jul 2014 15:25:37 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 441159D36A; Mon, 14 Jul 2014 01:24:50 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OyBnhyvJBxKm; Mon, 14 Jul 2014 01:24:49 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 3F6F617C076; Mon, 14 Jul 2014 01:21:58 -0400 (EDT) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id C950817C072 for ; Mon, 14 Jul 2014 01:21:56 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YUvOVYMye9xN for ; Mon, 14 Jul 2014 01:21:50 -0400 (EDT) Received: from mail-ig0-f174.google.com (mail-ig0-f174.google.com [209.85.213.174]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (not verified)) by maxx.maxx.shmoo.com (Postfix) with ESMTPS id 1E0009D326 for ; Mon, 14 Jul 2014 01:21:15 -0400 (EDT) Received: by mail-ig0-f174.google.com with SMTP id c1so1361312igq.1 for ; Sun, 13 Jul 2014 22:21:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/KQy8g/Xp0WFW0MJwUwQajhdVLbpKyvX8fhGvec/m6g=; b=WcSJSyz3S1GBYjjy52pc3rCBwI4bz8m8Zb/0iuQbTi+mMGdBxOaR0mehzwa+LI358R eiv1POnfZgZ5FDJ64vLfQbYvjKynaDQqElz91zL1RpvaFa11E8aAHhSP+8BPfwa063CZ 5tY5i1lXe+lIQF72xPtmiLGJX6PQsRh4s42+ZD19P4UwNrpaaBNO8qLOWSXr9R/S9n0W DOV/hbEVtTvT847ltZ2RRKeVBobuxD6QITxiK6QDXczmg/vhVrTslOk41lDiL/yeehvC fxGa7YbnH+fDQUJFjrKM+yEDZOvLwqxaj8oau2n5JfB+vZesy+PikWDo/66gOiskQPKI k5fA== X-Gm-Message-State: ALoCoQl5nw1Dsk4q17grhc2g6dv7qGrqOMx3nB62ooW5Q5nm4Xg4RmqrerNjmS/EeJKI0OhWRKQP X-Received: by 10.50.79.232 with SMTP id m8mr21709606igx.33.1405315274741; Sun, 13 Jul 2014 22:21:14 -0700 (PDT) Received: from hash ([2001:470:1d:6db:230:48ff:fe9d:9c89]) by mx.google.com with ESMTPSA id u6sm4600495igz.21.2014.07.13.22.21.08 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sun, 13 Jul 2014 22:21:09 -0700 (PDT) Received: from glass.local ([192.168.1.51] helo=glass.lan) by hash with esmtp (Exim 4.80) (envelope-from ) id 1X6YhG-0005TF-Ba; Mon, 14 Jul 2014 01:21:06 -0400 Received: from bob by glass.lan with local (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1X6YhG-0002UE-Qk; Mon, 14 Jul 2014 01:21:06 -0400 From: Bob Copeland To: hostap@lists.shmoo.com Subject: [PATCH/RFC 02/18] mesh: add mesh mode routines Date: Mon, 14 Jul 2014 01:19:07 -0400 Message-Id: <1405315163-9492-3-git-send-email-me@bobcopeland.com> X-Mailer: git-send-email 2.0.0.rc2 In-Reply-To: <1405315163-9492-1-git-send-email-me@bobcopeland.com> References: <1405315163-9492-1-git-send-email-me@bobcopeland.com> Cc: devel@lists.open80211s.org, Javier Lopez X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com From: Thomas Pedersen Add routines to (de)initialize mesh interface data structures and join and leave mesh networks. Signed-off-by: Javier Lopez Signed-off-by: Javier Cardona Signed-off-by: Jason Mobarak Signed-hostap: Thomas Pedersen --- wpa_supplicant/mesh.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++ wpa_supplicant/mesh.h | 36 +++++++ 2 files changed, 313 insertions(+) create mode 100644 wpa_supplicant/mesh.c create mode 100644 wpa_supplicant/mesh.h diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c new file mode 100644 index 0000000..5b4f5d9 --- /dev/null +++ b/wpa_supplicant/mesh.c @@ -0,0 +1,277 @@ +/* + * WPA Supplicant - Basic mesh mode routines + * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "mesh.h" + +static void +wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s) +{ + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); + wpa_s->ifmsh = NULL; + /* TODO: leave mesh (stop beacon). This will happen on link down + * anyway, so it's not urgent */ +} + +void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, + struct hostapd_iface *ifmsh) +{ + if (!ifmsh) + return; + + if (ifmsh->mconf) { + if (ifmsh->mconf->ies) + ifmsh->mconf->ies = NULL; + /* We cannot free this struct + * because wpa_authenticator on + * hostapd side is also using it + * for now just set to NULL and + * let hostapd code free it. + */ + os_free(ifmsh->mconf); + ifmsh->mconf = NULL; + } + + /* take care of shared data */ + hostapd_interface_deinit(ifmsh); + hostapd_interface_free(ifmsh); +} + +static struct mesh_conf * +mesh_config_create(struct wpa_ssid *ssid) +{ + struct mesh_conf *conf; + + conf = os_zalloc(sizeof(struct mesh_conf)); + if (!conf) + return NULL; + + os_memcpy(conf->meshid, ssid->ssid, ssid->ssid_len); + conf->meshid_len = ssid->ssid_len; + + if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) + conf->security |= MESH_CONF_SEC_AUTH | + MESH_CONF_SEC_AMPE; + else + conf->security |= MESH_CONF_SEC_NONE; + + /* defaults */ + conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP; + conf->mesh_pm_id = MESH_PATH_METRIC_AIRTIME; + 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; + + return conf; +} + +static int +wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + struct hostapd_iface *ifmsh; + struct hostapd_data *bss; + struct hostapd_config *conf; + struct mesh_conf *mconf; + int basic_rates_erp[] = {10, 20, 55, 60, 110, 120, 240, -1 }; + static int default_groups[] = { 19, 20, 21, 25, 26 }; + size_t len; + + wpa_s->ifmsh = ifmsh = os_zalloc(sizeof(*wpa_s->ifmsh)); + if (!ifmsh) + return -ENOMEM; + + ifmsh->num_bss = 1; + ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, + sizeof(struct hostapd_data *)); + if (!ifmsh->bss) + goto out_free; + + ifmsh->bss[0] = bss = os_zalloc(sizeof(struct hostapd_data)); + if (!bss) + goto out_free; + + os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN); + bss->driver = wpa_s->driver; + bss->drv_priv = wpa_s->drv_priv; + bss->iface = ifmsh; + wpa_s->assoc_freq = ssid->frequency; + wpa_s->current_ssid = ssid; + + /* setup an AP config for auth processing */ + conf = hostapd_config_defaults(); + if (!conf) + goto out_free; + + bss->conf = *conf->bss; + bss->conf->start_disabled = 1; + bss->conf->mesh = MESH_ENABLED; + bss->iconf = conf; + ifmsh->conf = conf; + + ifmsh->bss[0]->max_plinks = 99; + os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface)); + + mconf = mesh_config_create(ssid); + if (!mconf) + goto out_free; + ifmsh->mconf = mconf; + + /* need conf->hw_mode for supported rates. */ + /* c.f. wpa_supplicant/ap.c:wpa_supplicant_conf_ap() */ + if (ssid->frequency == 0) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211G; + conf->channel = 1; + } else if (ssid->frequency >= 2412 && ssid->frequency <= 2472) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211G; + conf->channel = (ssid->frequency - 2407) / 5; + } else if ((ssid->frequency >= 5180 && ssid->frequency <= 5240) || + (ssid->frequency >= 5745 && ssid->frequency <= 5825)) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211A; + conf->channel = (ssid->frequency - 5000) / 5; + } else if (ssid->frequency >= 56160 + 2160 * 1 && + ssid->frequency <= 56160 + 2160 * 4) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; + conf->channel = (ssid->frequency - 56160) / 2160; + } else { + wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz", + ssid->frequency); + goto out_free; + } + + /* XXX: hack! this is so an MPM which correctly sets the ERP + * mandatory rates as BSSBasicRateSet doesn't reject us. We + * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but + * this is way easier. This also makes our BSSBasicRateSet + * advertised in beacons match the one in peering frames, sigh. + * */ + if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { + conf->basic_rates = os_zalloc(sizeof(basic_rates_erp)); + if (!conf->basic_rates) + goto out_free; + os_memcpy(conf->basic_rates, + basic_rates_erp, sizeof(basic_rates_erp)); + } + + hostapd_setup_interface(ifmsh); + + if (wpa_drv_init_mesh(wpa_s)) { + wpa_msg(wpa_s, MSG_ERROR, "failed to init mesh in driver"); + return -1; + } + + if (mconf->security != MESH_CONF_SEC_NONE) { + bss->conf->wpa = ssid->proto; + bss->conf->wpa_key_mgmt = ssid->key_mgmt; + bss->conf->sae_groups = wpa_s->conf->sae_groups; + + if (wpa_s->conf->sae_groups) { + bss->conf->sae_groups = + os_zalloc(sizeof(wpa_s->conf->sae_groups)); + os_memcpy(bss->conf->sae_groups, + wpa_s->conf->sae_groups, + sizeof(wpa_s->conf->sae_groups)); + } else { + bss->conf->sae_groups = + os_zalloc(sizeof(default_groups)); + os_memcpy(bss->conf->sae_groups, + default_groups, + sizeof(default_groups)); + } + + len = os_strlen(ssid->passphrase); + bss->conf->ssid.wpa_passphrase = + dup_binstr(ssid->passphrase, len); + } + + return 0; +out_free: + wpa_supplicant_mesh_deinit(wpa_s); + return -ENOMEM; +} + +void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr, + const u8 *ies, int ie_len) +{ + struct ieee802_11_elems elems; + + wpa_msg(wpa_s, MSG_INFO, + "new peer notification for " MACSTR, MAC2STR(addr)); + + if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) { + wpa_msg(wpa_s, MSG_INFO, "Could not parse beacon from " MACSTR, + MAC2STR(addr)); + } +} + +int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + struct wpa_driver_mesh_join_params params; + int ret = 0; + + if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) { + ret = -ENOENT; + goto out; + } + + wpa_supplicant_mesh_deinit(wpa_s); + + os_memset(¶ms, 0, sizeof(params)); + params.meshid = ssid->ssid; + params.meshid_len = ssid->ssid_len; + params.freq = ssid->frequency; + + if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { + params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH; + params.flags |= WPA_DRIVER_MESH_FLAG_AMPE; + } + + params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM; + params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS; + + if (wpa_supplicant_mesh_init(wpa_s, ssid)) { + wpa_msg(wpa_s, MSG_ERROR, "failed to init mesh"); + goto out; + } + + if (wpa_s->ifmsh) { + params.ies = wpa_s->ifmsh->mconf->ies; + params.ie_len = wpa_s->ifmsh->mconf->ie_len; + params.basic_rates = wpa_s->ifmsh->basic_rates; + } + + wpa_msg(wpa_s, MSG_INFO, "joining mesh %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + ret = wpa_drv_join_mesh(wpa_s, ¶ms); + if (ret) + wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d\n", ret); + + /* hostapd sets the interface down until we associate */ + wpa_drv_set_operstate(wpa_s, 1); + +out: + return ret; +} + +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s) +{ + int ret = 0; + + wpa_msg(wpa_s, MSG_INFO, "leaving mesh"); + + ret = wpa_drv_leave_mesh(wpa_s); + + if (ret) + wpa_msg(wpa_s, MSG_ERROR, "mesh leave error=%d\n", ret); + + wpa_drv_set_operstate(wpa_s, 1); + + wpa_supplicant_mesh_deinit(wpa_s); + + return ret; +} diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h new file mode 100644 index 0000000..f08e641 --- /dev/null +++ b/wpa_supplicant/mesh.h @@ -0,0 +1,36 @@ +/* + * WPA Supplicant - Basic mesh mode routines + * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MESH_H +#define MESH_H +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/uuid.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "common/ieee802_11_defs.h" +#include "config_ssid.h" +#include "config.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "notify.h" + +#include "ap/sta_info.h" +#include "ap/hostapd.h" +#include "ap/ieee802_11.h" + +int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s); +void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr, + const u8 *ies, int ie_len); +void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, + struct hostapd_iface *ifmsh); +#endif /* MESH_H */