no_cck_rates is set in the scan parameters generally to make sure
that the Probe Request frames are not sent at any of the 802.11b
rates during active scans. With this patch we also omit those rates
from the Supported Rates IEs, which is required by the p2p spec and
also matches our flag's name.
The intent here was to validate that the frequency is a multiple of 5
and lies in a certain range. Somehow the channel was checked for being
a multiple of 5 instead.
This will be seen in Probe Requests. More IEs can and should
be added here depending on the support in IWD. E.g. HS20 indication,
Interworking, HT/VHT IE's etc.
For (Re)Association the HS20 indication element was passed exactly as
it was found in the scan results. The spec defines what bits can be
set and what cannot when this IE is used in (Re)Association. Instead
of assuming the AP's IE conforms to the spec, we now parse the IE and
re-build it for use with (Re)Association.
Since the full IE is no longer used, it was removed from scan_bss, and
replaced with a bit for HS20 support (hs20_capable). This member is
now used the same as hs20_ie was.
The version parsed during scan results is now used when building the
(Re)Association IE.
The HS20 indication element should always be included during
(Re)Association per the spec. This removes the need for a
dedicated boolean, and now the hs20_ie can be used instead.
If the scan was triggered and later aborted, make sure to reset the
triggered value when the CMD_NEW_SCAN_RESULTS event comes in.
src/station.c:station_enter_state() Old State: disconnected, new state: connecting
src/scan.c:scan_notify() Scan notification 33
src/station.c:station_netdev_event() Associating
src/scan.c:scan_notify() Scan notification 34
Aborting (signal 11) [/home/denkenz/iwd-master/src/iwd]
++++++++ backtrace ++++++++
#0 0x7efd4d6a2ef0 in /lib64/libc.so.6
#1 0x42b20d in scan_notify() at src/scan.c:1383
P2P probe requests are to be sent at min 6.0 Mb/s using OFDM,
specifically the 802.11b rates are prohibited (section 2.4.1 in Wi-Fi
P2p Technical Spec v1.7), some of which use CCK modulation. This is
already the default for 5G but for 2.4G the drivers generally do this
if we set the NL80211_ATTR_TX_NO_CCK_RATE flags with
NL80211_CMD_TRIGGER_SCAN.
The ifindex is used to index the netdevs in the system (wlan, ethernet,
etc.) but we can also do wifi scanning on interfaces that have no
corresponding netdev object, like the P2P-device virtual interfaces.
Use the wdev id's to reference interfaces, the nl80211 api doesn't care
whether we use a NL80211_ATTR_IFINDEX or NL80211_ATTR_WDEV. Only
wireless interfaces have a wdev id.
Save the actual cmd_id returned from l_genl_family_dump and zero it in
the get_scan_done. There's no need to zero it in scan_cancel because
get_scan_done gets called automatically.
Store the scan_context pointer in scan_results directly instead of
storing the ifindex. We now cancel ongoing GET_SCAN commands when the
scan_context is being freed so there's no point going through the extra
step of looking up the scan_context by ifindex inside the command
callback to guard against non-existent scan_contexts.
In order to do ANQP efficiently IWD needs the ability to suspend scanning
temporarily. This is because both scanning and ANQP go offchannel and must
remain off channel for some amount of time. This cannot be done
simultaneously and if e.g. ANQP is requested after a scan is already
pending, the kernel will wait till that scan finishes before sending out
the frame.
This IE tells us what Advertisement Protocols the AP supports. This
is only here to look for ANQP support, so all this does is iterate
through all other Advertisement Protocol tuples looking for ANQP.
If found, anqp_capable is set in the scan_bss
The vendor specific IE was being parsed only to check if the AP supported
WPA, which used a Microsoft OUI. Hotspot/OSEN uses neither WPA or RSN
(although its nearly identical to RSN) so the we also need to check for
this Wifi-Alliance OUI and set bss->osen (new) if found.
When handling a scan finished event for a scan we haven't started check
that we were not halfway through a scan request that would have its
results flushed by the external scan.
Instead of having two separate types of scans make the periodic scan
logic a layer on top of the one-off scan requests, with minimum code to
account for the lower priority of those scans and the fact that periodic
scans also receive results from external scans. Also try to simplify
the code for both the periodic and one-off scans. In the SCAN_RESULTS
and SCAN_ABORT add more complete checks of the current request's state
so we avoid some existing crashes related to external scans.
scan_send_next_cmd and start_next_scan_request are now just one function
since their funcionality was similar and start_next_scan_request is used
everywhere. Also the state after the trigger command receives an EBUSY
is now the same as when a new scan is on top of the queue so we have
fewer situations to consider.
This code still does not account for fragmented scans where an external
scan between two or our fragments flushes the results and we lose some
of the results, or for fragmented scans that take over 30s and the
kernel expires some results (both situations are unlikely.)
Previously, the scan results were disregarded once the new
ones were available. To enable the scan scenarios where the
new scan results are delivered in parts, we introduce a
concept of aging BSSs and will remove them based on
retention time.
CC src/scan.o
src/scan.c: In function ‘scan_bss_compute_rank’:
src/scan.c:1048:4: warning: this decimal constant is unsigned only in ISO C90
factor = factor * data_rate / 2340000000 +
This is not used by any of the scan notify callback implementations and
for P2P we're going to need to scan on an interface without an ifindex
so without this the other changes should be mostly contained in scan.
sc->state would get set when the TRIGGERED event arrived or when the
triggered callback for our own SCAN_TRIGGER command is received.
However it would not get reset to NOT_RUNNING when the NEW_SCAN_RESULTS
event is received, instead we'd first request the results with GET_SCAN
and only reset sc->state when that returns. If during that command a
new scan gets triggered, the GET_SCAN callback would still reset
sc->state and clobber the value set by the new scan.
To fix that repurpose sc->state to only track that period from the
TRIGGERED signal to the NEW_SCAN_RESULTS signal. sc->triggered can be
used to check if we're still waiting for the GET_SCAN command and
sc->start_cmd_id to check if we're waiting for the scan to get
triggered, so one of these three variables will now always indicate if
a scan is in progress.
On successful send, scan_send_start(..) used to set msg to NULL,
therefore the further management of the command by the caller was
impossible. This patch removes wrapper around l_genl_family_send()
and lets the callers to take responsibility for the command.
Some users may need their own control over 2.4/5GHz preference. This
adds a new user option, 'rank_5g_factor', which allows users to increase
or decrease their 5G preference.
This adds support for parsing the VHT IE, which allows a BSS supporting
VHT (80211ac) to be ranked higher than a BSS supporting only HT/basic
rates. Now, with basic/HT/VHT parsing we can calculate the theoretical
maximum data rate for all three and rank the BSS based on that.
This adds HT IE parsing and data rate calculation for HT (80211n)
rates. Now, a BSS supporting HT rates will be ranked higher than
a basic rate BSS, assuming the RSSI is at an acceptable level.
The spec dictates RSSI thresholds for different modulation schemes, which
correlate to different data rates. Until now were were ranking a BSS with
only looking at its advertised data rate, which may not even be possible
if the RSSI does not meet the threshold.
Now, RSSI is taken into consideration and the data rate returned from
parsing (Ext) Supported Rates IE(s) will reflect that.
This should not change the behaviour except for fixing a rare crash
due to scan_cancel not working correctly when cancelling the first scan
request in the queue while a periodic scan was running, and potentially
other corner cases. To be able to better distinguish between a periodic
scan in progress and a scan request in progress add a sc->current_sr
field that points either at a scan request or is NULL when a periodic
scan is in ongoing. Move the triggered flag from scan_request and
scan_preiodic directly to scan_context so it's there together with
start_cmd_id. Hopefully make scan_cancel simpler/clearer.
Note sc->state and sc->triggered have similar semantics so one of them
may be easily removed. Also the wiphy_id parameter to the scan callback
is rather useless, note I temporarily pass 0 as the value on error but
perhaps it should be dropped.
The main difference with this is that scan_context removal will also
trigger the .destroy calls. Normally there won't be any requests left
during scan_context but if there were any we should call destroy on
them.
Fix incorrect usage of the caller’s scan triggered callback.
In case of a failure, destroy scan request and notify caller
about the issue by returning zero scan id instead of calling
callers’ scan triggered callback with an error code.
Until now network.c managed the list of network_info structs including
for known networks and networks that are seen in at least one device's
scan results, with the is_known flag to distinguish known networks.
Each time the list was processed though the code was either interested
in one subset of networks or the other. Split the list into a Known
Networks list and the list of other networks seen in scans. Move all
code related to Known Networks to knownnetworks.c, this simplifies
network.h. It also gets rid of network_info_get_known which actually
returned the list of all network_infos (not just for known networks),
which logically should have been private to network.c. Update device.c
and scan.c to use functions specific to Known Networks instead of
filtering the lists by the is_known flag.
This will also allow knownnetworks.c to export DBus objects and/or
properties for the Known Networks information because it now knows when
Known Networks are added, removed or modified by IWD.
triggered flag was being reset to false in all cases. However, due to
how scan_finished logic works, it should have remained true if no more
commands were left to be sent (e.g. the scan was finished).
In addition, the periodic scan can now alternate between the
active or passive modes. The active mode is enabled by existence of
the known hidden networks and observation of them in the
previous scan result.
To support an auto-connect for the hidden networks and having
a limited number of SSIDs that can be appended into a probe
request, introduced a concept of a command batch. Now, scan request
may consist of a series of commands. The commands in the batch
are triggered sequentially. Once we are notified about the
results from a previous command, a consequent command in the
batch is triggered. The collective results are reported once
the batch is complete. On a command failure, the batch
processing is canceled and scan request is removed
The state of scan is split between the two variables sc->state
and sc->start_cmd_id. Not checking start_cmd_id used to cause
sending a scan request while periodic scan was just triggered
resulting in EBUSY.
Pass an additional parameter to the scan results notify functions to
tell them whether the scan was successful. If it wasn't don't bother
passing an empty bss_list queue, pass NULL as bss_list. This way the
callbacks can tell whether the scan indicates there are no BSSes in
range or simply was aborted and the old scan results should be kept.
Also handle the case of a periodic scan when handling a
NL80211_CMD_SCAN_ABORTED. The goal is to make sure the supplied callback
is always called if .trigger was called before, but this should also fix
some other corner cases.
* I add a sp.triggered field for periodic scans since sc->state doesn't
tell us whether the scan in progress was triggered by ourselved o
someone else (in that case .trigger has not been called)
* Since the NL80211_CMD_SCAN_ABORTED becomes similar to get_scan_done I
move the common code to scan_finished
* I believe this fixes a situation where we weren't updating sc->state
if we'd not triggered the scan, because both get_scan_done and the
NL80211_CMD_SCAN_ABORTED would return directly.
If the current request is not freed when we receive the
NL80211_CMD_SCAN_ABORTED event, device.c will keep thinking that
we're still scanning and the scan.c logic also gets confused and may
resend the current request at some point and call sr->trigger again
causing a segfault in device.c.
I pass an empty bss_list to the callback, another possibility would be
to pass NULL to let the callback know not to replace old results yet.
The callbacks would need to handle a NULL first.
Add sr NULL check before accessing sr->id. Call scan_request_free on
request structure and call the destroy callback. Cancel the netlink
TRIGGER_SCAN command if still running and try starting the next scan
in the queue. It'll probably still fail with EBUSY but it'll be
reattempted later.
Always call start_next_scan_request when a scan request has finished,
with a success or a failure, including a periodic scan attempt. Inside
that function check if there's any work to be done, either for one-off
scan requests or periodic scan, instead of having this check only inside
get_scan_done. Call start_next_scan_request in scan_periodic_start and
scan_periodic_timeout.
Also call the trigger callback with an error code when sending the
netlink command fails after the scan request has been queued because
another scan was in progress when the scan was requested.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000419d38 in scan_done (msg=0x692580, userdata=0x688250)
at src/scan.c:250
250 sc->state = sr->passive ? SCAN_STATE_PASSIVE : SCAN_STATE_ACTIVE;
(gdb) bt
0 0x0000000000419d38 in scan_done (msg=0x692580, userdata=0x688250)
at src/scan.c:250
1 0x000000000043cac0 in process_unicast (genl=0x686d60, nlmsg=0x7fffffffc3b0)
at ell/genl.c:390
2 0x000000000043ceb0 in received_data (io=0x686e60, user_data=0x686d60)
at ell/genl.c:506
3 0x000000000043967d in io_callback (fd=6, events=1, user_data=0x686e60)
at ell/io.c:120
4 0x000000000043824d in l_main_run () at ell/main.c:381
5 0x000000000040303c in main (argc=1, argv=0x7fffffffe668) at src/main.c:259
The reasoning is that the logic inside scan_common is reversed. Instead
of freeing the scan request on error, we always do it. This causes the
trigger_scan callback to receive invalid userdata.
Save the ids of the netlink trigger scan commands that we send and
cancel them in scan_ifindex_remove to fix a race leading to a
segfault. The segfault would happen every time if scan_ifindex_remove
was called in the same main loop iteration in which we sent the
command, on shutdown:
^CTerminate
src/netdev.c:netdev_free() Freeing netdev wlan3[6]
src/device.c:device_disassociated() 6
src/device.c:device_enter_state() Old State: connected, new state:
disconnected
src/device.c:device_enter_state() Old State: disconnected, new state:
autoconnect
src/scan.c:scan_periodic_start() Starting periodic scan for ifindex: 6
src/device.c:device_free()
src/device.c:bss_free() Freeing BSS 02:00:00:00:00:00
src/device.c:bss_free() Freeing BSS 02:00:00:00:01:00
Removing scan context for ifindex: 6
src/scan.c:scan_context_free() sc: 0x5555557ca290
src/scan.c:scan_notify() Scan notification 33
src/netdev.c:netdev_operstate_down_cb() netdev: 6, success: 1
src/scan.c:scan_periodic_done()
src/scan.c:scan_periodic_done() Periodic scan triggered for ifindex:
1434209520
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000064 in ?? ()
(gdb) bt
#0 0x0000000000000064 in ?? ()
#1 0x0000555555583560 in process_unicast (nlmsg=0x7fffffffc1a0,
genl=0x5555557c1d60) at ell/genl.c:390
#2 received_data (io=<optimized out>, user_data=0x5555557c1d60)
at ell/genl.c:506
#3 0x0000555555580d45 in io_callback (fd=<optimized out>,
events=1, user_data=0x5555557c1e60) at ell/io.c:120
#4 0x000055555558005f in l_main_run () at ell/main.c:381
#5 0x00005555555599c1 in main (argc=<optimized out>, argv=<optimized out>)
at src/main.c:259
Add a flush flag to scan_parameters to tell the kernel to flush the
cache of scan results before the new scan. Use this flag in the
active scan during roaming.
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.