| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- From 806c84ac8e8f60eaec22772b627f85eb5ac13544 Mon Sep 17 00:00:00 2001
- From: Gioacchino Mazzurco <[email protected]>
- Date: Mon, 6 May 2024 13:53:48 +0200
- Subject: [PATCH 1/3] Implement APuP Access Point Micro Peering
- Access Point Micro Peering is a simpler and hopefully more useful successor to
- Ad Hoc, Wireless Distribution System, 802.11s mesh mode, Multi-AP and EasyMesh.
- When enabled almost plain APs communicate between them via 4-address mode,
- like in WDS but all of them are AP, so they can eventually communicate also with
- plain stations and more AP nodes in sight, without more trickery.
- APuP has low hardware requirements, just AP mode support + 4-address mode, and
- no more unnecessary complications, like hardcoded bridging or routing algorithm
- in WiFi stack.
- For each AP in sight an interface is created, and then it can be used as
- convenient in each case, bridging, routing etc.
- Those interfaces could be simply bridged in a trivial topology (which happens
- automatically if wds_bridge is not an empty string), or feeded to a
- routing daemon.
- Signed-off-by: Gioacchino Mazzurco <[email protected]>
- Reviewed-by: Hauke Mehrtens <[email protected]>
- Reviewed-by: Moritz Warning <[email protected]>
- Hotfix-by: Sebastian Gottschall https://github.com/mirror/dd-wrt/commit/0c3001a69e8d8300569e416de856c96e903ad130
- ---
- hostapd/Makefile | 5 ++
- hostapd/config_file.c | 9 +++
- src/ap/ap_config.h | 29 +++++++
- src/ap/ap_drv_ops.c | 28 ++++++-
- src/ap/ap_drv_ops.h | 3 +
- src/ap/apup.c | 152 +++++++++++++++++++++++++++++++++++
- src/ap/apup.h | 24 ++++++
- src/ap/ieee802_11.c | 14 +++-
- src/ap/ieee802_11.h | 2 +
- src/drivers/driver.h | 2 +-
- src/drivers/driver_nl80211.c | 14 +---
- 11 files changed, 265 insertions(+), 17 deletions(-)
- create mode 100644 src/ap/apup.c
- create mode 100644 src/ap/apup.h
- --- a/hostapd/Makefile
- +++ b/hostapd/Makefile
- @@ -1429,6 +1429,11 @@ ifdef CONFIG_NO_TKIP
- CFLAGS += -DCONFIG_NO_TKIP
- endif
-
- +ifdef CONFIG_APUP
- +CFLAGS += -DCONFIG_APUP
- +OBJS += ../src/ap/apup.o
- +endif
- +
- $(DESTDIR)$(BINDIR)/%: %
- install -D $(<) $(@)
-
- --- a/hostapd/config_file.c
- +++ b/hostapd/config_file.c
- @@ -4976,6 +4976,15 @@ static int hostapd_config_fill(struct ho
- bss->mld_indicate_disabled = atoi(pos);
- #endif /* CONFIG_TESTING_OPTIONS */
- #endif /* CONFIG_IEEE80211BE */
- +#ifdef CONFIG_APUP
- + } else if (os_strcmp(buf, "apup") == 0) {
- + bss->apup = !!atoi(pos);
- + if (bss->apup)
- + bss->wds_sta = 1;
- + } else if (os_strcmp(buf, "apup_peer_ifname_prefix") == 0) {
- + os_strlcpy(bss->apup_peer_ifname_prefix,
- + pos, sizeof(bss->apup_peer_ifname_prefix));
- +#endif // def CONFIG_APUP
- } else {
- wpa_printf(MSG_ERROR,
- "Line %d: unknown configuration item '%s'",
- --- a/src/ap/ap_config.h
- +++ b/src/ap/ap_config.h
- @@ -984,6 +984,35 @@ struct hostapd_bss_config {
- int mbssid_index;
-
- bool spp_amsdu;
- +
- +#ifdef CONFIG_APUP
- + /**
- + * Access Point Micro Peering
- + * A simpler and more useful successor to Ad Hoc,
- + * Wireless Distribution System, 802.11s mesh mode, Multi-AP and EasyMesh.
- + *
- + * Almost plain APs communicate between them via 4-address mode, like in WDS
- + * but all of them are AP, so they can eventually communicate also with
- + * plain stations and more AP nodes in sight.
- + * Low hardware requirements, just AP mode support + 4-address mode, and no
- + * more unnecessary complications, like hardcoded bridging or routing
- + * algorithm in WiFi stack.
- + * For each AP in sight an interface is created, and then it can be used as
- + * convenient in each case, bridging, routing etc.
- + */
- + bool apup;
- +
- + /**
- + * In 4-address mode each peer AP in sight is associated to its own
- + * interface so we have more flexibility in "user-space".
- + * Those interfaces could be simply bridged in a trivial topology (which
- + * happens automatically if wds_bridge is not an empty string), or feeded to
- + * a routing daemon.
- + *
- + * If not defined interface names are generated following the WDS convention.
- + */
- + char apup_peer_ifname_prefix[IFNAMSIZ + 1];
- +#endif /* CONFIG_APUP */
- };
-
- /**
- --- a/src/ap/ap_drv_ops.c
- +++ b/src/ap/ap_drv_ops.c
- @@ -385,13 +385,39 @@ int hostapd_set_wds_sta(struct hostapd_d
- const u8 *addr, int aid, int val)
- {
- const char *bridge = NULL;
- + char ifName[IFNAMSIZ + 1];
- +
- + int mRet = 0;
-
- if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
- return -1;
- +
- +#ifdef CONFIG_APUP
- + if (hapd->conf->apup && hapd->conf->apup_peer_ifname_prefix[0]) {
- + mRet = os_snprintf(
- + ifName, sizeof(ifName), "%s%d",
- + hapd->conf->apup_peer_ifname_prefix, aid);
- + }
- + else
- +#endif // def CONFIG_APUP
- + mRet = os_snprintf(
- + ifName, sizeof(ifName), "%s.sta%d",
- + hapd->conf->iface, aid);
- +
- + if (mRet >= (int) sizeof(ifName))
- + wpa_printf(MSG_WARNING,
- + "nl80211: WDS interface name was truncated");
- + else if (mRet < 0)
- + return mRet;
- +
- + // Pass back to the caller the resulting interface name
- + if (ifname_wds)
- + os_strlcpy(ifname_wds, ifName, IFNAMSIZ + 1);
- +
- if (hapd->conf->wds_bridge[0])
- bridge = hapd->conf->wds_bridge;
- return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
- - bridge, ifname_wds);
- + bridge, ifName);
- }
-
-
- --- a/src/ap/ap_drv_ops.h
- +++ b/src/ap/ap_drv_ops.h
- @@ -35,6 +35,9 @@ int hostapd_set_drv_ieee8021x(struct hos
- int enabled);
- int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
- int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
- +
- +/** @param val as per nl80211 driver implementation, 1 means add 0 means remove
- + */
- int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
- const u8 *addr, int aid, int val);
- int hostapd_sta_add(struct hostapd_data *hapd,
- --- /dev/null
- +++ b/src/ap/apup.c
- @@ -0,0 +1,169 @@
- +/*
- + * hostapd / APuP Access Point Micro Peering
- + *
- + * Copyright (C) 2023-2024 Gioacchino Mazzurco <[email protected]>
- + *
- + * This software may be distributed under the terms of the BSD license.
- + * See README for more details.
- + */
- +
- +/* Be extremely careful altering include order, move just one in the wrong place
- + * and you will start getting a bunch of error of undefined bool, size_t etc. */
- +
- +#include "utils/includes.h"
- +#include "utils/common.h"
- +#include "utils/os.h"
- +
- +#include "apup.h"
- +
- +#include "drivers/driver.h"
- +#include "wpa_auth.h"
- +#include "ap_mlme.h"
- +#include "ieee802_11.h"
- +#include "ap_drv_ops.h"
- +#include "sta_info.h"
- +
- +#ifdef UBUS_SUPPORT
- +# include "ubus.h"
- +#endif
- +
- +#ifdef UCODE_SUPPORT
- +# include "ucode.h"
- +#endif
- +
- +void apup_process_beacon(struct hostapd_data *hapd,
- + const struct ieee80211_mgmt *mgmt, size_t len,
- + const struct ieee802_11_elems *elems )
- +{
- + if (!os_memcmp(hapd->own_addr, mgmt->bssid, ETH_ALEN))
- + {
- + wpa_printf(MSG_WARNING,
- + "apup_process_beacon(...) own beacon elems.ssid %.*s",
- + (int) elems->ssid_len, elems->ssid);
- + return;
- + }
- +
- + if (elems->ssid_len != hapd->conf->ssid.ssid_len ||
- + os_memcmp(elems->ssid, hapd->conf->ssid.ssid, elems->ssid_len))
- + return;
- +
- + struct sta_info* sta_ret = ap_get_sta(hapd, mgmt->bssid);
- + if (sta_ret)
- + return;
- +
- + sta_ret = ap_sta_add(hapd, mgmt->bssid);
- +
- + /* TODO: this has been added just to making compiler happy after breaking
- + * changes introduced in 11a607d12 and 7855b6d60 to support
- + * IEEE80211BE Multi Link Operation. Look at these commits with more time and
- + * understand what could be a proper implementation in this context too
- + */
- + const u8 *mld_link_addr = NULL;
- + bool mld_link_sta = false;
- + u16 eml_cap = 0;
- +
- + /* First add the station without more information */
- + int aRet = hostapd_sta_add(
- + hapd, mgmt->bssid, sta_ret->aid, 0,
- + NULL, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL,
- + sta_ret->flags, 0, 0, 0,
- + 0, // 0 add, 1 set
- + mld_link_addr, mld_link_sta, eml_cap);
- +
- + sta_ret->flags |= WLAN_STA_AUTH;
- + wpa_auth_sm_event(sta_ret->wpa_sm, WPA_AUTH);
- +
- + /* TODO: Investigate if supporting WPA or other encryption method is
- + * possible */
- + sta_ret->auth_alg = WLAN_AUTH_OPEN;
- + mlme_authenticate_indication(hapd, sta_ret);
- +
- + sta_ret->capability = le_to_host16(mgmt->u.beacon.capab_info);
- +
- + if (sta_ret->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- + sta_ret->flags |= WLAN_STA_SHORT_PREAMBLE;
- + else
- + sta_ret->flags &= ~WLAN_STA_SHORT_PREAMBLE;
- +
- + hostapd_copy_supp_rates(hapd, sta_ret, elems);
- +
- + /* Whithout this flag copy_sta_[v]ht_capab will disable [V]HT
- + * capabilities even if available */
- + if (elems->ht_capabilities || elems->vht_capabilities)
- + sta_ret->flags |= WLAN_STA_WMM;
- +
- + copy_sta_ht_capab(hapd, sta_ret, elems->ht_capabilities);
- +#ifdef CONFIG_IEEE80211AC
- + copy_sta_vht_capab(hapd, sta_ret, elems->vht_capabilities);
- + copy_sta_vht_oper(hapd, sta_ret, elems->vht_operation);
- + copy_sta_vendor_vht(hapd, sta_ret, elems->vendor_vht, elems->vendor_vht_len);
- +#endif // def CONFIG_IEEE80211AC
- +#ifdef CONFIG_IEEE80211AX
- + copy_sta_he_capab(hapd, sta_ret, IEEE80211_MODE_AP,
- + elems->he_capabilities, elems->he_capabilities_len);
- + copy_sta_he_6ghz_capab(hapd, sta_ret, elems->he_6ghz_band_cap);
- +#endif // def CONFIG_IEEE80211AX
- +#ifdef CONFIG_IEEE80211BE
- + copy_sta_eht_capab(hapd, sta_ret,
- + IEEE80211_MODE_AP, // TODO: Make sure is the right value
- + elems->he_capabilities, elems->he_capabilities_len,
- + elems->eht_capabilities, elems->eht_capabilities_len);
- +#endif //def CONFIG_IEEE80211BE
- +
- + update_ht_state(hapd, sta_ret);
- +
- + if (hostapd_get_aid(hapd, sta_ret) < 0)
- + {
- + wpa_printf(MSG_INFO, "apup_process_beacon(...) No room for more AIDs");
- + return;
- + }
- +
- + sta_ret->flags |= WLAN_STA_ASSOC_REQ_OK;
- +
- + /* Make sure that the previously registered inactivity timer will not
- + * remove the STA immediately. */
- + sta_ret->timeout_next = STA_NULLFUNC;
- +
- + sta_ret->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
- +
- + /* Then set the paramethers */
- + int sRet = hostapd_sta_add(
- + hapd, mgmt->bssid, sta_ret->aid,
- + sta_ret->capability,
- + sta_ret->supported_rates, sta_ret->supported_rates_len,
- + 0, // u16 listen_interval TODO ?
- + sta_ret->ht_capabilities,
- + sta_ret->vht_capabilities,
- + sta_ret->he_capab, sta_ret->he_capab_len,
- + sta_ret->eht_capab, sta_ret->eht_capab_len,
- + sta_ret->he_6ghz_capab,
- + sta_ret->flags,
- + 0, // u8 qosinfo
- + sta_ret->vht_opmode,
- + 0, // int supp_p2p_ps
- + 1, // 0 add, 1 set
- + mld_link_addr, mld_link_sta, eml_cap);
- +
- + ap_sta_set_authorized(hapd, sta_ret, 1);
- + hostapd_set_sta_flags(hapd, sta_ret);
- +
- + char mIfname[IFNAMSIZ + 1];
- + os_memset(mIfname, 0, IFNAMSIZ + 1);
- +
- + // last param 1 means add 0 means remove
- + int mRet = hostapd_set_wds_sta(
- + hapd, mIfname, mgmt->bssid, sta_ret->aid, 1);
- +
- + wpa_printf(MSG_INFO,
- + "apup_process_beacon(...) Added APuP peer at %s with flags: %d,"
- + " capabilities %d",
- + mIfname, sta_ret->flags, sta_ret->capability);
- +
- +#ifdef UBUS_SUPPORT
- + hostapd_ubus_notify_apup_newpeer(hapd, mgmt->bssid, mIfname);
- +#endif
- +
- +#ifdef UCODE_SUPPORT
- + hostapd_ucode_apup_newpeer(hapd, mIfname);
- +#endif
- +}
- --- /dev/null
- +++ b/src/ap/apup.h
- @@ -0,0 +1,24 @@
- +/*
- + * hostapd / APuP Access Point Micro Peering
- + *
- + * Copyright (C) 2023-2024 Gioacchino Mazzurco <[email protected]>
- + *
- + * This software may be distributed under the terms of the BSD license.
- + * See README for more details.
- + */
- +
- +/* Be extremely careful altering include order, move just one in the wrong place
- + * and you will start getting a bunch of error of undefined bool, size_t etc. */
- +
- +#include "utils/includes.h"
- +#include "utils/common.h"
- +
- +#include "hostapd.h"
- +#include "common/ieee802_11_defs.h"
- +
- +/** When beacons from other Access Point are received, if the SSID is matching
- + * add them as APuP peers (aka WDS STA to our own AP) the same happens on the
- + * peer when receiving our beacons */
- +void apup_process_beacon(struct hostapd_data *hapd,
- + const struct ieee80211_mgmt *mgmt, size_t len,
- + const struct ieee802_11_elems *elems );
- --- a/src/ap/ieee802_11.c
- +++ b/src/ap/ieee802_11.c
- @@ -60,6 +60,9 @@
- #include "nan_usd_ap.h"
- #include "pasn/pasn_common.h"
-
- +#ifdef CONFIG_APUP
- +# include "apup.h"
- +#endif // def CONFIG_APUP
-
- #ifdef CONFIG_FILS
- static struct wpabuf *
- @@ -3837,8 +3840,8 @@ static u16 check_multi_ap(struct hostapd
- }
-
-
- -static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
- - struct ieee802_11_elems *elems)
- +u16 hostapd_copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
- + const struct ieee802_11_elems *elems)
- {
- /* Supported rates not used in IEEE 802.11ad/DMG */
- if (hapd->iface->current_mode &&
- @@ -4283,7 +4286,7 @@ static int __check_assoc_ies(struct host
- elems->ext_capab_len);
- if (resp != WLAN_STATUS_SUCCESS)
- return resp;
- - resp = copy_supp_rates(hapd, sta, elems);
- + resp = hostapd_copy_supp_rates(hapd, sta, elems);
- if (resp != WLAN_STATUS_SUCCESS)
- return resp;
-
- @@ -6358,6 +6361,11 @@ static void handle_beacon(struct hostapd
- 0);
-
- ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
- +
- +#ifdef CONFIG_APUP
- + if (hapd->conf->apup)
- + apup_process_beacon(hapd, mgmt, len, &elems);
- +#endif // def CONFIG_APUP
- }
-
-
- --- a/src/ap/ieee802_11.h
- +++ b/src/ap/ieee802_11.h
- @@ -145,6 +145,8 @@ int hostapd_process_ml_assoc_req_addr(st
- const u8 *basic_mle, size_t basic_mle_len,
- u8 *mld_addr);
- int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
- +u16 hostapd_copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
- + const struct ieee802_11_elems *elems);
- u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *ht_capab);
- u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta,
- --- a/src/drivers/driver.h
- +++ b/src/drivers/driver.h
- @@ -4187,7 +4187,7 @@ struct wpa_driver_ops {
- * Returns: 0 on success, -1 on failure
- */
- int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val,
- - const char *bridge_ifname, char *ifname_wds);
- + const char *bridge_ifname, const char *ifname_wds);
-
- /**
- * send_action - Transmit an Action frame
- --- a/src/drivers/driver_nl80211.c
- +++ b/src/drivers/driver_nl80211.c
- @@ -8703,25 +8703,15 @@ static int have_ifidx(struct wpa_driver_
-
-
- static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
- - const char *bridge_ifname, char *ifname_wds)
- + const char *bridge_ifname, const char *ifname_wds)
- {
- struct i802_bss *bss = priv;
- struct wpa_driver_nl80211_data *drv = bss->drv;
- - char name[IFNAMSIZ + 1];
- + const char *name = ifname_wds; // Kept to reduce changes to the minimum
- union wpa_event_data event;
- bool add_br = false;
- int ret;
-
- - ret = os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
- - if (ret >= (int) sizeof(name))
- - wpa_printf(MSG_WARNING,
- - "nl80211: WDS interface name was truncated");
- - else if (ret < 0)
- - return ret;
- -
- - if (ifname_wds)
- - os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
- -
- wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
- " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
- if (val) {
|