1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * WPA Supplicant - auto scan 3e5b75505Sopenharmony_ci * Copyright (c) 2012, Intel Corporation. All rights reserved. 4e5b75505Sopenharmony_ci * Copyright 2015 Intel Deutschland GmbH 5e5b75505Sopenharmony_ci * 6e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 7e5b75505Sopenharmony_ci * See README for more details. 8e5b75505Sopenharmony_ci */ 9e5b75505Sopenharmony_ci 10e5b75505Sopenharmony_ci#include "includes.h" 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "common.h" 13e5b75505Sopenharmony_ci#include "config.h" 14e5b75505Sopenharmony_ci#include "wpa_supplicant_i.h" 15e5b75505Sopenharmony_ci#include "bss.h" 16e5b75505Sopenharmony_ci#include "scan.h" 17e5b75505Sopenharmony_ci#include "autoscan.h" 18e5b75505Sopenharmony_ci 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_cistatic const struct autoscan_ops * autoscan_modules[] = { 21e5b75505Sopenharmony_ci#ifdef CONFIG_AUTOSCAN_EXPONENTIAL 22e5b75505Sopenharmony_ci &autoscan_exponential_ops, 23e5b75505Sopenharmony_ci#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */ 24e5b75505Sopenharmony_ci#ifdef CONFIG_AUTOSCAN_PERIODIC 25e5b75505Sopenharmony_ci &autoscan_periodic_ops, 26e5b75505Sopenharmony_ci#endif /* CONFIG_AUTOSCAN_PERIODIC */ 27e5b75505Sopenharmony_ci NULL 28e5b75505Sopenharmony_ci}; 29e5b75505Sopenharmony_ci 30e5b75505Sopenharmony_ci 31e5b75505Sopenharmony_cistatic void request_scan(struct wpa_supplicant *wpa_s) 32e5b75505Sopenharmony_ci{ 33e5b75505Sopenharmony_ci wpa_s->scan_req = MANUAL_SCAN_REQ; 34e5b75505Sopenharmony_ci 35e5b75505Sopenharmony_ci if (wpa_supplicant_req_sched_scan(wpa_s)) 36e5b75505Sopenharmony_ci wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 0); 37e5b75505Sopenharmony_ci} 38e5b75505Sopenharmony_ci 39e5b75505Sopenharmony_ci 40e5b75505Sopenharmony_ciint autoscan_init(struct wpa_supplicant *wpa_s, int req_scan) 41e5b75505Sopenharmony_ci{ 42e5b75505Sopenharmony_ci const char *name = wpa_s->conf->autoscan; 43e5b75505Sopenharmony_ci const char *params; 44e5b75505Sopenharmony_ci size_t nlen; 45e5b75505Sopenharmony_ci int i; 46e5b75505Sopenharmony_ci const struct autoscan_ops *ops = NULL; 47e5b75505Sopenharmony_ci struct sched_scan_plan *scan_plans; 48e5b75505Sopenharmony_ci 49e5b75505Sopenharmony_ci /* Give preference to scheduled scan plans if supported/configured */ 50e5b75505Sopenharmony_ci if (wpa_s->sched_scan_plans) { 51e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 52e5b75505Sopenharmony_ci "autoscan: sched_scan_plans set - use it instead"); 53e5b75505Sopenharmony_ci return 0; 54e5b75505Sopenharmony_ci } 55e5b75505Sopenharmony_ci 56e5b75505Sopenharmony_ci if (wpa_s->autoscan && wpa_s->autoscan_priv) { 57e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "autoscan: Already initialized"); 58e5b75505Sopenharmony_ci return 0; 59e5b75505Sopenharmony_ci } 60e5b75505Sopenharmony_ci 61e5b75505Sopenharmony_ci if (name == NULL) 62e5b75505Sopenharmony_ci return 0; 63e5b75505Sopenharmony_ci 64e5b75505Sopenharmony_ci params = os_strchr(name, ':'); 65e5b75505Sopenharmony_ci if (params == NULL) { 66e5b75505Sopenharmony_ci params = ""; 67e5b75505Sopenharmony_ci nlen = os_strlen(name); 68e5b75505Sopenharmony_ci } else { 69e5b75505Sopenharmony_ci nlen = params - name; 70e5b75505Sopenharmony_ci params++; 71e5b75505Sopenharmony_ci } 72e5b75505Sopenharmony_ci 73e5b75505Sopenharmony_ci for (i = 0; autoscan_modules[i]; i++) { 74e5b75505Sopenharmony_ci if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) { 75e5b75505Sopenharmony_ci ops = autoscan_modules[i]; 76e5b75505Sopenharmony_ci break; 77e5b75505Sopenharmony_ci } 78e5b75505Sopenharmony_ci } 79e5b75505Sopenharmony_ci 80e5b75505Sopenharmony_ci if (ops == NULL) { 81e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "autoscan: Could not find module " 82e5b75505Sopenharmony_ci "matching the parameter '%s'", name); 83e5b75505Sopenharmony_ci return -1; 84e5b75505Sopenharmony_ci } 85e5b75505Sopenharmony_ci 86e5b75505Sopenharmony_ci scan_plans = os_malloc(sizeof(*wpa_s->sched_scan_plans)); 87e5b75505Sopenharmony_ci if (!scan_plans) 88e5b75505Sopenharmony_ci return -1; 89e5b75505Sopenharmony_ci 90e5b75505Sopenharmony_ci wpa_s->autoscan_params = NULL; 91e5b75505Sopenharmony_ci 92e5b75505Sopenharmony_ci wpa_s->autoscan_priv = ops->init(wpa_s, params); 93e5b75505Sopenharmony_ci if (!wpa_s->autoscan_priv) { 94e5b75505Sopenharmony_ci os_free(scan_plans); 95e5b75505Sopenharmony_ci return -1; 96e5b75505Sopenharmony_ci } 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_ci scan_plans[0].interval = 5; 99e5b75505Sopenharmony_ci scan_plans[0].iterations = 0; 100e5b75505Sopenharmony_ci os_free(wpa_s->sched_scan_plans); 101e5b75505Sopenharmony_ci wpa_s->sched_scan_plans = scan_plans; 102e5b75505Sopenharmony_ci wpa_s->sched_scan_plans_num = 1; 103e5b75505Sopenharmony_ci wpa_s->autoscan = ops; 104e5b75505Sopenharmony_ci 105e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with " 106e5b75505Sopenharmony_ci "parameters '%s'", ops->name, params); 107e5b75505Sopenharmony_ci if (!req_scan) 108e5b75505Sopenharmony_ci return 0; 109e5b75505Sopenharmony_ci 110e5b75505Sopenharmony_ci /* 111e5b75505Sopenharmony_ci * Cancelling existing scan requests, if any. 112e5b75505Sopenharmony_ci */ 113e5b75505Sopenharmony_ci wpa_supplicant_cancel_sched_scan(wpa_s); 114e5b75505Sopenharmony_ci wpa_supplicant_cancel_scan(wpa_s); 115e5b75505Sopenharmony_ci 116e5b75505Sopenharmony_ci /* 117e5b75505Sopenharmony_ci * Firing first scan, which will lead to call autoscan_notify_scan. 118e5b75505Sopenharmony_ci */ 119e5b75505Sopenharmony_ci request_scan(wpa_s); 120e5b75505Sopenharmony_ci 121e5b75505Sopenharmony_ci return 0; 122e5b75505Sopenharmony_ci} 123e5b75505Sopenharmony_ci 124e5b75505Sopenharmony_ci 125e5b75505Sopenharmony_civoid autoscan_deinit(struct wpa_supplicant *wpa_s) 126e5b75505Sopenharmony_ci{ 127e5b75505Sopenharmony_ci if (wpa_s->autoscan && wpa_s->autoscan_priv) { 128e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "autoscan: Deinitializing module '%s'", 129e5b75505Sopenharmony_ci wpa_s->autoscan->name); 130e5b75505Sopenharmony_ci wpa_s->autoscan->deinit(wpa_s->autoscan_priv); 131e5b75505Sopenharmony_ci wpa_s->autoscan = NULL; 132e5b75505Sopenharmony_ci wpa_s->autoscan_priv = NULL; 133e5b75505Sopenharmony_ci 134e5b75505Sopenharmony_ci wpa_s->scan_interval = 5; 135e5b75505Sopenharmony_ci 136e5b75505Sopenharmony_ci os_free(wpa_s->sched_scan_plans); 137e5b75505Sopenharmony_ci wpa_s->sched_scan_plans = NULL; 138e5b75505Sopenharmony_ci wpa_s->sched_scan_plans_num = 0; 139e5b75505Sopenharmony_ci } 140e5b75505Sopenharmony_ci} 141e5b75505Sopenharmony_ci 142e5b75505Sopenharmony_ci 143e5b75505Sopenharmony_ciint autoscan_notify_scan(struct wpa_supplicant *wpa_s, 144e5b75505Sopenharmony_ci struct wpa_scan_results *scan_res) 145e5b75505Sopenharmony_ci{ 146e5b75505Sopenharmony_ci int interval; 147e5b75505Sopenharmony_ci 148e5b75505Sopenharmony_ci if (wpa_s->autoscan && wpa_s->autoscan_priv) { 149e5b75505Sopenharmony_ci interval = wpa_s->autoscan->notify_scan(wpa_s->autoscan_priv, 150e5b75505Sopenharmony_ci scan_res); 151e5b75505Sopenharmony_ci 152e5b75505Sopenharmony_ci if (interval <= 0) 153e5b75505Sopenharmony_ci return -1; 154e5b75505Sopenharmony_ci 155e5b75505Sopenharmony_ci wpa_s->scan_interval = interval; 156e5b75505Sopenharmony_ci wpa_s->sched_scan_plans[0].interval = interval; 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci request_scan(wpa_s); 159e5b75505Sopenharmony_ci } 160e5b75505Sopenharmony_ci 161e5b75505Sopenharmony_ci return 0; 162e5b75505Sopenharmony_ci} 163