1252190Srpaulo/* 2252190Srpaulo * WPA Supplicant - auto scan 3252190Srpaulo * Copyright (c) 2012, Intel Corporation. All rights reserved. 4252190Srpaulo * 5252190Srpaulo * This software may be distributed under the terms of the BSD license. 6252190Srpaulo * See README for more details. 7252190Srpaulo */ 8252190Srpaulo 9252190Srpaulo#include "includes.h" 10252190Srpaulo 11252190Srpaulo#include "common.h" 12252190Srpaulo#include "config.h" 13252190Srpaulo#include "wpa_supplicant_i.h" 14252190Srpaulo#include "bss.h" 15252190Srpaulo#include "scan.h" 16252190Srpaulo#include "autoscan.h" 17252190Srpaulo 18252190Srpaulo#ifdef CONFIG_AUTOSCAN_EXPONENTIAL 19252190Srpauloextern const struct autoscan_ops autoscan_exponential_ops; 20252190Srpaulo#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */ 21252190Srpaulo 22252190Srpaulo#ifdef CONFIG_AUTOSCAN_PERIODIC 23252190Srpauloextern const struct autoscan_ops autoscan_periodic_ops; 24252190Srpaulo#endif /* CONFIG_AUTOSCAN_PERIODIC */ 25252190Srpaulo 26252190Srpaulostatic const struct autoscan_ops * autoscan_modules[] = { 27252190Srpaulo#ifdef CONFIG_AUTOSCAN_EXPONENTIAL 28252190Srpaulo &autoscan_exponential_ops, 29252190Srpaulo#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */ 30252190Srpaulo#ifdef CONFIG_AUTOSCAN_PERIODIC 31252190Srpaulo &autoscan_periodic_ops, 32252190Srpaulo#endif /* CONFIG_AUTOSCAN_PERIODIC */ 33252190Srpaulo NULL 34252190Srpaulo}; 35252190Srpaulo 36252190Srpaulo 37252190Srpaulostatic void request_scan(struct wpa_supplicant *wpa_s) 38252190Srpaulo{ 39252190Srpaulo wpa_s->scan_req = MANUAL_SCAN_REQ; 40252190Srpaulo 41252190Srpaulo if (wpa_supplicant_req_sched_scan(wpa_s)) 42252190Srpaulo wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 0); 43252190Srpaulo} 44252190Srpaulo 45252190Srpaulo 46252190Srpauloint autoscan_init(struct wpa_supplicant *wpa_s, int req_scan) 47252190Srpaulo{ 48252190Srpaulo const char *name = wpa_s->conf->autoscan; 49252190Srpaulo const char *params; 50252190Srpaulo size_t nlen; 51252190Srpaulo int i; 52252190Srpaulo const struct autoscan_ops *ops = NULL; 53252190Srpaulo 54252190Srpaulo if (wpa_s->autoscan && wpa_s->autoscan_priv) 55252190Srpaulo return 0; 56252190Srpaulo 57252190Srpaulo if (name == NULL) 58252190Srpaulo return 0; 59252190Srpaulo 60252190Srpaulo params = os_strchr(name, ':'); 61252190Srpaulo if (params == NULL) { 62252190Srpaulo params = ""; 63252190Srpaulo nlen = os_strlen(name); 64252190Srpaulo } else { 65252190Srpaulo nlen = params - name; 66252190Srpaulo params++; 67252190Srpaulo } 68252190Srpaulo 69252190Srpaulo for (i = 0; autoscan_modules[i]; i++) { 70252190Srpaulo if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) { 71252190Srpaulo ops = autoscan_modules[i]; 72252190Srpaulo break; 73252190Srpaulo } 74252190Srpaulo } 75252190Srpaulo 76252190Srpaulo if (ops == NULL) { 77252190Srpaulo wpa_printf(MSG_ERROR, "autoscan: Could not find module " 78252190Srpaulo "matching the parameter '%s'", name); 79252190Srpaulo return -1; 80252190Srpaulo } 81252190Srpaulo 82252190Srpaulo wpa_s->autoscan_params = NULL; 83252190Srpaulo 84252190Srpaulo wpa_s->autoscan_priv = ops->init(wpa_s, params); 85252190Srpaulo if (wpa_s->autoscan_priv == NULL) 86252190Srpaulo return -1; 87252190Srpaulo wpa_s->autoscan = ops; 88252190Srpaulo 89252190Srpaulo wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with " 90252190Srpaulo "parameters '%s'", ops->name, params); 91252190Srpaulo if (!req_scan) 92252190Srpaulo return 0; 93252190Srpaulo 94252190Srpaulo /* 95252190Srpaulo * Cancelling existing scan requests, if any. 96252190Srpaulo */ 97252190Srpaulo wpa_supplicant_cancel_sched_scan(wpa_s); 98252190Srpaulo wpa_supplicant_cancel_scan(wpa_s); 99252190Srpaulo 100252190Srpaulo /* 101252190Srpaulo * Firing first scan, which will lead to call autoscan_notify_scan. 102252190Srpaulo */ 103252190Srpaulo request_scan(wpa_s); 104252190Srpaulo 105252190Srpaulo return 0; 106252190Srpaulo} 107252190Srpaulo 108252190Srpaulo 109252190Srpaulovoid autoscan_deinit(struct wpa_supplicant *wpa_s) 110252190Srpaulo{ 111252190Srpaulo if (wpa_s->autoscan && wpa_s->autoscan_priv) { 112252190Srpaulo wpa_printf(MSG_DEBUG, "autoscan: Deinitializing module '%s'", 113252190Srpaulo wpa_s->autoscan->name); 114252190Srpaulo wpa_s->autoscan->deinit(wpa_s->autoscan_priv); 115252190Srpaulo wpa_s->autoscan = NULL; 116252190Srpaulo wpa_s->autoscan_priv = NULL; 117252190Srpaulo 118252190Srpaulo wpa_s->scan_interval = 5; 119252190Srpaulo wpa_s->sched_scan_interval = 0; 120252190Srpaulo } 121252190Srpaulo} 122252190Srpaulo 123252190Srpaulo 124252190Srpauloint autoscan_notify_scan(struct wpa_supplicant *wpa_s, 125252190Srpaulo struct wpa_scan_results *scan_res) 126252190Srpaulo{ 127252190Srpaulo int interval; 128252190Srpaulo 129252190Srpaulo if (wpa_s->autoscan && wpa_s->autoscan_priv) { 130252190Srpaulo interval = wpa_s->autoscan->notify_scan(wpa_s->autoscan_priv, 131252190Srpaulo scan_res); 132252190Srpaulo 133252190Srpaulo if (interval <= 0) 134252190Srpaulo return -1; 135252190Srpaulo 136252190Srpaulo wpa_s->scan_interval = interval; 137252190Srpaulo wpa_s->sched_scan_interval = interval; 138252190Srpaulo 139252190Srpaulo request_scan(wpa_s); 140252190Srpaulo } 141252190Srpaulo 142252190Srpaulo return 0; 143252190Srpaulo} 144