blob: 0c207473ede78601004f992ef5838188c98c6b4e [file] [log] [blame]
From 4cfeeac3cb5224c3779e79259688221479735d06 Mon Sep 17 00:00:00 2001
From: "howard.hsu" <howard-yh.hsu@mediatek.com>
Date: Wed, 16 Feb 2022 15:54:22 +0800
Subject: [PATCH] Add hostapd patches for WiFi Certification MBO test plan
---
...hbor_count-and-hostapd_neighbor_inse.patch | 72 +++++++++++++
...g-neighbor-report-elements-in-ANQP-r.patch | 95 ++++++++++++++++
...g-neignbor-report-elements-in-BTM-re.patch | 68 ++++++++++++
...ing-BSS-Termination-TSF-by-using-hos.patch | 66 ++++++++++++
...erface-if-BSS-Termination-TSF-is-set.patch | 47 ++++++++
...assoc_frame_timer-to-send-disassocia.patch | 63 +++++++++++
...g-neighbor-report-elements-in-BTM-re.patch | 31 ++++++
...hostapd_neighbor_set_own_report_pref.patch | 88 +++++++++++++++
...d_neighbor_set_pref_by_non_pref_chan.patch | 101 ++++++++++++++++++
9 files changed, 631 insertions(+)
create mode 100644 package/network/services/hostapd/patches/902-master-Add-hostapd_neighbor_count-and-hostapd_neighbor_inse.patch
create mode 100644 package/network/services/hostapd/patches/903-master-Support-including-neighbor-report-elements-in-ANQP-r.patch
create mode 100644 package/network/services/hostapd/patches/904-master-Support-including-neignbor-report-elements-in-BTM-re.patch
create mode 100644 package/network/services/hostapd/patches/905-master-Support-configuring-BSS-Termination-TSF-by-using-hos.patch
create mode 100644 package/network/services/hostapd/patches/906-master-Disable-interface-if-BSS-Termination-TSF-is-set.patch
create mode 100644 package/network/services/hostapd/patches/907-master-Add-set_send_disassoc_frame_timer-to-send-disassocia.patch
create mode 100644 package/network/services/hostapd/patches/908-master-Support-including-neighbor-report-elements-in-BTM-re.patch
create mode 100644 package/network/services/hostapd/patches/909-master-Add-hostapd_neighbor_set_own_report_pref.patch
create mode 100644 package/network/services/hostapd/patches/910-master-Add-hostapd_neighbor_set_pref_by_non_pref_chan.patch
diff --git a/package/network/services/hostapd/patches/902-master-Add-hostapd_neighbor_count-and-hostapd_neighbor_inse.patch b/package/network/services/hostapd/patches/902-master-Add-hostapd_neighbor_count-and-hostapd_neighbor_inse.patch
new file mode 100644
index 0000000..e761c00
--- /dev/null
+++ b/package/network/services/hostapd/patches/902-master-Add-hostapd_neighbor_count-and-hostapd_neighbor_inse.patch
@@ -0,0 +1,72 @@
+From 413cb1d917383c5f4cb4bb6b94310c4f193a9187 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 19:18:07 +0800
+Subject: [PATCH 1/9] Add hostapd_neighbor_count() and
+ hostapd_neighbor_insert_buffer ()
+
+The first function can count the number of neighbor report in neighbore report
+database. The second can iterate neighbor report database to build up neighbor
+report data.
+---
+ src/ap/neighbor_db.c | 32 ++++++++++++++++++++++++++++++++
+ src/ap/neighbor_db.h | 3 +++
+ 2 files changed, 35 insertions(+)
+
+diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
+index 229edd2..ce6865d 100644
+--- a/src/ap/neighbor_db.c
++++ b/src/ap/neighbor_db.c
+@@ -89,6 +89,38 @@ int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen)
+ }
+
+
++int hostapd_neighbor_count(struct hostapd_data *hapd)
++{
++ struct hostapd_neighbor_entry *nr;
++ int count = 0;
++
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ count++;
++ }
++ return count;
++}
++
++
++int hostapd_neighbor_insert_buffer(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ struct hostapd_neighbor_entry *nr;
++ char *pos = buf;
++
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ /* For neighbor report IE, we only need bssid and nr*/
++ *pos++ = WLAN_EID_NEIGHBOR_REPORT;
++ *pos++ = wpabuf_len(nr->nr);
++ os_memcpy(pos, wpabuf_head(nr->nr), wpabuf_len(nr->nr));
++ pos += wpabuf_len(nr->nr);
++ }
++
++ return pos - buf;
++}
++
++
+ static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
+ {
+ wpabuf_free(nr->nr);
+diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
+index 992671b..1ae194d 100644
+--- a/src/ap/neighbor_db.h
++++ b/src/ap/neighbor_db.h
+@@ -24,4 +24,7 @@ int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid);
+ void hostapd_free_neighbor_db(struct hostapd_data *hapd);
+
++int hostapd_neighbor_count(struct hostapd_data *hapd);
++int hostapd_neighbor_insert_buffer(struct hostapd_data *hapd, char *buf,
++ size_t buflen);
+ #endif /* NEIGHBOR_DB_H */
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/903-master-Support-including-neighbor-report-elements-in-ANQP-r.patch b/package/network/services/hostapd/patches/903-master-Support-including-neighbor-report-elements-in-ANQP-r.patch
new file mode 100644
index 0000000..3e6506a
--- /dev/null
+++ b/package/network/services/hostapd/patches/903-master-Support-including-neighbor-report-elements-in-ANQP-r.patch
@@ -0,0 +1,95 @@
+From adacd810f97a89472f26b454805cd67d0e6f5d31 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 19:25:05 +0800
+Subject: [PATCH 2/9] Support including neighbor report elements in ANQP
+ response
+
+---
+ src/ap/gas_serv.c | 29 +++++++++++++++++++++++++++++
+ src/ap/gas_serv.h | 2 ++
+ 2 files changed, 31 insertions(+)
+
+diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
+index 90f1577..5845ff8 100644
+--- a/src/ap/gas_serv.c
++++ b/src/ap/gas_serv.c
+@@ -19,6 +19,7 @@
+ #include "dpp_hostapd.h"
+ #include "sta_info.h"
+ #include "gas_serv.h"
++#include "neighbor_db.h"
+
+
+ #ifdef CONFIG_DPP
+@@ -369,6 +370,24 @@ static void anqp_add_network_auth_type(struct hostapd_data *hapd,
+ }
+ }
+
++static void anqp_add_neighbor_report(struct hostapd_data *hapd,
++ struct wpabuf *buf)
++{
++ struct hostapd_neighbor_entry *nr;
++ u8 *len_pos = gas_anqp_add_element(buf, ANQP_NEIGHBOR_REPORT);
++ if (dl_list_empty(&hapd->nr_db)) {
++ wpabuf_put_le16(buf, 0);
++ }
++ else {
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list ) {
++ wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT);
++ wpabuf_put_u8(buf, wpabuf_len(nr->nr));
++ wpabuf_put_buf(buf, nr->nr);
++ }
++ }
++ gas_anqp_set_element_len(buf, len_pos);
++}
++
+
+ static void anqp_add_roaming_consortium(struct hostapd_data *hapd,
+ struct wpabuf *buf)
+@@ -986,6 +1005,9 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
+ len += 1000;
+ if (request & ANQP_REQ_ICON_REQUEST)
+ len += 65536;
++ if (request & ANQP_REQ_NEIGHBOR_REPORT) {
++ len += (40 * hostapd_neighbor_count(hapd));
++ }
+ #ifdef CONFIG_FILS
+ if (request & ANQP_FILS_REALM_INFO)
+ len += 2 * dl_list_len(&hapd->conf->fils_realms);
+@@ -1028,6 +1050,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
+ anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY);
+ if (request & ANQP_REQ_EMERGENCY_NAI)
+ anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI);
++ if (request & ANQP_REQ_NEIGHBOR_REPORT)
++ anqp_add_neighbor_report(hapd, buf);
+
+ for (i = 0; i < num_extra_req; i++) {
+ #ifdef CONFIG_FILS
+@@ -1172,6 +1196,11 @@ static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id,
+ "Emergency NAI",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
++ case ANQP_NEIGHBOR_REPORT:
++ set_anqp_req(ANQP_REQ_NEIGHBOR_REPORT,
++ "Neighbor Report",
++ get_anqp_elem(hapd, info_id) != NULL, qi);
++ break;
+ default:
+ #ifdef CONFIG_FILS
+ if (info_id == ANQP_FILS_REALM_INFO &&
+diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h
+index 1528af4..d0241f2 100644
+--- a/src/ap/gas_serv.h
++++ b/src/ap/gas_serv.h
+@@ -40,6 +40,8 @@
+ (1 << (ANQP_TDLS_CAPABILITY - ANQP_QUERY_LIST))
+ #define ANQP_REQ_EMERGENCY_NAI \
+ (1 << (ANQP_EMERGENCY_NAI - ANQP_QUERY_LIST))
++#define ANQP_REQ_NEIGHBOR_REPORT \
++ (1 << (ANQP_NEIGHBOR_REPORT - ANQP_QUERY_LIST))
+ /*
+ * First 15 Hotspot 2.0 vendor specific ANQP-elements can be included in the
+ * optimized bitmap.
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/904-master-Support-including-neignbor-report-elements-in-BTM-re.patch b/package/network/services/hostapd/patches/904-master-Support-including-neignbor-report-elements-in-BTM-re.patch
new file mode 100644
index 0000000..86d8fd1
--- /dev/null
+++ b/package/network/services/hostapd/patches/904-master-Support-including-neignbor-report-elements-in-BTM-re.patch
@@ -0,0 +1,68 @@
+From 4a7b4a0fe05dd01ae64dd4e291d05de6d5f05bb7 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 19:49:09 +0800
+Subject: [PATCH 3/9] Support including neignbor report elements in BTM
+ response
+
+---
+ src/ap/wnm_ap.c | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
+index 72cd126..b55b3f3 100644
+--- a/src/ap/wnm_ap.c
++++ b/src/ap/wnm_ap.c
+@@ -20,6 +20,7 @@
+ #include "ap/wpa_auth.h"
+ #include "mbo_ap.h"
+ #include "wnm_ap.h"
++#include "ap/neighbor_db.h"
+
+ #define MAX_TFS_IE_LEN 1024
+
+@@ -370,9 +371,21 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
+ u8 *pos;
+ int res;
+
+- mgmt = os_zalloc(sizeof(*mgmt));
+- if (mgmt == NULL)
++ int nr_num = hostapd_neighbor_count(hapd);
++ int nr_size = ETH_ALEN + 4 + 1 + 1 + 1 + 5;
++ int total_nr_size = nr_num * nr_size;
++ u8 *nr_data = os_malloc(total_nr_size);
++ int nr_data_len = 0;
++ if(nr_data == NULL) {
++ wpa_printf (MSG_ERROR, "Failed to allocate memory");
++ } else {
++ nr_data_len = hostapd_neighbor_insert_buffer(hapd, nr_data, total_nr_size);
++ }
++ mgmt = os_zalloc(sizeof(*mgmt) + nr_data_len);
++ if (mgmt == NULL) {
++ wpa_printf (MSG_ERROR, "Failed to allocate memory for mgmt frame");
+ return -1;
++ }
+ os_memcpy(mgmt->da, addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+@@ -382,10 +395,18 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
+ mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+ mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token;
+ mgmt->u.action.u.bss_tm_req.req_mode = 0;
++ if(nr_num) {
++ mgmt->u.action.u.bss_tm_req.req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
++ }
+ mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
+ mgmt->u.action.u.bss_tm_req.validity_interval = 1;
+ pos = mgmt->u.action.u.bss_tm_req.variable;
+
++ if(nr_num) {
++ os_memcpy(pos, nr_data, nr_data_len);
++ pos += nr_data_len;
++ }
++
+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
+ MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/905-master-Support-configuring-BSS-Termination-TSF-by-using-hos.patch b/package/network/services/hostapd/patches/905-master-Support-configuring-BSS-Termination-TSF-by-using-hos.patch
new file mode 100644
index 0000000..f6832e3
--- /dev/null
+++ b/package/network/services/hostapd/patches/905-master-Support-configuring-BSS-Termination-TSF-by-using-hos.patch
@@ -0,0 +1,66 @@
+From 56613ad9b568a3ac7467105beaa162c68ffbbf70 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 20:20:03 +0800
+Subject: [PATCH 4/9] Support configuring BSS Termination TSF by using
+ hostapd_cli command
+
+---
+ hostapd/ctrl_iface.c | 9 +++++++++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 1 +
+ 3 files changed, 11 insertions(+)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index f50fafb..1b5a091 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -954,6 +954,10 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ wpa_printf(MSG_DEBUG, "Invalid bss_term data");
+ return -1;
+ }
++ if (hapd->conf->bss_termination_tsf) {
++ WPA_PUT_LE64(&bss_term_dur[2], hapd->conf->bss_termination_tsf);
++ }
++
+ end++;
+ WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
+ }
+@@ -1589,6 +1593,11 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
+ #endif /* CONFIG_DPP */
+ } else if (os_strcasecmp(cmd, "setband") == 0) {
+ ret = hostapd_ctrl_iface_set_band(hapd, value);
++ } else if (os_strcasecmp(cmd, "bss_termination_tsf") == 0) {
++ int termination_sec = atoi(value);
++ hapd->conf->bss_termination_tsf = termination_sec;
++ wpa_printf(MSG_DEBUG, "BSS Termination TSF: value = %d",
++ termination_sec);
+ } else {
+ ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
+ if (ret)
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 1f04686..078a3fc 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -170,6 +170,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
+ /* comeback after 10 TUs */
+ bss->pasn_comeback_after = 10;
+ #endif /* CONFIG_PASN */
++ bss->bss_termination_tsf = 0;
+ }
+
+
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index f3aff36..7301bbb 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -549,6 +549,7 @@ struct hostapd_bss_config {
+ int wnm_sleep_mode;
+ int wnm_sleep_mode_no_keys;
+ int bss_transition;
++ unsigned int bss_termination_tsf;
+
+ /* IEEE 802.11u - Interworking */
+ int interworking;
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/906-master-Disable-interface-if-BSS-Termination-TSF-is-set.patch b/package/network/services/hostapd/patches/906-master-Disable-interface-if-BSS-Termination-TSF-is-set.patch
new file mode 100644
index 0000000..0d28e4e
--- /dev/null
+++ b/package/network/services/hostapd/patches/906-master-Disable-interface-if-BSS-Termination-TSF-is-set.patch
@@ -0,0 +1,47 @@
+From dcedb231bc62949d458792530a14ceddfee20e96 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 21:03:38 +0800
+Subject: [PATCH 5/9] Disable interface if BSS Termination TSF is set
+
+---
+ src/ap/wnm_ap.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
+index b55b3f3..6eac3ac 100644
+--- a/src/ap/wnm_ap.c
++++ b/src/ap/wnm_ap.c
+@@ -767,6 +767,22 @@ static void set_disassoc_timer(struct hostapd_data *hapd, struct sta_info *sta,
+ }
+
+
++void bss_termination_disable_iface(void *eloop_ctx, void *timeout_ctx)
++{
++ struct hostapd_data *hapd = eloop_ctx;
++ hostapd_disable_iface(hapd->iface);
++}
++
++
++static void set_disable_iface_timer(struct hostapd_data *hapd, struct sta_info *sta,
++ int disable_iface_timer)
++{
++ wpa_printf(MSG_DEBUG, "Disable interface timer set to %d secs", disable_iface_timer);
++ eloop_register_timeout(disable_iface_timer, 0,
++ bss_termination_disable_iface, hapd, NULL);
++}
++
++
+ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
+ struct sta_info *sta, const char *url,
+ int disassoc_timer)
+@@ -856,6 +872,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
+ bss_term_dur) {
+ os_memcpy(pos, bss_term_dur, 12);
+ pos += 12;
++ set_disable_iface_timer(hapd, sta, hapd->conf->bss_termination_tsf);
+ }
+
+ if (url) {
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/907-master-Add-set_send_disassoc_frame_timer-to-send-disassocia.patch b/package/network/services/hostapd/patches/907-master-Add-set_send_disassoc_frame_timer-to-send-disassocia.patch
new file mode 100644
index 0000000..be0f823
--- /dev/null
+++ b/package/network/services/hostapd/patches/907-master-Add-set_send_disassoc_frame_timer-to-send-disassocia.patch
@@ -0,0 +1,63 @@
+From cb31775e39eaa2b8a0bd36f5e195ac8bff967535 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 21:15:07 +0800
+Subject: [PATCH 6/9] Add set_send_disassoc_frame_timer() to send disassociate
+ frame
+
+Function set_disassoc_timer() may fail if key was deleted first. This new
+function will not ask to delete key as set_disassoc_timer() did.
+---
+ src/ap/wnm_ap.c | 30 +++++++++++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
+index 6eac3ac..fad132c 100644
+--- a/src/ap/wnm_ap.c
++++ b/src/ap/wnm_ap.c
+@@ -767,6 +767,34 @@ static void set_disassoc_timer(struct hostapd_data *hapd, struct sta_info *sta,
+ }
+
+
++static void set_send_disassoc_frame_timer(struct hostapd_data *hapd, struct sta_info *sta,
++ int disassoc_timer)
++{
++ int timeout, beacon_int;
++
++ /*
++ * Prevent STA from reconnecting using cached PMKSA to force
++ * full authentication with the authentication server (which may
++ * decide to reject the connection),
++ */
++ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
++
++ beacon_int = hapd->iconf->beacon_int;
++ if (beacon_int < 1)
++ beacon_int = 100; /* best guess */
++ /* Calculate timeout in ms based on beacon_int in TU */
++ timeout = disassoc_timer * beacon_int * 128 / 125;
++ wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
++ " set to %d ms", MAC2STR(sta->addr), timeout);
++
++ u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
++
++ hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
++ if (sta)
++ ap_sta_disassociate(hapd, sta, reason);
++}
++
++
+ void bss_termination_disable_iface(void *eloop_ctx, void *timeout_ctx)
+ {
+ struct hostapd_data *hapd = eloop_ctx;
+@@ -909,7 +937,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
+ if (disassoc_timer) {
+ /* send disassociation frame after time-out */
+- set_disassoc_timer(hapd, sta, disassoc_timer);
++ set_send_disassoc_frame_timer(hapd, sta, disassoc_timer);
+ }
+
+ return 0;
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/908-master-Support-including-neighbor-report-elements-in-BTM-re.patch b/package/network/services/hostapd/patches/908-master-Support-including-neighbor-report-elements-in-BTM-re.patch
new file mode 100644
index 0000000..1bf102a
--- /dev/null
+++ b/package/network/services/hostapd/patches/908-master-Support-including-neighbor-report-elements-in-BTM-re.patch
@@ -0,0 +1,31 @@
+From 9043eff145701c6324ae48966301681adacb89c4 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 21:16:45 +0800
+Subject: [PATCH 7/9] Support including neighbor report elements in BTM request
+
+---
+ hostapd/ctrl_iface.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 1b5a091..5a82ae6 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -984,8 +984,13 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+ }
+
+- if (os_strstr(cmd, " pref=1"))
++ if (os_strstr(cmd, " pref=1")) {
+ req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
++ if (nei_len == 0) {
++ // Add neigibor report from neighbor report db to nei_rep buffer
++ nei_len = hostapd_neighbor_insert_buffer (hapd, nei_rep, 1000);
++ }
++ }
+ if (os_strstr(cmd, " abridged=1"))
+ req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
+ if (os_strstr(cmd, " disassoc_imminent=1"))
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/909-master-Add-hostapd_neighbor_set_own_report_pref.patch b/package/network/services/hostapd/patches/909-master-Add-hostapd_neighbor_set_own_report_pref.patch
new file mode 100644
index 0000000..14571fe
--- /dev/null
+++ b/package/network/services/hostapd/patches/909-master-Add-hostapd_neighbor_set_own_report_pref.patch
@@ -0,0 +1,88 @@
+From 6fc069a54efb892e486dfde59cb97e0023dbbf5d Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 21:27:55 +0800
+Subject: [PATCH 8/9] Add hostapd_neighbor_set_own_report_pref()
+
+If my own BSS is going to terminate itself, the preference value of neighbor
+report must be set to 0.
+---
+ hostapd/ctrl_iface.c | 5 ++++-
+ src/ap/neighbor_db.c | 36 ++++++++++++++++++++++++++++++++++++
+ src/ap/neighbor_db.h | 2 ++
+ 3 files changed, 42 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 5a82ae6..3146a25 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -993,8 +993,11 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ }
+ if (os_strstr(cmd, " abridged=1"))
+ req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
+- if (os_strstr(cmd, " disassoc_imminent=1"))
++ if (os_strstr(cmd, " disassoc_imminent=1")) {
+ req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
++ /* Set own BSS neighbor report preference value as 0 */
++ hostapd_neighbor_set_own_report_pref(hapd, nei_rep, nei_len, 0);
++ }
+
+ #ifdef CONFIG_MBO
+ pos = os_strstr(cmd, "mbo=");
+diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
+index ce6865d..bc1b163 100644
+--- a/src/ap/neighbor_db.c
++++ b/src/ap/neighbor_db.c
+@@ -352,3 +352,39 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
+ wpabuf_free(nr);
+ #endif /* NEED_AP_MLME */
+ }
++
++
++void hostapd_neighbor_set_own_report_pref(struct hostapd_data *hapd, char *nei_buf,
++ size_t buflen, const int pref)
++{
++ struct hostapd_neighbor_entry *nr;
++ char *pos, *next_nr;
++
++ pos = nei_buf;
++ next_nr = nei_buf;
++
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ pos = next_nr;
++ next_nr = pos + 2 + wpabuf_len(nr->nr);
++ /* Shift 2 bytes for Element ID and Neighbor report length */
++ pos = pos + 2;
++ if(os_memcmp(pos, hapd->own_addr, ETH_ALEN) == 0) {
++ /* Shift for BSSID + BSSID info + Op_class + channel num + PHY type */
++ pos = pos + 6 + 4 + 1 + 1 + 1;
++
++ /* Iterate Subelement */
++ while (next_nr - pos > 0) {
++ if (*pos == 3) {
++ pos = pos + 2;
++ *pos = pref;
++ return;
++ } else {
++ pos++;
++ int shift_len = *pos++;
++ pos = pos + shift_len;
++ }
++ }
++ }
++ }
++}
+diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
+index 1ae194d..2e16f72 100644
+--- a/src/ap/neighbor_db.h
++++ b/src/ap/neighbor_db.h
+@@ -27,4 +27,6 @@ void hostapd_free_neighbor_db(struct hostapd_data *hapd);
+ int hostapd_neighbor_count(struct hostapd_data *hapd);
+ int hostapd_neighbor_insert_buffer(struct hostapd_data *hapd, char *buf,
+ size_t buflen);
++void hostapd_neighbor_set_own_report_pref(struct hostapd_data *hapd, char *nei_buf,
++ size_t buflen, const int pref);
+ #endif /* NEIGHBOR_DB_H */
+--
+2.18.0
+
diff --git a/package/network/services/hostapd/patches/910-master-Add-hostapd_neighbor_set_pref_by_non_pref_chan.patch b/package/network/services/hostapd/patches/910-master-Add-hostapd_neighbor_set_pref_by_non_pref_chan.patch
new file mode 100644
index 0000000..632475c
--- /dev/null
+++ b/package/network/services/hostapd/patches/910-master-Add-hostapd_neighbor_set_pref_by_non_pref_chan.patch
@@ -0,0 +1,101 @@
+From 7aab6cf66cfb7dea480d16e312e0f0eb08e758ab Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 21:32:17 +0800
+Subject: [PATCH 9/9] Add hostapd_neighbor_set_pref_by_non_pref_chan()
+
+The preference value of neighbor report shall be modified according to struct
+non_pref_chan_info.
+---
+ hostapd/ctrl_iface.c | 2 ++
+ src/ap/neighbor_db.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
+ src/ap/neighbor_db.h | 4 ++++
+ 3 files changed, 57 insertions(+)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 3146a25..974e5b9 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -1000,6 +1000,8 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ }
+
+ #ifdef CONFIG_MBO
++ hostapd_neighbor_set_pref_by_non_pref_chan(hapd, sta, nei_rep, nei_len);
++
+ pos = os_strstr(cmd, "mbo=");
+ if (pos) {
+ unsigned int mbo_reason, cell_pref, reassoc_delay;
+diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
+index bc1b163..75b6fcc 100644
+--- a/src/ap/neighbor_db.c
++++ b/src/ap/neighbor_db.c
+@@ -388,3 +388,54 @@ void hostapd_neighbor_set_own_report_pref(struct hostapd_data *hapd, char *nei_b
+ }
+ }
+ }
++
++#ifdef CONFIG_MBO
++void hostapd_neighbor_set_pref_by_non_pref_chan(struct hostapd_data *hapd,
++ struct sta_info* sta, char *nei_buf, size_t buflen)
++{
++ struct hostapd_neighbor_entry *nr;
++ struct mbo_non_pref_chan_info *info;
++ u8 i;
++
++ for(info = sta->non_pref_chan; info; info = info->next) {
++ /* Check OP_Class and Channel num */
++ for(i = 0; i < info->num_channels; i++) {
++ char *pos, *next_nr;
++
++ pos = nei_buf;
++ next_nr = nei_buf;
++
++ /* Iterate Neighbor report database */
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ pos = next_nr;
++ next_nr = pos + 2 + wpabuf_len(nr->nr);
++ /**
++ * Shift 12 bytes for Element ID, Neighbor report length,
++ * BSSID and BSSID info.
++ */
++ pos = pos + 12;
++ int nr_op_class = *pos++;
++ int nr_channel = *pos;
++ if(info->op_class == nr_op_class && info->channels[i] == nr_channel) {
++ /* Shift for Channel Num + PHY type */
++ pos = pos + 1 + 1;
++
++ // Iterate Subelement
++ while(next_nr - pos > 0) {
++ if(*pos == 3) {
++ pos = pos + 2;
++ *pos = info->pref;
++ break;
++ }else {
++ pos++;
++ int shift_len = *pos++;
++ pos = pos + shift_len;
++ }
++ }
++ }
++ }
++ }
++ }
++}
++#endif
+diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
+index 2e16f72..a1ddc07 100644
+--- a/src/ap/neighbor_db.h
++++ b/src/ap/neighbor_db.h
+@@ -29,4 +29,8 @@ int hostapd_neighbor_insert_buffer(struct hostapd_data *hapd, char *buf,
+ size_t buflen);
+ void hostapd_neighbor_set_own_report_pref(struct hostapd_data *hapd, char *nei_buf,
+ size_t buflen, const int pref);
++#ifdef CONFIG_MBO
++void hostapd_neighbor_set_pref_by_non_pref_chan(struct hostapd_data *hapd,
++ struct sta_info* sta, char *nei_buf, size_t buflen);
++#endif
+ #endif /* NEIGHBOR_DB_H */
+--
+2.18.0
+
--
2.18.0