+
+
+void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
+ unsigned int type)
+{
+ type &= MAC_ADDR_RAND_ALL;
+ wpa_s->mac_addr_rand_enable &= ~type;
+
+ if (type & MAC_ADDR_RAND_SCAN) {
+ os_free(wpa_s->mac_addr_scan);
+ wpa_s->mac_addr_scan = NULL;
+ }
+
+ if (type & MAC_ADDR_RAND_SCHED_SCAN) {
+ os_free(wpa_s->mac_addr_sched_scan);
+ wpa_s->mac_addr_sched_scan = NULL;
+ }
+
+ if (type & MAC_ADDR_RAND_PNO) {
+ os_free(wpa_s->mac_addr_pno);
+ wpa_s->mac_addr_pno = NULL;
+ }
+}
+
+
+int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
+ unsigned int type, const u8 *addr,
+ const u8 *mask)
+{
+ u8 *tmp = NULL;
+
+ wpas_mac_addr_rand_scan_clear(wpa_s, type);
+
+ if (addr) {
+ tmp = os_malloc(2 * ETH_ALEN);
+ if (!tmp)
+ return -1;
+ os_memcpy(tmp, addr, ETH_ALEN);
+ os_memcpy(tmp + ETH_ALEN, mask, ETH_ALEN);
+ }
+
+ if (type == MAC_ADDR_RAND_SCAN) {
+ wpa_s->mac_addr_scan = tmp;
+ } else if (type == MAC_ADDR_RAND_SCHED_SCAN) {
+ wpa_s->mac_addr_sched_scan = tmp;
+ } else if (type == MAC_ADDR_RAND_PNO) {
+ wpa_s->mac_addr_pno = tmp;
+ } else {
+ wpa_printf(MSG_INFO,
+ "scan: Invalid MAC randomization type=0x%x",
+ type);
+ os_free(tmp);
+ return -1;
+ }
+
+ wpa_s->mac_addr_rand_enable |= type;
+ return 0;
+}
+
+
+int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
+{
+ int scan_work = !!wpa_s->scan_work;
+
+#ifdef CONFIG_P2P
+ scan_work |= !!wpa_s->p2p_scan_work;
+#endif /* CONFIG_P2P */
+
+ if (scan_work && wpa_s->own_scan_running) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
+ return wpa_drv_abort_scan(wpa_s);
+ }
+
+ return 0;
+}
+
+
+int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct sched_scan_plan *scan_plans = NULL;
+ const char *token, *context = NULL;
+ unsigned int num = 0;
+
+ if (!cmd)
+ return -1;
+
+ if (!cmd[0]) {
+ wpa_printf(MSG_DEBUG, "Clear sched scan plans");
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = NULL;
+ wpa_s->sched_scan_plans_num = 0;
+ return 0;
+ }
+
+ while ((token = cstr_token(cmd, " ", &context))) {
+ int ret;
+ struct sched_scan_plan *scan_plan, *n;
+
+ n = os_realloc_array(scan_plans, num + 1, sizeof(*scan_plans));
+ if (!n)
+ goto fail;
+
+ scan_plans = n;
+ scan_plan = &scan_plans[num];
+ num++;
+
+ ret = sscanf(token, "%u:%u", &scan_plan->interval,
+ &scan_plan->iterations);
+ if (ret <= 0 || ret > 2 || !scan_plan->interval) {
+ wpa_printf(MSG_ERROR,
+ "Invalid sched scan plan input: %s", token);
+ goto fail;
+ }
+
+ if (scan_plan->interval > wpa_s->max_sched_scan_plan_interval) {
+ wpa_printf(MSG_WARNING,
+ "scan plan %u: Scan interval too long(%u), use the maximum allowed(%u)",
+ num, scan_plan->interval,
+ wpa_s->max_sched_scan_plan_interval);
+ scan_plan->interval =
+ wpa_s->max_sched_scan_plan_interval;
+ }
+
+ if (ret == 1) {
+ scan_plan->iterations = 0;
+ break;
+ }
+
+ if (!scan_plan->iterations) {
+ wpa_printf(MSG_ERROR,
+ "scan plan %u: Number of iterations cannot be zero",
+ num);
+ goto fail;
+ }
+
+ if (scan_plan->iterations >
+ wpa_s->max_sched_scan_plan_iterations) {
+ wpa_printf(MSG_WARNING,
+ "scan plan %u: Too many iterations(%u), use the maximum allowed(%u)",
+ num, scan_plan->iterations,
+ wpa_s->max_sched_scan_plan_iterations);
+ scan_plan->iterations =
+ wpa_s->max_sched_scan_plan_iterations;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "scan plan %u: interval=%u iterations=%u",
+ num, scan_plan->interval, scan_plan->iterations);
+ }
+
+ if (!scan_plans) {
+ wpa_printf(MSG_ERROR, "Invalid scan plans entry");
+ goto fail;
+ }
+
+ if (cstr_token(cmd, " ", &context) || scan_plans[num - 1].iterations) {
+ wpa_printf(MSG_ERROR,
+ "All scan plans but the last must specify a number of iterations");
+ goto fail;
+ }
+
+ wpa_printf(MSG_DEBUG, "scan plan %u (last plan): interval=%u",
+ num, scan_plans[num - 1].interval);
+
+ if (num > wpa_s->max_sched_scan_plans) {
+ wpa_printf(MSG_WARNING,
+ "Too many scheduled scan plans (only %u supported)",
+ wpa_s->max_sched_scan_plans);
+ wpa_printf(MSG_WARNING,
+ "Use only the first %u scan plans, and the last one (in infinite loop)",
+ wpa_s->max_sched_scan_plans - 1);
+ os_memcpy(&scan_plans[wpa_s->max_sched_scan_plans - 1],
+ &scan_plans[num - 1], sizeof(*scan_plans));
+ num = wpa_s->max_sched_scan_plans;
+ }
+
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = scan_plans;
+ wpa_s->sched_scan_plans_num = num;
+
+ return 0;
+
+fail:
+ os_free(scan_plans);
+ wpa_printf(MSG_ERROR, "invalid scan plans list");
+ return -1;
+}