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