Home | History | Annotate | Line # | Download | only in wpa_supplicant
      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