780-Implement-APuP-Access-Point-Micro-Peering.patch 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. From 806c84ac8e8f60eaec22772b627f85eb5ac13544 Mon Sep 17 00:00:00 2001
  2. From: Gioacchino Mazzurco <[email protected]>
  3. Date: Mon, 6 May 2024 13:53:48 +0200
  4. Subject: [PATCH 1/3] Implement APuP Access Point Micro Peering
  5. Access Point Micro Peering is a simpler and hopefully more useful successor to
  6. Ad Hoc, Wireless Distribution System, 802.11s mesh mode, Multi-AP and EasyMesh.
  7. When enabled almost plain APs communicate between them via 4-address mode,
  8. like in WDS but all of them are AP, so they can eventually communicate also with
  9. plain stations and more AP nodes in sight, without more trickery.
  10. APuP has low hardware requirements, just AP mode support + 4-address mode, and
  11. no more unnecessary complications, like hardcoded bridging or routing algorithm
  12. in WiFi stack.
  13. For each AP in sight an interface is created, and then it can be used as
  14. convenient in each case, bridging, routing etc.
  15. Those interfaces could be simply bridged in a trivial topology (which happens
  16. automatically if wds_bridge is not an empty string), or feeded to a
  17. routing daemon.
  18. Signed-off-by: Gioacchino Mazzurco <[email protected]>
  19. Reviewed-by: Hauke Mehrtens <[email protected]>
  20. Reviewed-by: Moritz Warning <[email protected]>
  21. Hotfix-by: Sebastian Gottschall https://github.com/mirror/dd-wrt/commit/0c3001a69e8d8300569e416de856c96e903ad130
  22. ---
  23. hostapd/Makefile | 5 ++
  24. hostapd/config_file.c | 9 +++
  25. src/ap/ap_config.h | 29 +++++++
  26. src/ap/ap_drv_ops.c | 28 ++++++-
  27. src/ap/ap_drv_ops.h | 3 +
  28. src/ap/apup.c | 152 +++++++++++++++++++++++++++++++++++
  29. src/ap/apup.h | 24 ++++++
  30. src/ap/ieee802_11.c | 14 +++-
  31. src/ap/ieee802_11.h | 2 +
  32. src/drivers/driver.h | 2 +-
  33. src/drivers/driver_nl80211.c | 14 +---
  34. 11 files changed, 265 insertions(+), 17 deletions(-)
  35. create mode 100644 src/ap/apup.c
  36. create mode 100644 src/ap/apup.h
  37. --- a/hostapd/Makefile
  38. +++ b/hostapd/Makefile
  39. @@ -1429,6 +1429,11 @@ ifdef CONFIG_NO_TKIP
  40. CFLAGS += -DCONFIG_NO_TKIP
  41. endif
  42. +ifdef CONFIG_APUP
  43. +CFLAGS += -DCONFIG_APUP
  44. +OBJS += ../src/ap/apup.o
  45. +endif
  46. +
  47. $(DESTDIR)$(BINDIR)/%: %
  48. install -D $(<) $(@)
  49. --- a/hostapd/config_file.c
  50. +++ b/hostapd/config_file.c
  51. @@ -4976,6 +4976,15 @@ static int hostapd_config_fill(struct ho
  52. bss->mld_indicate_disabled = atoi(pos);
  53. #endif /* CONFIG_TESTING_OPTIONS */
  54. #endif /* CONFIG_IEEE80211BE */
  55. +#ifdef CONFIG_APUP
  56. + } else if (os_strcmp(buf, "apup") == 0) {
  57. + bss->apup = !!atoi(pos);
  58. + if (bss->apup)
  59. + bss->wds_sta = 1;
  60. + } else if (os_strcmp(buf, "apup_peer_ifname_prefix") == 0) {
  61. + os_strlcpy(bss->apup_peer_ifname_prefix,
  62. + pos, sizeof(bss->apup_peer_ifname_prefix));
  63. +#endif // def CONFIG_APUP
  64. } else {
  65. wpa_printf(MSG_ERROR,
  66. "Line %d: unknown configuration item '%s'",
  67. --- a/src/ap/ap_config.h
  68. +++ b/src/ap/ap_config.h
  69. @@ -984,6 +984,35 @@ struct hostapd_bss_config {
  70. int mbssid_index;
  71. bool spp_amsdu;
  72. +
  73. +#ifdef CONFIG_APUP
  74. + /**
  75. + * Access Point Micro Peering
  76. + * A simpler and more useful successor to Ad Hoc,
  77. + * Wireless Distribution System, 802.11s mesh mode, Multi-AP and EasyMesh.
  78. + *
  79. + * Almost plain APs communicate between them via 4-address mode, like in WDS
  80. + * but all of them are AP, so they can eventually communicate also with
  81. + * plain stations and more AP nodes in sight.
  82. + * Low hardware requirements, just AP mode support + 4-address mode, and no
  83. + * more unnecessary complications, like hardcoded bridging or routing
  84. + * algorithm in WiFi stack.
  85. + * For each AP in sight an interface is created, and then it can be used as
  86. + * convenient in each case, bridging, routing etc.
  87. + */
  88. + bool apup;
  89. +
  90. + /**
  91. + * In 4-address mode each peer AP in sight is associated to its own
  92. + * interface so we have more flexibility in "user-space".
  93. + * Those interfaces could be simply bridged in a trivial topology (which
  94. + * happens automatically if wds_bridge is not an empty string), or feeded to
  95. + * a routing daemon.
  96. + *
  97. + * If not defined interface names are generated following the WDS convention.
  98. + */
  99. + char apup_peer_ifname_prefix[IFNAMSIZ + 1];
  100. +#endif /* CONFIG_APUP */
  101. };
  102. /**
  103. --- a/src/ap/ap_drv_ops.c
  104. +++ b/src/ap/ap_drv_ops.c
  105. @@ -385,13 +385,39 @@ int hostapd_set_wds_sta(struct hostapd_d
  106. const u8 *addr, int aid, int val)
  107. {
  108. const char *bridge = NULL;
  109. + char ifName[IFNAMSIZ + 1];
  110. +
  111. + int mRet = 0;
  112. if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
  113. return -1;
  114. +
  115. +#ifdef CONFIG_APUP
  116. + if (hapd->conf->apup && hapd->conf->apup_peer_ifname_prefix[0]) {
  117. + mRet = os_snprintf(
  118. + ifName, sizeof(ifName), "%s%d",
  119. + hapd->conf->apup_peer_ifname_prefix, aid);
  120. + }
  121. + else
  122. +#endif // def CONFIG_APUP
  123. + mRet = os_snprintf(
  124. + ifName, sizeof(ifName), "%s.sta%d",
  125. + hapd->conf->iface, aid);
  126. +
  127. + if (mRet >= (int) sizeof(ifName))
  128. + wpa_printf(MSG_WARNING,
  129. + "nl80211: WDS interface name was truncated");
  130. + else if (mRet < 0)
  131. + return mRet;
  132. +
  133. + // Pass back to the caller the resulting interface name
  134. + if (ifname_wds)
  135. + os_strlcpy(ifname_wds, ifName, IFNAMSIZ + 1);
  136. +
  137. if (hapd->conf->wds_bridge[0])
  138. bridge = hapd->conf->wds_bridge;
  139. return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
  140. - bridge, ifname_wds);
  141. + bridge, ifName);
  142. }
  143. --- a/src/ap/ap_drv_ops.h
  144. +++ b/src/ap/ap_drv_ops.h
  145. @@ -35,6 +35,9 @@ int hostapd_set_drv_ieee8021x(struct hos
  146. int enabled);
  147. int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
  148. int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
  149. +
  150. +/** @param val as per nl80211 driver implementation, 1 means add 0 means remove
  151. + */
  152. int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
  153. const u8 *addr, int aid, int val);
  154. int hostapd_sta_add(struct hostapd_data *hapd,
  155. --- /dev/null
  156. +++ b/src/ap/apup.c
  157. @@ -0,0 +1,169 @@
  158. +/*
  159. + * hostapd / APuP Access Point Micro Peering
  160. + *
  161. + * Copyright (C) 2023-2024 Gioacchino Mazzurco <[email protected]>
  162. + *
  163. + * This software may be distributed under the terms of the BSD license.
  164. + * See README for more details.
  165. + */
  166. +
  167. +/* Be extremely careful altering include order, move just one in the wrong place
  168. + * and you will start getting a bunch of error of undefined bool, size_t etc. */
  169. +
  170. +#include "utils/includes.h"
  171. +#include "utils/common.h"
  172. +#include "utils/os.h"
  173. +
  174. +#include "apup.h"
  175. +
  176. +#include "drivers/driver.h"
  177. +#include "wpa_auth.h"
  178. +#include "ap_mlme.h"
  179. +#include "ieee802_11.h"
  180. +#include "ap_drv_ops.h"
  181. +#include "sta_info.h"
  182. +
  183. +#ifdef UBUS_SUPPORT
  184. +# include "ubus.h"
  185. +#endif
  186. +
  187. +#ifdef UCODE_SUPPORT
  188. +# include "ucode.h"
  189. +#endif
  190. +
  191. +void apup_process_beacon(struct hostapd_data *hapd,
  192. + const struct ieee80211_mgmt *mgmt, size_t len,
  193. + const struct ieee802_11_elems *elems )
  194. +{
  195. + if (!os_memcmp(hapd->own_addr, mgmt->bssid, ETH_ALEN))
  196. + {
  197. + wpa_printf(MSG_WARNING,
  198. + "apup_process_beacon(...) own beacon elems.ssid %.*s",
  199. + (int) elems->ssid_len, elems->ssid);
  200. + return;
  201. + }
  202. +
  203. + if (elems->ssid_len != hapd->conf->ssid.ssid_len ||
  204. + os_memcmp(elems->ssid, hapd->conf->ssid.ssid, elems->ssid_len))
  205. + return;
  206. +
  207. + struct sta_info* sta_ret = ap_get_sta(hapd, mgmt->bssid);
  208. + if (sta_ret)
  209. + return;
  210. +
  211. + sta_ret = ap_sta_add(hapd, mgmt->bssid);
  212. +
  213. + /* TODO: this has been added just to making compiler happy after breaking
  214. + * changes introduced in 11a607d12 and 7855b6d60 to support
  215. + * IEEE80211BE Multi Link Operation. Look at these commits with more time and
  216. + * understand what could be a proper implementation in this context too
  217. + */
  218. + const u8 *mld_link_addr = NULL;
  219. + bool mld_link_sta = false;
  220. + u16 eml_cap = 0;
  221. +
  222. + /* First add the station without more information */
  223. + int aRet = hostapd_sta_add(
  224. + hapd, mgmt->bssid, sta_ret->aid, 0,
  225. + NULL, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL,
  226. + sta_ret->flags, 0, 0, 0,
  227. + 0, // 0 add, 1 set
  228. + mld_link_addr, mld_link_sta, eml_cap);
  229. +
  230. + sta_ret->flags |= WLAN_STA_AUTH;
  231. + wpa_auth_sm_event(sta_ret->wpa_sm, WPA_AUTH);
  232. +
  233. + /* TODO: Investigate if supporting WPA or other encryption method is
  234. + * possible */
  235. + sta_ret->auth_alg = WLAN_AUTH_OPEN;
  236. + mlme_authenticate_indication(hapd, sta_ret);
  237. +
  238. + sta_ret->capability = le_to_host16(mgmt->u.beacon.capab_info);
  239. +
  240. + if (sta_ret->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
  241. + sta_ret->flags |= WLAN_STA_SHORT_PREAMBLE;
  242. + else
  243. + sta_ret->flags &= ~WLAN_STA_SHORT_PREAMBLE;
  244. +
  245. + hostapd_copy_supp_rates(hapd, sta_ret, elems);
  246. +
  247. + /* Whithout this flag copy_sta_[v]ht_capab will disable [V]HT
  248. + * capabilities even if available */
  249. + if (elems->ht_capabilities || elems->vht_capabilities)
  250. + sta_ret->flags |= WLAN_STA_WMM;
  251. +
  252. + copy_sta_ht_capab(hapd, sta_ret, elems->ht_capabilities);
  253. +#ifdef CONFIG_IEEE80211AC
  254. + copy_sta_vht_capab(hapd, sta_ret, elems->vht_capabilities);
  255. + copy_sta_vht_oper(hapd, sta_ret, elems->vht_operation);
  256. + copy_sta_vendor_vht(hapd, sta_ret, elems->vendor_vht, elems->vendor_vht_len);
  257. +#endif // def CONFIG_IEEE80211AC
  258. +#ifdef CONFIG_IEEE80211AX
  259. + copy_sta_he_capab(hapd, sta_ret, IEEE80211_MODE_AP,
  260. + elems->he_capabilities, elems->he_capabilities_len);
  261. + copy_sta_he_6ghz_capab(hapd, sta_ret, elems->he_6ghz_band_cap);
  262. +#endif // def CONFIG_IEEE80211AX
  263. +#ifdef CONFIG_IEEE80211BE
  264. + copy_sta_eht_capab(hapd, sta_ret,
  265. + IEEE80211_MODE_AP, // TODO: Make sure is the right value
  266. + elems->he_capabilities, elems->he_capabilities_len,
  267. + elems->eht_capabilities, elems->eht_capabilities_len);
  268. +#endif //def CONFIG_IEEE80211BE
  269. +
  270. + update_ht_state(hapd, sta_ret);
  271. +
  272. + if (hostapd_get_aid(hapd, sta_ret) < 0)
  273. + {
  274. + wpa_printf(MSG_INFO, "apup_process_beacon(...) No room for more AIDs");
  275. + return;
  276. + }
  277. +
  278. + sta_ret->flags |= WLAN_STA_ASSOC_REQ_OK;
  279. +
  280. + /* Make sure that the previously registered inactivity timer will not
  281. + * remove the STA immediately. */
  282. + sta_ret->timeout_next = STA_NULLFUNC;
  283. +
  284. + sta_ret->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
  285. +
  286. + /* Then set the paramethers */
  287. + int sRet = hostapd_sta_add(
  288. + hapd, mgmt->bssid, sta_ret->aid,
  289. + sta_ret->capability,
  290. + sta_ret->supported_rates, sta_ret->supported_rates_len,
  291. + 0, // u16 listen_interval TODO ?
  292. + sta_ret->ht_capabilities,
  293. + sta_ret->vht_capabilities,
  294. + sta_ret->he_capab, sta_ret->he_capab_len,
  295. + sta_ret->eht_capab, sta_ret->eht_capab_len,
  296. + sta_ret->he_6ghz_capab,
  297. + sta_ret->flags,
  298. + 0, // u8 qosinfo
  299. + sta_ret->vht_opmode,
  300. + 0, // int supp_p2p_ps
  301. + 1, // 0 add, 1 set
  302. + mld_link_addr, mld_link_sta, eml_cap);
  303. +
  304. + ap_sta_set_authorized(hapd, sta_ret, 1);
  305. + hostapd_set_sta_flags(hapd, sta_ret);
  306. +
  307. + char mIfname[IFNAMSIZ + 1];
  308. + os_memset(mIfname, 0, IFNAMSIZ + 1);
  309. +
  310. + // last param 1 means add 0 means remove
  311. + int mRet = hostapd_set_wds_sta(
  312. + hapd, mIfname, mgmt->bssid, sta_ret->aid, 1);
  313. +
  314. + wpa_printf(MSG_INFO,
  315. + "apup_process_beacon(...) Added APuP peer at %s with flags: %d,"
  316. + " capabilities %d",
  317. + mIfname, sta_ret->flags, sta_ret->capability);
  318. +
  319. +#ifdef UBUS_SUPPORT
  320. + hostapd_ubus_notify_apup_newpeer(hapd, mgmt->bssid, mIfname);
  321. +#endif
  322. +
  323. +#ifdef UCODE_SUPPORT
  324. + hostapd_ucode_apup_newpeer(hapd, mIfname);
  325. +#endif
  326. +}
  327. --- /dev/null
  328. +++ b/src/ap/apup.h
  329. @@ -0,0 +1,24 @@
  330. +/*
  331. + * hostapd / APuP Access Point Micro Peering
  332. + *
  333. + * Copyright (C) 2023-2024 Gioacchino Mazzurco <[email protected]>
  334. + *
  335. + * This software may be distributed under the terms of the BSD license.
  336. + * See README for more details.
  337. + */
  338. +
  339. +/* Be extremely careful altering include order, move just one in the wrong place
  340. + * and you will start getting a bunch of error of undefined bool, size_t etc. */
  341. +
  342. +#include "utils/includes.h"
  343. +#include "utils/common.h"
  344. +
  345. +#include "hostapd.h"
  346. +#include "common/ieee802_11_defs.h"
  347. +
  348. +/** When beacons from other Access Point are received, if the SSID is matching
  349. + * add them as APuP peers (aka WDS STA to our own AP) the same happens on the
  350. + * peer when receiving our beacons */
  351. +void apup_process_beacon(struct hostapd_data *hapd,
  352. + const struct ieee80211_mgmt *mgmt, size_t len,
  353. + const struct ieee802_11_elems *elems );
  354. --- a/src/ap/ieee802_11.c
  355. +++ b/src/ap/ieee802_11.c
  356. @@ -60,6 +60,9 @@
  357. #include "nan_usd_ap.h"
  358. #include "pasn/pasn_common.h"
  359. +#ifdef CONFIG_APUP
  360. +# include "apup.h"
  361. +#endif // def CONFIG_APUP
  362. #ifdef CONFIG_FILS
  363. static struct wpabuf *
  364. @@ -3837,8 +3840,8 @@ static u16 check_multi_ap(struct hostapd
  365. }
  366. -static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
  367. - struct ieee802_11_elems *elems)
  368. +u16 hostapd_copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
  369. + const struct ieee802_11_elems *elems)
  370. {
  371. /* Supported rates not used in IEEE 802.11ad/DMG */
  372. if (hapd->iface->current_mode &&
  373. @@ -4283,7 +4286,7 @@ static int __check_assoc_ies(struct host
  374. elems->ext_capab_len);
  375. if (resp != WLAN_STATUS_SUCCESS)
  376. return resp;
  377. - resp = copy_supp_rates(hapd, sta, elems);
  378. + resp = hostapd_copy_supp_rates(hapd, sta, elems);
  379. if (resp != WLAN_STATUS_SUCCESS)
  380. return resp;
  381. @@ -6358,6 +6361,11 @@ static void handle_beacon(struct hostapd
  382. 0);
  383. ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
  384. +
  385. +#ifdef CONFIG_APUP
  386. + if (hapd->conf->apup)
  387. + apup_process_beacon(hapd, mgmt, len, &elems);
  388. +#endif // def CONFIG_APUP
  389. }
  390. --- a/src/ap/ieee802_11.h
  391. +++ b/src/ap/ieee802_11.h
  392. @@ -145,6 +145,8 @@ int hostapd_process_ml_assoc_req_addr(st
  393. const u8 *basic_mle, size_t basic_mle_len,
  394. u8 *mld_addr);
  395. int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
  396. +u16 hostapd_copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
  397. + const struct ieee802_11_elems *elems);
  398. u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
  399. const u8 *ht_capab);
  400. u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta,
  401. --- a/src/drivers/driver.h
  402. +++ b/src/drivers/driver.h
  403. @@ -4187,7 +4187,7 @@ struct wpa_driver_ops {
  404. * Returns: 0 on success, -1 on failure
  405. */
  406. int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val,
  407. - const char *bridge_ifname, char *ifname_wds);
  408. + const char *bridge_ifname, const char *ifname_wds);
  409. /**
  410. * send_action - Transmit an Action frame
  411. --- a/src/drivers/driver_nl80211.c
  412. +++ b/src/drivers/driver_nl80211.c
  413. @@ -8703,25 +8703,15 @@ static int have_ifidx(struct wpa_driver_
  414. static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
  415. - const char *bridge_ifname, char *ifname_wds)
  416. + const char *bridge_ifname, const char *ifname_wds)
  417. {
  418. struct i802_bss *bss = priv;
  419. struct wpa_driver_nl80211_data *drv = bss->drv;
  420. - char name[IFNAMSIZ + 1];
  421. + const char *name = ifname_wds; // Kept to reduce changes to the minimum
  422. union wpa_event_data event;
  423. bool add_br = false;
  424. int ret;
  425. - ret = os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
  426. - if (ret >= (int) sizeof(name))
  427. - wpa_printf(MSG_WARNING,
  428. - "nl80211: WDS interface name was truncated");
  429. - else if (ret < 0)
  430. - return ret;
  431. -
  432. - if (ifname_wds)
  433. - os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
  434. -
  435. wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
  436. " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
  437. if (val) {