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