Advertisement
Guest User

Untitled

a guest
May 21st, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.05 KB | None | 0 0
  1. From 11e9ffc61037f15ce3161f80c660dfcf5f7dc2c3 Mon Sep 17 00:00:00 2001
  2. From: Robert Marko <robimarko@gmail.com>
  3. Date: Fri, 10 May 2019 20:38:20 +0200
  4. Subject: [PATCH] Add low RSSI features for OpenWrt
  5.  
  6. Still WIP and depends on ubus.
  7. ---
  8. hostapd/config_file.c | 20 ++++++++++++++++++++
  9. src/ap/ap_config.c | 7 +++++++
  10. src/ap/ap_config.h | 6 ++++++
  11. src/ap/sta_info.c | 4 ++++
  12. src/ap/sta_info.h | 4 ++++
  13. src/drivers/driver_nl80211.c | 4 ++++
  14. 6 files changed, 45 insertions(+)
  15.  
  16. --- a/hostapd/config_file.c
  17. +++ b/hostapd/config_file.c
  18. @@ -3149,6 +3149,26 @@ static int hostapd_config_fill(struct ho
  19. return 1;
  20. }
  21. conf->send_probe_response = val;
  22. +#ifdef UBUS_SUPPORT
  23. + } else if (os_strcmp(buf, "signal_connect") == 0) {
  24. + bss->signal_auth_min = atoi(pos);
  25. + } else if (os_strcmp(buf, "signal_stay") == 0) {
  26. + bss->signal_stay_min = atoi(pos);
  27. + } else if (os_strcmp(buf, "signal_poll_time") == 0) {
  28. + bss->signal_poll_time = atoi(pos);
  29. + if (bss->signal_poll_time < 2) {
  30. + wpa_printf(MSG_ERROR, "Line %d: invalid signal poll time", line);
  31. + return 1;
  32. + }
  33. + } else if (os_strcmp(buf, "signal_strikes") == 0) {
  34. + bss->signal_strikes = atoi(pos);
  35. + } else if (os_strcmp(buf, "signal_drop_reason") == 0) {
  36. + bss->signal_drop_reason = atoi(pos);
  37. + if (bss->signal_drop_reason < 1 || bss->signal_drop_reason > 54) {
  38. + wpa_printf(MSG_ERROR, "Line %d: invalid signal drop reason", line);
  39. + return 1;
  40. + }
  41. +#endif /* UBUS_SUPPORT */
  42. } else if (os_strcmp(buf, "supported_rates") == 0) {
  43. if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
  44. wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
  45. --- a/src/ap/ap_config.c
  46. +++ b/src/ap/ap_config.c
  47. @@ -80,6 +80,13 @@ void hostapd_config_defaults_bss(struct
  48. bss->eapol_version = EAPOL_VERSION;
  49.  
  50. bss->max_listen_interval = 65535;
  51. +#ifdef UBUS_SUPPORT
  52. + bss->signal_auth_min = -128; /* this is lower than any real signal, so all stations will be accepted */
  53. + bss->signal_stay_min = -128;
  54. + bss->signal_strikes = 3;
  55. + bss->signal_poll_time = 10;
  56. + bss->signal_drop_reason = 3; /* "Local choice" */
  57. +#endif /* UBUS_SUPPORT */
  58.  
  59. bss->pwd_group = 19; /* ECC: GF(p=256) */
  60.  
  61. --- a/src/ap/ap_config.h
  62. +++ b/src/ap/ap_config.h
  63. @@ -322,6 +322,12 @@ struct hostapd_bss_config {
  64. int wds_sta;
  65. int isolate;
  66. int start_disabled;
  67. + int signal_auth_min; /* Minimum signal a STA needs to authenticate */
  68. + int signal_stay_min; /* Minimum signal needed to stay connected. */
  69. + int signal_poll_time; /* Time in seconds between checks of connected STAs */
  70. + int signal_strikes; /* Number of consecutive times signal can be low
  71. + before dropping the STA. */
  72. + int signal_drop_reason; /* IEEE802.11 reason code transmitted when dropping a STA. */
  73.  
  74. int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
  75. * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
  76. --- a/src/ap/sta_info.c
  77. +++ b/src/ap/sta_info.c
  78. @@ -706,6 +706,10 @@ struct sta_info * ap_sta_add(struct host
  79. &sta->probe_ie_taxonomy);
  80. #endif /* CONFIG_TAXONOMY */
  81.  
  82. +#ifdef UBUS_SUPPORT
  83. + sta->sig_drop_strikes = 0;
  84. +#endif /* UBUS_SUPPORT */
  85. +
  86. return sta;
  87. }
  88.  
  89. --- a/src/ap/sta_info.h
  90. +++ b/src/ap/sta_info.h
  91. @@ -252,6 +252,10 @@ struct sta_info {
  92. struct wpabuf *fils_g_sta;
  93. #endif /* CONFIG_FILS */
  94.  
  95. +#ifdef UBUS_SUPPORT
  96. + int sig_drop_strikes; /* Number of times signal was below threshold. */
  97. +#endif /* UBUS_SUPPORT */
  98. +
  99. #ifdef CONFIG_OWE
  100. u8 *owe_pmk;
  101. size_t owe_pmk_len;
  102. --- a/src/drivers/driver_nl80211.c
  103. +++ b/src/drivers/driver_nl80211.c
  104. @@ -6179,6 +6179,7 @@ static int get_sta_handler(struct nl_msg
  105. [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
  106. [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
  107. [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
  108. + [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
  109. [NL80211_STA_INFO_ACK_SIGNAL] = { .type = NLA_U8 },
  110. };
  111. struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
  112. @@ -6242,6 +6243,9 @@ static int get_sta_handler(struct nl_msg
  113. nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
  114. if (stats[NL80211_STA_INFO_SIGNAL])
  115. data->signal = nla_get_u8(stats[NL80211_STA_INFO_SIGNAL]);
  116. + if (stats[NL80211_STA_INFO_SIGNAL_AVG])
  117. + data->last_ack_rssi =
  118. + (int) (s8) nla_get_u8(stats[NL80211_STA_INFO_SIGNAL_AVG]);
  119. if (stats[NL80211_STA_INFO_ACK_SIGNAL]) {
  120. data->last_ack_rssi =
  121. nla_get_u8(stats[NL80211_STA_INFO_ACK_SIGNAL]);
  122. --- a/src/ap/ubus.c
  123. +++ b/src/ap/ubus.c
  124. @@ -142,6 +142,59 @@ hostapd_bss_ban_client(struct hostapd_da
  125. eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd);
  126. }
  127.  
  128. +static void
  129. +hostapd_bss_signal_check(void *eloop_data, void *user_ctx)
  130. +/* This is called by an eloop timeout. All stations in the list are checked
  131. + * for signal level. This requires calling the driver, since hostapd doesn't
  132. + * see packets from a station once it is fully authorized.
  133. + * Stations with signal level below the threshold will be dropped.
  134. + * Cases where the last RSSI is significantly less than the average are usually
  135. + * a bad reading and should not lead to a drop.
  136. + */
  137. +{
  138. + struct hostapd_data *hapd = user_ctx;
  139. + struct hostap_sta_driver_data data;
  140. + struct sta_info *sta, *sta_next;
  141. + u8 addr[ETH_ALEN]; // Buffer the address for logging purposes, in case it is destroyed while dropping
  142. + int strikes; // same with strike count on this station.
  143. + int num_sta = 0;
  144. + int num_drop = 0;
  145. + int signal_inst;
  146. + int signal_avg;
  147. +
  148. +
  149. + for (sta = hapd->sta_list; sta; sta = sta_next) {
  150. + sta_next = sta->next;
  151. + memcpy(addr, sta->addr, ETH_ALEN);
  152. + if (!hostapd_drv_read_sta_data(hapd, &data, addr)) {
  153. + signal_inst = data.signal;
  154. + signal_avg = data.last_ack_rssi;
  155. + num_sta++;
  156. + strikes = sta->sig_drop_strikes;
  157. + if (signal_inst > signal_avg)
  158. + signal_avg = signal_inst;
  159. + if (signal_inst > (signal_avg - 5)) { // ignore unusually low instantaneous signal.
  160. + if (signal_avg < hapd->conf->signal_stay_min) { // signal bad.
  161. + strikes = ++sta->sig_drop_strikes;
  162. + if (strikes >= hapd->conf->signal_strikes) { // Struck out--, drop.
  163. + ap_sta_deauthenticate(hapd, sta, hapd->conf->signal_drop_reason);
  164. + num_drop++;
  165. + }
  166. + }
  167. + else {
  168. + sta->sig_drop_strikes = 0; // signal OK, reset the strike counter.
  169. + strikes = 0;
  170. + }
  171. + }
  172. + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_DEBUG, "%i %i (%i)",
  173. + data.signal, data.last_ack_rssi, strikes);
  174. + }
  175. + }
  176. + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_INFO, "signal poll: %i STAs, %i dropped", num_sta, num_drop);
  177. +
  178. + eloop_register_timeout(hapd->conf->signal_poll_time, 0, hostapd_bss_signal_check, eloop_data, hapd);
  179. +}
  180. +
  181. static int
  182. hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
  183. struct ubus_request_data *req, const char *method,
  184. @@ -503,6 +556,72 @@ hostapd_vendor_elements(struct ubus_cont
  185. return UBUS_STATUS_OK;
  186. }
  187.  
  188. +enum {
  189. + SIGNAL_CONNECT,
  190. + SIGNAL_STAY,
  191. + SIGNAL_STRIKES,
  192. + SIGNAL_POLL,
  193. + SIGNAL_DROP_REASON,
  194. + __SIGNAL_SETTINGS_MAX
  195. +};
  196. +
  197. +static const struct blobmsg_policy sig_policy[__SIGNAL_SETTINGS_MAX] = {
  198. + [SIGNAL_CONNECT] = {"connect", BLOBMSG_TYPE_INT32},
  199. + [SIGNAL_STAY] = {"stay", BLOBMSG_TYPE_INT32},
  200. + [SIGNAL_STRIKES] = {"strikes", BLOBMSG_TYPE_INT32},
  201. + [SIGNAL_POLL] = {"poll_time", BLOBMSG_TYPE_INT32},
  202. + [SIGNAL_DROP_REASON] = {"reason", BLOBMSG_TYPE_INT32}
  203. +};
  204. +
  205. +static int
  206. +hostapd_bss_set_signal(struct ubus_context *ctx, struct ubus_object *obj,
  207. + struct ubus_request_data *req, const char *method,
  208. + struct blob_attr *msg)
  209. +{
  210. + struct blob_attr *tb[__SIGNAL_SETTINGS_MAX];
  211. + struct hostapd_data *hapd = get_hapd_from_object(obj);
  212. + int sig_stay;
  213. +
  214. + blobmsg_parse(sig_policy, __SIGNAL_SETTINGS_MAX, tb, blob_data(msg), blob_len(msg));
  215. +
  216. + if (!tb[SIGNAL_CONNECT])
  217. + return UBUS_STATUS_INVALID_ARGUMENT;
  218. + hapd->conf->signal_auth_min = blobmsg_get_u32(tb[SIGNAL_CONNECT]);
  219. + if (tb[SIGNAL_STAY]) {
  220. + sig_stay = blobmsg_get_u32(tb[SIGNAL_STAY]);
  221. +
  222. + }
  223. + else
  224. + sig_stay = hapd->conf->signal_auth_min - 5; // Default is 5 dB lower to stay.
  225. + hapd->conf->signal_stay_min = sig_stay;
  226. + if (tb[SIGNAL_STRIKES]) {
  227. + hapd->conf->signal_strikes = blobmsg_get_u32(tb[SIGNAL_STRIKES]);
  228. + if (hapd->conf->signal_strikes < 1)
  229. + return UBUS_STATUS_INVALID_ARGUMENT;
  230. + }
  231. + else
  232. + hapd->conf->signal_strikes = 3;
  233. + if (tb[SIGNAL_POLL]) {
  234. + hapd->conf->signal_poll_time = blobmsg_get_u32(tb[SIGNAL_POLL]);
  235. + if (hapd->conf->signal_poll_time < 3)
  236. + return UBUS_STATUS_INVALID_ARGUMENT;
  237. + }
  238. + else
  239. + hapd->conf->signal_poll_time = 10;
  240. + if (tb[SIGNAL_DROP_REASON]) {
  241. + hapd->conf->signal_drop_reason = blobmsg_get_u32(tb[SIGNAL_DROP_REASON]);
  242. + if ((hapd->conf->signal_drop_reason < 1) || (hapd->conf->signal_drop_reason > 35)) // XXX -- look up real limit
  243. + return UBUS_STATUS_INVALID_ARGUMENT;
  244. + }
  245. + else
  246. + hapd->conf->signal_drop_reason = 3; // Local choice. 5 (AP too busy) is also a good one.
  247. +
  248. + eloop_cancel_timeout(hostapd_bss_signal_check, ELOOP_ALL_CTX, ELOOP_ALL_CTX);
  249. + eloop_register_timeout(3, 0, hostapd_bss_signal_check, NULL, hapd); // Start up the poll timer.
  250. +
  251. + return UBUS_STATUS_OK;
  252. +}
  253. +
  254. static void
  255. hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr)
  256. {
  257. @@ -960,6 +1079,7 @@ static const struct ubus_method bss_meth
  258. UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy),
  259. #endif
  260. UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy),
  261. + UBUS_METHOD("set_required_signal", hostapd_bss_set_signal, sig_policy),
  262. UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy),
  263. UBUS_METHOD("bss_mgmt_enable", hostapd_bss_mgmt_enable, bss_mgmt_enable_policy),
  264. UBUS_METHOD_NOARG("rrm_nr_get_own", hostapd_rrm_nr_get_own),
  265. @@ -1003,6 +1123,9 @@ void hostapd_ubus_add_bss(struct hostapd
  266. obj->n_methods = bss_object_type.n_methods;
  267. ret = ubus_add_object(ctx, obj);
  268. hostapd_ubus_ref_inc();
  269. + /* This should run after the config file has been read, I hope. */
  270. + if (hapd->conf->signal_stay_min > -128)
  271. + eloop_register_timeout(3, 0, hostapd_bss_signal_check, NULL, hapd); // Start up the poll timer.
  272. }
  273.  
  274. void hostapd_ubus_free_bss(struct hostapd_data *hapd)
  275. @@ -1051,6 +1174,19 @@ int hostapd_ubus_handle_event(struct hos
  276. else
  277. addr = req->addr;
  278.  
  279. + if (req->type < ARRAY_SIZE(types))
  280. + type = types[req->type];
  281. +
  282. + if (req->frame_info && req->type != HOSTAPD_UBUS_PROBE_REQ) // don't clutter the log with probes.
  283. + hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME, HOSTAPD_LEVEL_INFO, "%s request, signal %i %s",
  284. + type, req->frame_info->ssi_signal,
  285. + (req->frame_info->ssi_signal >= hapd->conf->signal_auth_min) ? "(Accepted)" : "(DENIED)");
  286. + // reject weak signals.
  287. + if (req->frame_info && req->frame_info->ssi_signal < hapd->conf->signal_auth_min)
  288. + return -2;
  289. +
  290. + // reject banned MACs.
  291. +
  292. ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl);
  293. if (ban)
  294. return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
  295. @@ -1058,9 +1194,6 @@ int hostapd_ubus_handle_event(struct hos
  296. if (!hapd->ubus.obj.has_subscribers)
  297. return WLAN_STATUS_SUCCESS;
  298.  
  299. - if (req->type < ARRAY_SIZE(types))
  300. - type = types[req->type];
  301. -
  302. blob_buf_init(&b, 0);
  303. blobmsg_add_macaddr(&b, "address", addr);
  304. if (req->mgmt_frame)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement