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 return 0; 52 53 if (wpa_s->autoscan && wpa_s->autoscan_priv) 54 return 0; 55 56 if (name == NULL) 57 return 0; 58 59 params = os_strchr(name, ':'); 60 if (params == NULL) { 61 params = ""; 62 nlen = os_strlen(name); 63 } else { 64 nlen = params - name; 65 params++; 66 } 67 68 for (i = 0; autoscan_modules[i]; i++) { 69 if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) { 70 ops = autoscan_modules[i]; 71 break; 72 } 73 } 74 75 if (ops == NULL) { 76 wpa_printf(MSG_ERROR, "autoscan: Could not find module " 77 "matching the parameter '%s'", name); 78 return -1; 79 } 80 81 scan_plans = os_malloc(sizeof(*wpa_s->sched_scan_plans)); 82 if (!scan_plans) 83 return -1; 84 85 wpa_s->autoscan_params = NULL; 86 87 wpa_s->autoscan_priv = ops->init(wpa_s, params); 88 if (!wpa_s->autoscan_priv) { 89 os_free(scan_plans); 90 return -1; 91 } 92 93 scan_plans[0].interval = 5; 94 scan_plans[0].iterations = 0; 95 os_free(wpa_s->sched_scan_plans); 96 wpa_s->sched_scan_plans = scan_plans; 97 wpa_s->sched_scan_plans_num = 1; 98 wpa_s->autoscan = ops; 99 100 wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with " 101 "parameters '%s'", ops->name, params); 102 if (!req_scan) 103 return 0; 104 105 /* 106 * Cancelling existing scan requests, if any. 107 */ 108 wpa_supplicant_cancel_sched_scan(wpa_s); 109 wpa_supplicant_cancel_scan(wpa_s); 110 111 /* 112 * Firing first scan, which will lead to call autoscan_notify_scan. 113 */ 114 request_scan(wpa_s); 115 116 return 0; 117 } 118 119 120 void autoscan_deinit(struct wpa_supplicant *wpa_s) 121 { 122 if (wpa_s->autoscan && wpa_s->autoscan_priv) { 123 wpa_printf(MSG_DEBUG, "autoscan: Deinitializing module '%s'", 124 wpa_s->autoscan->name); 125 wpa_s->autoscan->deinit(wpa_s->autoscan_priv); 126 wpa_s->autoscan = NULL; 127 wpa_s->autoscan_priv = NULL; 128 129 wpa_s->scan_interval = 5; 130 131 os_free(wpa_s->sched_scan_plans); 132 wpa_s->sched_scan_plans = NULL; 133 wpa_s->sched_scan_plans_num = 0; 134 } 135 } 136 137 138 int autoscan_notify_scan(struct wpa_supplicant *wpa_s, 139 struct wpa_scan_results *scan_res) 140 { 141 int interval; 142 143 if (wpa_s->autoscan && wpa_s->autoscan_priv) { 144 interval = wpa_s->autoscan->notify_scan(wpa_s->autoscan_priv, 145 scan_res); 146 147 if (interval <= 0) 148 return -1; 149 150 wpa_s->scan_interval = interval; 151 wpa_s->sched_scan_plans[0].interval = interval; 152 153 request_scan(wpa_s); 154 } 155 156 return 0; 157 } 158