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