2
0

370-ap_sta_support.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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. @@ -117,6 +121,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. @@ -82,6 +82,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. @@ -125,6 +125,55 @@ static void wpas_update_fils_connect_par
  108. #endif /* CONFIG_FILS && IEEE8021X_EAPOL */
  109. +static int hostapd_stop(struct wpa_supplicant *wpa_s)
  110. +{
  111. + const char *cmd = "STOP_AP";
  112. + char buf[256];
  113. + size_t len = sizeof(buf);
  114. +
  115. + if (wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL) < 0) {
  116. + wpa_printf(MSG_ERROR, "\nFailed to stop hostapd AP interfaces\n");
  117. + return -1;
  118. + }
  119. + return 0;
  120. +}
  121. +
  122. +static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
  123. +{
  124. + char *cmd = NULL;
  125. + char buf[256];
  126. + size_t len = sizeof(buf);
  127. + enum hostapd_hw_mode hw_mode;
  128. + u8 channel;
  129. + int sec_chan = 0;
  130. + int ret;
  131. +
  132. + if (!bss)
  133. + return -1;
  134. +
  135. + if (bss->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) {
  136. + int sec = bss->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
  137. + if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
  138. + sec_chan = 1;
  139. + else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
  140. + sec_chan = -1;
  141. + }
  142. +
  143. + hw_mode = ieee80211_freq_to_chan(bss->freq, &channel);
  144. + if (asprintf(&cmd, "UPDATE channel=%d sec_chan=%d hw_mode=%d",
  145. + channel, sec_chan, hw_mode) < 0)
  146. + return -1;
  147. +
  148. + ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
  149. + free(cmd);
  150. +
  151. + if (ret < 0) {
  152. + wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n");
  153. + return -1;
  154. + }
  155. + return 0;
  156. +}
  157. +
  158. /* Configure default/group WEP keys for static WEP */
  159. int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
  160. {
  161. @@ -920,12 +969,16 @@ void wpa_supplicant_set_state(struct wpa
  162. sme_sched_obss_scan(wpa_s, 1);
  163. + if (wpa_s->hostapd)
  164. + hostapd_reload(wpa_s, wpa_s->current_bss);
  165. #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
  166. if (!fils_hlp_sent && ssid && ssid->eap.erp)
  167. wpas_update_fils_connect_params(wpa_s);
  168. #endif /* CONFIG_FILS && IEEE8021X_EAPOL */
  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. @@ -1977,6 +2030,8 @@ void wpa_supplicant_associate(struct wpa
  177. wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
  178. ssid->id);
  179. wpas_notify_mesh_group_started(wpa_s, ssid);
  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. @@ -5487,6 +5542,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. @@ -5808,6 +5873,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. @@ -101,6 +101,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. @@ -513,6 +518,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. @@ -2328,6 +2328,11 @@ static int hostapd_ctrl_iface_chan_switc
  235. if (ret)
  236. return ret;
  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. @@ -1381,11 +1381,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/src/drivers/driver.h
  257. +++ b/src/drivers/driver.h
  258. @@ -4469,6 +4469,13 @@ enum wpa_event_type {
  259. EVENT_CH_SWITCH,
  260. /**
  261. + * EVENT_CH_SWITCH - AP or GO will switch channels soon
  262. + *
  263. + * Described in wpa_event_data.ch_switch
  264. + * */
  265. + EVENT_CH_SWITCH_STARTED,
  266. +
  267. + /**
  268. * EVENT_WNM - Request WNM operation
  269. *
  270. * This event can be used to request a WNM operation to be performed.
  271. @@ -5306,6 +5313,7 @@ union wpa_event_data {
  272. /**
  273. * struct ch_switch
  274. + * @count: countdown until channel switch
  275. * @freq: Frequency of new channel in MHz
  276. * @ht_enabled: Whether this is an HT channel
  277. * @ch_offset: Secondary channel offset
  278. @@ -5314,6 +5322,7 @@ union wpa_event_data {
  279. * @cf2: Center frequency 2
  280. */
  281. struct ch_switch {
  282. + int count;
  283. int freq;
  284. int ht_enabled;
  285. int ch_offset;
  286. --- a/src/drivers/driver_nl80211_event.c
  287. +++ b/src/drivers/driver_nl80211_event.c
  288. @@ -526,7 +526,8 @@ static int calculate_chan_offset(int wid
  289. static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
  290. struct nlattr *ifindex, struct nlattr *freq,
  291. struct nlattr *type, struct nlattr *bw,
  292. - struct nlattr *cf1, struct nlattr *cf2)
  293. + struct nlattr *cf1, struct nlattr *cf2,
  294. + struct nlattr *count)
  295. {
  296. struct i802_bss *bss;
  297. union wpa_event_data data;
  298. @@ -584,11 +585,15 @@ static void mlme_event_ch_switch(struct
  299. data.ch_switch.cf1 = nla_get_u32(cf1);
  300. if (cf2)
  301. data.ch_switch.cf2 = nla_get_u32(cf2);
  302. + if (count)
  303. + data.ch_switch.count = nla_get_u32(count);
  304. bss->freq = data.ch_switch.freq;
  305. drv->assoc_freq = data.ch_switch.freq;
  306. - wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
  307. + wpa_supplicant_event(bss->ctx,
  308. + count ? EVENT_CH_SWITCH_STARTED : EVENT_CH_SWITCH,
  309. + &data);
  310. }
  311. @@ -2446,6 +2451,7 @@ static void do_process_drv_event(struct
  312. tb[NL80211_ATTR_PMK],
  313. tb[NL80211_ATTR_PMKID]);
  314. break;
  315. + case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
  316. case NL80211_CMD_CH_SWITCH_NOTIFY:
  317. mlme_event_ch_switch(drv,
  318. tb[NL80211_ATTR_IFINDEX],
  319. @@ -2453,7 +2459,8 @@ static void do_process_drv_event(struct
  320. tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
  321. tb[NL80211_ATTR_CHANNEL_WIDTH],
  322. tb[NL80211_ATTR_CENTER_FREQ1],
  323. - tb[NL80211_ATTR_CENTER_FREQ2]);
  324. + tb[NL80211_ATTR_CENTER_FREQ2],
  325. + tb[NL80211_ATTR_CH_SWITCH_COUNT]);
  326. break;
  327. case NL80211_CMD_DISCONNECT:
  328. mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
  329. --- a/wpa_supplicant/events.c
  330. +++ b/wpa_supplicant/events.c
  331. @@ -4026,6 +4026,60 @@ static void wpas_event_assoc_reject(stru
  332. }
  333. +static void
  334. +supplicant_ch_switch_started(struct wpa_supplicant *wpa_s,
  335. + union wpa_event_data *data)
  336. +{
  337. + char buf[256];
  338. + size_t len = sizeof(buf);
  339. + char *cmd = NULL;
  340. + int width = 20;
  341. + int ret;
  342. +
  343. + if (!wpa_s->hostapd)
  344. + return;
  345. +
  346. + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
  347. + "count=%d freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
  348. + data->ch_switch.count,
  349. + data->ch_switch.freq,
  350. + data->ch_switch.ht_enabled,
  351. + data->ch_switch.ch_offset,
  352. + channel_width_to_string(data->ch_switch.ch_width),
  353. + data->ch_switch.cf1,
  354. + data->ch_switch.cf2);
  355. +
  356. + switch (data->ch_switch.ch_width) {
  357. + case CHAN_WIDTH_20_NOHT:
  358. + case CHAN_WIDTH_20:
  359. + width = 20;
  360. + break;
  361. + case CHAN_WIDTH_40:
  362. + width = 40;
  363. + break;
  364. + case CHAN_WIDTH_80:
  365. + width = 80;
  366. + break;
  367. + case CHAN_WIDTH_160:
  368. + case CHAN_WIDTH_80P80:
  369. + width = 160;
  370. + break;
  371. + }
  372. +
  373. + asprintf(&cmd, "CHAN_SWITCH %d %d sec_channel_offset=%d center_freq1=%d center_freq2=%d, bandwidth=%d auto-ht\n",
  374. + data->ch_switch.count - 1,
  375. + data->ch_switch.freq,
  376. + data->ch_switch.ch_offset,
  377. + data->ch_switch.cf1,
  378. + data->ch_switch.cf2,
  379. + width);
  380. + ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
  381. + free(cmd);
  382. +
  383. + if (ret < 0)
  384. + wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n");
  385. +}
  386. +
  387. void supplicant_event(void *ctx, enum wpa_event_type event,
  388. union wpa_event_data *data)
  389. {
  390. @@ -4309,6 +4363,10 @@ void supplicant_event(void *ctx, enum wp
  391. data->rx_from_unknown.wds);
  392. break;
  393. #endif /* CONFIG_AP */
  394. + case EVENT_CH_SWITCH_STARTED:
  395. + supplicant_ch_switch_started(wpa_s, data);
  396. + break;
  397. +
  398. case EVENT_CH_SWITCH:
  399. if (!data || !wpa_s->current_ssid)
  400. break;