scan: Add scan_active_full

Add a version of scan_active that accepts a struct with the scan
parameters so we can more easily add new parameters.  Since the genl
message is now built within scan_active_start the extra_ie memory
can be freed by the caller at any time.
This commit is contained in:
Andrew Zaborowski 2016-12-23 05:37:58 -05:00 committed by Denis Kenzior
parent ada054cc30
commit ed1538d5bb
2 changed files with 91 additions and 72 deletions

View File

@ -66,8 +66,7 @@ struct scan_request {
scan_destroy_func_t destroy; scan_destroy_func_t destroy;
bool passive:1; /* Active or Passive scan? */ bool passive:1; /* Active or Passive scan? */
bool triggered:1; bool triggered:1;
uint8_t *extra_ie; struct l_genl_msg *start_cmd;
size_t extra_ie_size;
}; };
struct scan_context { struct scan_context {
@ -106,6 +105,7 @@ static void scan_request_free(void *data)
{ {
struct scan_request *sr = data; struct scan_request *sr = data;
l_genl_msg_unref(sr->start_cmd);
free(sr); free(sr);
} }
@ -166,45 +166,17 @@ bool scan_ifindex_remove(uint32_t ifindex)
return true; return true;
} }
static bool __scan_passive_start(struct l_genl_family *nl80211, static bool scan_send_start(struct l_genl_msg **msg,
uint32_t ifindex, scan_func_t callback, void *user_data)
scan_func_t callback, void *user_data)
{ {
struct l_genl_msg *msg; if (!l_genl_family_send(nl80211, *msg, callback,
user_data, NULL)) {
l_error("Sending NL80211_CMD_TRIGGER_SCAN failed");
msg = l_genl_msg_new_sized(NL80211_CMD_TRIGGER_SCAN, 16);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &ifindex);
if (!l_genl_family_send(nl80211, msg, callback, user_data, NULL)) {
l_error("Starting passive scan failed");
return false; return false;
} }
return true; *msg = NULL;
}
static bool __scan_active_start(struct l_genl_family *nl80211,
uint32_t ifindex,
uint8_t *extra_ie, size_t extra_ie_size,
scan_func_t callback, void *user_data)
{
struct l_genl_msg *msg;
msg = l_genl_msg_new_sized(NL80211_CMD_TRIGGER_SCAN,
32 + extra_ie_size);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &ifindex);
l_genl_msg_enter_nested(msg, NL80211_ATTR_SCAN_SSIDS);
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, 0, NULL);
l_genl_msg_leave_nested(msg);
if (extra_ie && extra_ie_size)
l_genl_msg_append_attr(msg, NL80211_ATTR_IE, extra_ie_size,
extra_ie);
if (!l_genl_family_send(nl80211, msg, callback, user_data, NULL)) {
l_error("Starting active scan failed");
return false;
}
return true; return true;
} }
@ -214,7 +186,6 @@ static void start_next_scan_request(void *userdata)
uint32_t ifindex = L_PTR_TO_UINT(userdata); uint32_t ifindex = L_PTR_TO_UINT(userdata);
struct scan_context *sc; struct scan_context *sc;
struct scan_request *sr; struct scan_request *sr;
bool r;
sc = l_queue_find(scan_contexts, scan_context_match, sc = l_queue_find(scan_contexts, scan_context_match,
L_UINT_TO_PTR(ifindex)); L_UINT_TO_PTR(ifindex));
@ -224,16 +195,7 @@ static void start_next_scan_request(void *userdata)
sr = l_queue_peek_head(sc->requests); sr = l_queue_peek_head(sc->requests);
if (sr->passive) if (!scan_send_start(&sr->start_cmd, scan_done, sc)) {
r = __scan_passive_start(nl80211, ifindex, scan_done, sc);
else
r = __scan_active_start(nl80211, ifindex,
sr->extra_ie, sr->extra_ie_size,
scan_done, sc);
if (!r) {
l_error("Could not send CMD_TRIGGER_SCAN");
if (sr->destroy) if (sr->destroy)
sr->destroy(sr->userdata); sr->destroy(sr->userdata);
@ -287,15 +249,37 @@ static void scan_done(struct l_genl_msg *msg, void *userdata)
sr->trigger(0, sr->userdata); sr->trigger(0, sr->userdata);
} }
static struct l_genl_msg *scan_build_cmd(uint32_t ifindex, bool passive,
const struct scan_parameters *params)
{
struct l_genl_msg *msg;
msg = l_genl_msg_new_sized(NL80211_CMD_TRIGGER_SCAN,
32 + params->extra_ie_size);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &ifindex);
if (!passive) {
l_genl_msg_enter_nested(msg, NL80211_ATTR_SCAN_SSIDS);
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, 0, NULL);
l_genl_msg_leave_nested(msg);
}
if (params->extra_ie && params->extra_ie_size)
l_genl_msg_append_attr(msg, NL80211_ATTR_IE,
params->extra_ie_size,
params->extra_ie);
return msg;
}
static uint32_t scan_common(uint32_t ifindex, bool passive, static uint32_t scan_common(uint32_t ifindex, bool passive,
uint8_t *extra_ie, size_t extra_ie_size, const struct scan_parameters *params,
scan_trigger_func_t trigger, scan_trigger_func_t trigger,
scan_notify_func_t notify, void *userdata, scan_notify_func_t notify, void *userdata,
scan_destroy_func_t destroy) scan_destroy_func_t destroy)
{ {
struct scan_context *sc; struct scan_context *sc;
struct scan_request *sr; struct scan_request *sr;
bool r;
sc = l_queue_find(scan_contexts, scan_context_match, sc = l_queue_find(scan_contexts, scan_context_match,
L_UINT_TO_PTR(ifindex)); L_UINT_TO_PTR(ifindex));
@ -309,28 +293,25 @@ static uint32_t scan_common(uint32_t ifindex, bool passive,
sr->userdata = userdata; sr->userdata = userdata;
sr->destroy = destroy; sr->destroy = destroy;
sr->passive = passive; sr->passive = passive;
sr->extra_ie = extra_ie;
sr->extra_ie_size = extra_ie_size;
sr->id = ++next_scan_request_id; sr->id = ++next_scan_request_id;
sr->start_cmd = scan_build_cmd(ifindex, passive, params);
if (!sr->start_cmd)
goto error;
if (l_queue_length(sc->requests) > 0) if (l_queue_length(sc->requests) > 0)
goto done; goto done;
if (sc->state != SCAN_STATE_NOT_RUNNING) if (sc->state != SCAN_STATE_NOT_RUNNING)
goto done; goto done;
if (passive) if (scan_send_start(&sr->start_cmd, scan_done, sc))
r = __scan_passive_start(nl80211, ifindex, scan_done, sc); goto done;
else
r = __scan_active_start(nl80211, ifindex,
extra_ie, extra_ie_size,
scan_done, sc);
if (!r) { error:
scan_request_free(sr); scan_request_free(sr);
return 0;
}
return 0;
done: done:
l_queue_push_tail(sc->requests, sr); l_queue_push_tail(sc->requests, sr);
@ -341,20 +322,32 @@ uint32_t scan_passive(uint32_t ifindex, scan_trigger_func_t trigger,
scan_notify_func_t notify, void *userdata, scan_notify_func_t notify, void *userdata,
scan_destroy_func_t destroy) scan_destroy_func_t destroy)
{ {
return scan_common(ifindex, true, NULL, 0, trigger, notify, struct scan_parameters params = {};
return scan_common(ifindex, true, &params, trigger, notify,
userdata, destroy); userdata, destroy);
} }
/*
* @extra_ie data is passed by reference. So it must be valid at least until
* the @trigger callback is called.
*/
uint32_t scan_active(uint32_t ifindex, uint8_t *extra_ie, size_t extra_ie_size, uint32_t scan_active(uint32_t ifindex, uint8_t *extra_ie, size_t extra_ie_size,
scan_trigger_func_t trigger, scan_trigger_func_t trigger,
scan_notify_func_t notify, void *userdata, scan_notify_func_t notify, void *userdata,
scan_destroy_func_t destroy) scan_destroy_func_t destroy)
{ {
return scan_common(ifindex, false, extra_ie, extra_ie_size, struct scan_parameters params = {};
params.extra_ie = extra_ie;
params.extra_ie_size = extra_ie_size;
return scan_common(ifindex, false, &params,
trigger, notify, userdata, destroy);
}
uint32_t scan_active_full(uint32_t ifindex,
const struct scan_parameters *params,
scan_trigger_func_t trigger, scan_notify_func_t notify,
void *userdata, scan_destroy_func_t destroy)
{
return scan_common(ifindex, false, params,
trigger, notify, userdata, destroy); trigger, notify, userdata, destroy);
} }
@ -436,6 +429,23 @@ static void scan_periodic_done(struct l_genl_msg *msg, void *user_data)
sc->sp.trigger(0, sc->sp.userdata); sc->sp.trigger(0, sc->sp.userdata);
} }
static bool scan_periodic_send_start(struct scan_context *sc)
{
struct scan_parameters params = {};
struct l_genl_msg *msg;
msg = scan_build_cmd(sc->ifindex, true, &params);
if (!msg)
return false;
if (!scan_send_start(&msg, scan_periodic_done, sc)) {
l_genl_msg_unref(msg);
return false;
}
return true;
}
void scan_periodic_start(uint32_t ifindex, scan_trigger_func_t trigger, void scan_periodic_start(uint32_t ifindex, scan_trigger_func_t trigger,
scan_notify_func_t func, void *userdata) scan_notify_func_t func, void *userdata)
{ {
@ -461,7 +471,7 @@ void scan_periodic_start(uint32_t ifindex, scan_trigger_func_t trigger,
sc->sp.retry = false; sc->sp.retry = false;
sc->sp.rearm = false; sc->sp.rearm = false;
__scan_passive_start(nl80211, ifindex, scan_periodic_done, sc); scan_periodic_send_start(sc);
} }
bool scan_periodic_stop(uint32_t ifindex) bool scan_periodic_stop(uint32_t ifindex)
@ -501,7 +511,8 @@ static void scan_periodic_timeout(struct l_timeout *timeout, void *user_data)
l_debug("scan_periodic_timeout: %u", sc->ifindex); l_debug("scan_periodic_timeout: %u", sc->ifindex);
sc->sp.interval *= 2; sc->sp.interval *= 2;
__scan_passive_start(nl80211, sc->ifindex, scan_periodic_done, sc);
scan_periodic_send_start(sc);
} }
static void scan_periodic_rearm(struct scan_context *sc) static void scan_periodic_rearm(struct scan_context *sc)
@ -925,9 +936,8 @@ static void get_scan_done(void *user)
l_idle_oneshot(start_next_scan_request, l_idle_oneshot(start_next_scan_request,
L_UINT_TO_PTR(sc->ifindex), NULL); L_UINT_TO_PTR(sc->ifindex), NULL);
} else if (sc->sp.retry) { } else if (sc->sp.retry) {
__scan_passive_start(nl80211, sc->ifindex, if (scan_periodic_send_start(sc))
scan_periodic_done, sc); sc->sp.retry = false;
sc->sp.retry = false;
} else if (sc->sp.rearm) { } else if (sc->sp.rearm) {
scan_periodic_rearm(sc); scan_periodic_rearm(sc);
} }

View File

@ -64,6 +64,11 @@ struct scan_bss {
bool cap_rm_neighbor_report : 1; bool cap_rm_neighbor_report : 1;
}; };
struct scan_parameters {
const uint8_t *extra_ie;
size_t extra_ie_size;
};
uint32_t scan_passive(uint32_t ifindex, scan_trigger_func_t trigger, uint32_t scan_passive(uint32_t ifindex, scan_trigger_func_t trigger,
scan_notify_func_t notify, void *userdata, scan_notify_func_t notify, void *userdata,
scan_destroy_func_t destroy); scan_destroy_func_t destroy);
@ -71,6 +76,10 @@ uint32_t scan_active(uint32_t ifindex, uint8_t *extra_ie, size_t extra_ie_size,
scan_trigger_func_t trigger, scan_trigger_func_t trigger,
scan_notify_func_t notify, void *userdata, scan_notify_func_t notify, void *userdata,
scan_destroy_func_t destroy); scan_destroy_func_t destroy);
uint32_t scan_active_full(uint32_t ifindex,
const struct scan_parameters *params,
scan_trigger_func_t trigger, scan_notify_func_t notify,
void *userdata, scan_destroy_func_t destroy);
bool scan_cancel(uint32_t ifindex, uint32_t id); bool scan_cancel(uint32_t ifindex, uint32_t id);
void scan_periodic_start(uint32_t ifindex, scan_trigger_func_t trigger, void scan_periodic_start(uint32_t ifindex, scan_trigger_func_t trigger,