370-ap_sta_support.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. --- a/wpa_supplicant/Makefile
  2. +++ b/wpa_supplicant/Makefile
  3. @@ -26,6 +26,10 @@ CFLAGS += $(EXTRA_CFLAGS)
  4. CFLAGS += -I$(abspath ../src)
  5. CFLAGS += -I$(abspath ../src/utils)
  6. +ifdef MULTICALL
  7. +CFLAGS += -DMULTICALL
  8. +endif
  9. +
  10. -include .config
  11. -include $(if $(MULTICALL),../hostapd/.config)
  12. @@ -118,6 +122,8 @@ OBJS_c += ../src/utils/common.o
  13. OBJS_c += ../src/common/cli.o
  14. OBJS += wmm_ac.o
  15. +OBJS += ../src/common/wpa_ctrl.o
  16. +
  17. ifndef CONFIG_OS
  18. ifdef CONFIG_NATIVE_WINDOWS
  19. CONFIG_OS=win32
  20. --- a/wpa_supplicant/bss.c
  21. +++ b/wpa_supplicant/bss.c
  22. @@ -11,6 +11,7 @@
  23. #include "utils/common.h"
  24. #include "utils/eloop.h"
  25. #include "common/ieee802_11_defs.h"
  26. +#include "common/ieee802_11_common.h"
  27. #include "drivers/driver.h"
  28. #include "eap_peer/eap.h"
  29. #include "wpa_supplicant_i.h"
  30. @@ -294,6 +295,10 @@ void calculate_update_time(const struct
  31. static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
  32. struct os_reltime *fetch_time)
  33. {
  34. + struct ieee80211_ht_capabilities *capab;
  35. + struct ieee80211_ht_operation *oper;
  36. + struct ieee802_11_elems elems;
  37. +
  38. dst->flags = src->flags;
  39. os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
  40. dst->freq = src->freq;
  41. @@ -306,6 +311,15 @@ static void wpa_bss_copy_res(struct wpa_
  42. dst->est_throughput = src->est_throughput;
  43. dst->snr = src->snr;
  44. + memset(&elems, 0, sizeof(elems));
  45. + ieee802_11_parse_elems((u8 *) (src + 1), src->ie_len, &elems, 0);
  46. + capab = (struct ieee80211_ht_capabilities *) elems.ht_capabilities;
  47. + oper = (struct ieee80211_ht_operation *) elems.ht_operation;
  48. + if (capab)
  49. + dst->ht_capab = le_to_host16(capab->ht_capabilities_info);
  50. + if (oper)
  51. + dst->ht_param = oper->ht_param;
  52. +
  53. calculate_update_time(fetch_time, src->age, &dst->last_update);
  54. }
  55. --- a/wpa_supplicant/bss.h
  56. +++ b/wpa_supplicant/bss.h
  57. @@ -83,6 +83,10 @@ struct wpa_bss {
  58. u8 ssid[SSID_MAX_LEN];
  59. /** Length of SSID */
  60. size_t ssid_len;
  61. + /** HT capabilities */
  62. + u16 ht_capab;
  63. + /* Five octets of HT Operation Information */
  64. + u8 ht_param;
  65. /** Frequency of the channel in MHz (e.g., 2412 = channel 1) */
  66. int freq;
  67. /** Beacon interval in TUs (host byte order) */
  68. --- a/wpa_supplicant/main.c
  69. +++ b/wpa_supplicant/main.c
  70. @@ -34,7 +34,7 @@ static void usage(void)
  71. "vW] [-P<pid file>] "
  72. "[-g<global ctrl>] \\\n"
  73. " [-G<group>] \\\n"
  74. - " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
  75. + " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-H<hostapd path>] "
  76. "[-p<driver_param>] \\\n"
  77. " [-b<br_ifname>] [-e<entropy file>]"
  78. #ifdef CONFIG_DEBUG_FILE
  79. @@ -74,6 +74,7 @@ static void usage(void)
  80. " -g = global ctrl_interface\n"
  81. " -G = global ctrl_interface group\n"
  82. " -h = show this help text\n"
  83. + " -H = connect to a hostapd instance to manage state changes\n"
  84. " -i = interface name\n"
  85. " -I = additional configuration file\n"
  86. " -K = include keys (passwords, etc.) in debug output\n"
  87. @@ -201,7 +202,7 @@ int main(int argc, char *argv[])
  88. for (;;) {
  89. c = getopt(argc, argv,
  90. - "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
  91. + "b:Bc:C:D:de:f:g:G:hH:i:I:KLMm:No:O:p:P:qsTtuvW");
  92. if (c < 0)
  93. break;
  94. switch (c) {
  95. @@ -248,6 +249,9 @@ int main(int argc, char *argv[])
  96. usage();
  97. exitcode = 0;
  98. goto out;
  99. + case 'H':
  100. + iface->hostapd_ctrl = optarg;
  101. + break;
  102. case 'i':
  103. iface->ifname = optarg;
  104. break;
  105. --- a/wpa_supplicant/wpa_supplicant.c
  106. +++ b/wpa_supplicant/wpa_supplicant.c
  107. @@ -129,6 +129,54 @@ static void wpas_update_fils_connect_par
  108. static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
  109. #endif /* CONFIG_OWE */
  110. +static int hostapd_stop(struct wpa_supplicant *wpa_s)
  111. +{
  112. + const char *cmd = "STOP_AP";
  113. + char buf[256];
  114. + size_t len = sizeof(buf);
  115. +
  116. + if (wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL) < 0) {
  117. + wpa_printf(MSG_ERROR, "\nFailed to stop hostapd AP interfaces\n");
  118. + return -1;
  119. + }
  120. + return 0;
  121. +}
  122. +
  123. +static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
  124. +{
  125. + char *cmd = NULL;
  126. + char buf[256];
  127. + size_t len = sizeof(buf);
  128. + enum hostapd_hw_mode hw_mode;
  129. + u8 channel;
  130. + int sec_chan = 0;
  131. + int ret;
  132. +
  133. + if (!bss)
  134. + return -1;
  135. +
  136. + if (bss->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) {
  137. + int sec = bss->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
  138. + if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
  139. + sec_chan = 1;
  140. + else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
  141. + sec_chan = -1;
  142. + }
  143. +
  144. + hw_mode = ieee80211_freq_to_chan(bss->freq, &channel);
  145. + if (asprintf(&cmd, "UPDATE channel=%d sec_chan=%d hw_mode=%d",
  146. + channel, sec_chan, hw_mode) < 0)
  147. + return -1;
  148. +
  149. + ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
  150. + free(cmd);
  151. +
  152. + if (ret < 0) {
  153. + wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n");
  154. + return -1;
  155. + }
  156. + return 0;
  157. +}
  158. #ifdef CONFIG_WEP
  159. /* Configure default/group WEP keys for static WEP */
  160. @@ -991,6 +1039,8 @@ void wpa_supplicant_set_state(struct wpa
  161. sme_sched_obss_scan(wpa_s, 1);
  162. + if (wpa_s->hostapd)
  163. + hostapd_reload(wpa_s, wpa_s->current_bss);
  164. #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
  165. if (!fils_hlp_sent && ssid && ssid->eap.erp)
  166. update_fils_connect_params = true;
  167. @@ -1001,6 +1051,8 @@ void wpa_supplicant_set_state(struct wpa
  168. #endif /* CONFIG_OWE */
  169. } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
  170. state == WPA_ASSOCIATED) {
  171. + if (wpa_s->hostapd)
  172. + hostapd_stop(wpa_s);
  173. wpa_s->new_connection = 1;
  174. wpa_drv_set_operstate(wpa_s, 0);
  175. #ifndef IEEE8021X_EAPOL
  176. @@ -2225,6 +2277,8 @@ void wpa_supplicant_associate(struct wpa
  177. return;
  178. }
  179. wpa_s->current_bss = bss;
  180. + if (wpa_s->hostapd)
  181. + hostapd_reload(wpa_s, wpa_s->current_bss);
  182. #else /* CONFIG_MESH */
  183. wpa_msg(wpa_s, MSG_ERROR,
  184. "mesh mode support not included in the build");
  185. @@ -6207,6 +6261,16 @@ static int wpa_supplicant_init_iface(str
  186. sizeof(wpa_s->bridge_ifname));
  187. }
  188. + if (iface->hostapd_ctrl) {
  189. + wpa_s->hostapd = wpa_ctrl_open(iface->hostapd_ctrl);
  190. + if (!wpa_s->hostapd) {
  191. + wpa_printf(MSG_ERROR, "\nFailed to connect to hostapd\n");
  192. + return -1;
  193. + }
  194. + if (hostapd_stop(wpa_s) < 0)
  195. + return -1;
  196. + }
  197. +
  198. /* RSNA Supplicant Key Management - INITIALIZE */
  199. eapol_sm_notify_portEnabled(wpa_s->eapol, false);
  200. eapol_sm_notify_portValid(wpa_s->eapol, false);
  201. @@ -6540,6 +6604,11 @@ static void wpa_supplicant_deinit_iface(
  202. if (terminate)
  203. wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
  204. + if (wpa_s->hostapd) {
  205. + wpa_ctrl_close(wpa_s->hostapd);
  206. + wpa_s->hostapd = NULL;
  207. + }
  208. +
  209. if (wpa_s->ctrl_iface) {
  210. wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
  211. wpa_s->ctrl_iface = NULL;
  212. --- a/wpa_supplicant/wpa_supplicant_i.h
  213. +++ b/wpa_supplicant/wpa_supplicant_i.h
  214. @@ -104,6 +104,11 @@ struct wpa_interface {
  215. const char *ifname;
  216. /**
  217. + * hostapd_ctrl - path to hostapd control socket for notification
  218. + */
  219. + const char *hostapd_ctrl;
  220. +
  221. + /**
  222. * bridge_ifname - Optional bridge interface name
  223. *
  224. * If the driver interface (ifname) is included in a Linux bridge
  225. @@ -530,6 +535,8 @@ struct wpa_supplicant {
  226. #endif /* CONFIG_CTRL_IFACE_BINDER */
  227. char bridge_ifname[16];
  228. + struct wpa_ctrl *hostapd;
  229. +
  230. char *confname;
  231. char *confanother;
  232. --- a/hostapd/ctrl_iface.c
  233. +++ b/hostapd/ctrl_iface.c
  234. @@ -2712,6 +2712,11 @@ static int hostapd_ctrl_iface_chan_switc
  235. return 0;
  236. }
  237. + if (os_strstr(pos, " auto-ht")) {
  238. + settings.freq_params.ht_enabled = iface->conf->ieee80211n;
  239. + settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
  240. + }
  241. +
  242. for (i = 0; i < iface->num_bss; i++) {
  243. /* Save CHAN_SWITCH VHT config */
  244. --- a/src/ap/beacon.c
  245. +++ b/src/ap/beacon.c
  246. @@ -1468,11 +1468,6 @@ int ieee802_11_set_beacon(struct hostapd
  247. struct wpabuf *beacon, *proberesp, *assocresp;
  248. int res, ret = -1;
  249. - if (hapd->csa_in_progress) {
  250. - wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
  251. - return -1;
  252. - }
  253. -
  254. hapd->beacon_set_done = 1;
  255. if (ieee802_11_build_ap_params(hapd, &params) < 0)
  256. --- a/wpa_supplicant/events.c
  257. +++ b/wpa_supplicant/events.c
  258. @@ -4581,6 +4581,60 @@ static void wpas_event_unprot_beacon(str
  259. }
  260. +static void
  261. +supplicant_ch_switch_started(struct wpa_supplicant *wpa_s,
  262. + union wpa_event_data *data)
  263. +{
  264. + char buf[256];
  265. + size_t len = sizeof(buf);
  266. + char *cmd = NULL;
  267. + int width = 20;
  268. + int ret;
  269. +
  270. + if (!wpa_s->hostapd)
  271. + return;
  272. +
  273. + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
  274. + "count=%d freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
  275. + data->ch_switch.count,
  276. + data->ch_switch.freq,
  277. + data->ch_switch.ht_enabled,
  278. + data->ch_switch.ch_offset,
  279. + channel_width_to_string(data->ch_switch.ch_width),
  280. + data->ch_switch.cf1,
  281. + data->ch_switch.cf2);
  282. +
  283. + switch (data->ch_switch.ch_width) {
  284. + case CHAN_WIDTH_20_NOHT:
  285. + case CHAN_WIDTH_20:
  286. + width = 20;
  287. + break;
  288. + case CHAN_WIDTH_40:
  289. + width = 40;
  290. + break;
  291. + case CHAN_WIDTH_80:
  292. + width = 80;
  293. + break;
  294. + case CHAN_WIDTH_160:
  295. + case CHAN_WIDTH_80P80:
  296. + width = 160;
  297. + break;
  298. + }
  299. +
  300. + asprintf(&cmd, "CHAN_SWITCH %d %d sec_channel_offset=%d center_freq1=%d center_freq2=%d, bandwidth=%d auto-ht\n",
  301. + data->ch_switch.count - 1,
  302. + data->ch_switch.freq,
  303. + data->ch_switch.ch_offset,
  304. + data->ch_switch.cf1,
  305. + data->ch_switch.cf2,
  306. + width);
  307. + ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
  308. + free(cmd);
  309. +
  310. + if (ret < 0)
  311. + wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n");
  312. +}
  313. +
  314. void supplicant_event(void *ctx, enum wpa_event_type event,
  315. union wpa_event_data *data)
  316. {
  317. @@ -4883,8 +4937,10 @@ void supplicant_event(void *ctx, enum wp
  318. channel_width_to_string(data->ch_switch.ch_width),
  319. data->ch_switch.cf1,
  320. data->ch_switch.cf2);
  321. - if (event == EVENT_CH_SWITCH_STARTED)
  322. + if (event == EVENT_CH_SWITCH_STARTED) {
  323. + supplicant_ch_switch_started(wpa_s, data);
  324. break;
  325. + }
  326. wpa_s->assoc_freq = data->ch_switch.freq;
  327. wpa_s->current_ssid->frequency = data->ch_switch.freq;
  328. --- a/src/drivers/driver.h
  329. +++ b/src/drivers/driver.h
  330. @@ -5690,6 +5690,7 @@ union wpa_event_data {
  331. /**
  332. * struct ch_switch
  333. + * @count: Count until channel switch activates
  334. * @freq: Frequency of new channel in MHz
  335. * @ht_enabled: Whether this is an HT channel
  336. * @ch_offset: Secondary channel offset
  337. @@ -5698,6 +5699,7 @@ union wpa_event_data {
  338. * @cf2: Center frequency 2
  339. */
  340. struct ch_switch {
  341. + int count;
  342. int freq;
  343. int ht_enabled;
  344. int ch_offset;
  345. --- a/src/drivers/driver_nl80211_event.c
  346. +++ b/src/drivers/driver_nl80211_event.c
  347. @@ -541,7 +541,7 @@ static void mlme_event_ch_switch(struct
  348. struct nlattr *ifindex, struct nlattr *freq,
  349. struct nlattr *type, struct nlattr *bw,
  350. struct nlattr *cf1, struct nlattr *cf2,
  351. - int finished)
  352. + struct nlattr *count, int finished)
  353. {
  354. struct i802_bss *bss;
  355. union wpa_event_data data;
  356. @@ -600,6 +600,8 @@ static void mlme_event_ch_switch(struct
  357. data.ch_switch.cf1 = nla_get_u32(cf1);
  358. if (cf2)
  359. data.ch_switch.cf2 = nla_get_u32(cf2);
  360. + if (count)
  361. + data.ch_switch.count = nla_get_u32(count);
  362. if (finished)
  363. bss->freq = data.ch_switch.freq;
  364. @@ -2686,6 +2688,7 @@ static void do_process_drv_event(struct
  365. tb[NL80211_ATTR_CHANNEL_WIDTH],
  366. tb[NL80211_ATTR_CENTER_FREQ1],
  367. tb[NL80211_ATTR_CENTER_FREQ2],
  368. + tb[NL80211_ATTR_CH_SWITCH_COUNT],
  369. 0);
  370. break;
  371. case NL80211_CMD_CH_SWITCH_NOTIFY:
  372. @@ -2696,6 +2699,7 @@ static void do_process_drv_event(struct
  373. tb[NL80211_ATTR_CHANNEL_WIDTH],
  374. tb[NL80211_ATTR_CENTER_FREQ1],
  375. tb[NL80211_ATTR_CENTER_FREQ2],
  376. + NULL,
  377. 1);
  378. break;
  379. case NL80211_CMD_DISCONNECT: