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