Instead of calling the device added or removed callback when the
interface is detected, call it when interface goes up or down. This
only affects the addition and removal of the WSC interface now.
During the network_info refactoring the adding of the connected BSS to
device->bss_list in case it is not in the scan results has moved to
after the l_hashmap_foreach_remove call meaning that the network could
be removed even though it is still pointed at by
device->connected networks. Reverse the order to what it was before.
Alternatively network_process network could take not of the fact the
network is connected and not call network_remove on it leaving it with
an empty bss_list.
It is probably rare that a disconnect should fail but if it happens the
device->state is not returned to CONNECTED and I'm not sure if it should
be, so the ConnectedNetwork property and other bits should probably be
reset at the start of the disconnection instead of at the end.
Also check if state is CONNECTED before calling network_disconnected
because network_connected may have not been called yet.
--interfaces (-i) tells iwd which interfaces to manage. If the option
is ommitted, all interfaces will be managed.
--nointerfaces (-I) tells iwd which interfaces to blacklist. If the
option is ommitted, no interfaces will be blacklisted.
When setting operstate to dormant or down, give it a callback for debug
purposes. It looks like that operstate down message does not have a
chance to go out currently.
knownnetworks.c/.h implements the KnownNetworks interface and loads the
known networks from storage on startup. The list of all the networks
including information on whether a network is known is managed in
network.c to avoid having two separate lists of network_info structures
and keeping them in sync. That turns out to be difficult because the
network.c list is sorted by connected_time and connected_time changes
can be triggered in both network.c or knownnetworks.c. Both can also
trigger a network_info to be removed completely.
network_info gets a is_known flag that is used for the
GetOrderedNetworks tracking and to implement the KnownNetworks
interface - loading of the list of known networks on startup and
forgetting networks.
For simplicity and future use (possibly performance), every struct network
gets a pointer to a network_info structure, there's one network_info for
every network being by any interface, not only known networks. The SSID
and security type information is removed from struct network because the
network_info holds that information.
network_info also gets a seen_count field to count how many references
from network.info fields it has, so as to fix the removal of
network_info structures. Previously, once they were added to the
networks list, they'd stay there forever possibly skewing the network
ranking results.
This also fixed the network ranking used by GetOrderedNetwork which
wasn't working due to a missing assignment of *index in
network_find_info also triggering valgrind alerts.
The eapol state machine parameters are now built inside device.c when
the network connection is attempted. The reason is that the device
object knows about network settings, wiphy constraints and should
contain the main 'management' logic.
netdev now manages the actual low-level process of building association
messages, detecting authentication events, etc.
Keep an updated sorted list of networks in addition to the "networks"
hashmap. The list can be queried through the GetOrderedNetworks dbus
method.
We also take advantage of that list to get rid of a single
l_hashmap_foreach in new_scan_results.
A function that calculates a new rank type to order all networks
currently seen by a netdev. The order is designed for displaying the
list to user so that the networks most likely to be wanted by the user
are first on the list.
Since the rankmod value only makes sense for autoconnectable networks,
change network_rankmod to return an indication of whether the rankmod is
valid as a boolean instead of as a double, as discussed before.
Do nothing in device_disassociated if device->connected_network
indicates we are not associated. This may happen if the device was
connected since before iwd was started, this should possibly be fixed
separately by querying device state when device is detected.
Make sure networks of all 4 security types have a settings file created
or updated with a new modification time on a successful connect so that
autoconnect and network sorting works for networks other than PSK too.
By doing this on storage_network_touch failure we make sure we don't
overwrite anything dropped into the settings directory while we were
connecting.
for network_seen and network_connected
Only accept a struct network pointer instead of separately the ssid and
security type. This is needed so we can do some more simplification in
the next patch by having access to the network struct.
It looks like with multiple netdev seeing the same networks we'd create
multiple network_info structures for each network. Since the
"networks" list (of network_info structs) is global that's probbaly not
the intention here.
Turn netdev watches into device watches. The intent is to refactor out
netdev specific details into its own class and move device specific
logic into device.c away from wiphy.c
Sometimes the periodic scan is started and stopped before the timeout
was created. If periodic_scan_stop was called before, the timeout
object was not reset to NULL, which can lead to a crash.
The lost beacon event can be received when iwd thinks netdev is
diconnected if it was connected before iwd started, and then
netdev_disassociated will segfault.
It seems until now dbus.c would always connect to dbus-1 (unless
DBUS_SESSION_BUS_ADDRESS pointed at kdbus) and passing -K only made
iwd create a kdbus bus and not use it. Now use ell to actually use
kdbus instead of dbus-1 with -K. Don't use the src/kdbus.c functions
that duplicate ell functionality. As a side effect the connection
description and the bloom sizes are now the ell defaults.
Instead of passing the user_data parameter in every __eapol_rx_packet
call to be used by EAPOL in all tx_packet calls, add
eapol_sm_set_tx_user_data function that sets the value of user_data for
all subsequent tx_packet calls. This way tx_packet can be called from
places that are not necessarily inside an __eapol_rx_packet call.
Only EAP as the inner authentication option is supported. According to
wikipedia this is the most popular EAP-TTLS use case, with MD5 as the
inner EAP's method.
Add the EAP-TLS authentication method. Currently, all the credentials
data is read from the provisioning file even though things like the
private key passphrase should possibly be obtained from the dbus agent.
Probe Response messages can contain additional attributes tucked away
into the WFA-Vendor specific attribute. Parse these attributes while
making sure the order is as expected.
==2469== 24 bytes in 1 blocks are still reachable in loss record 1 of 1
==2469== at 0x4C2B970: malloc (vg_replace_malloc.c:296)
==2469== by 0x40E6DD: l_malloc (util.c:62)
==2469== by 0x40F1CD: l_queue_new (queue.c:63)
==2469== by 0x40D534: scan_init (scan.c:796)
==2469== by 0x403AC3: nl80211_appeared (wiphy.c:2121)
==2469== by 0x415FF3: get_family_callback (genl.c:987)
==2469== by 0x415A4F: process_request (genl.c:381)
==2469== by 0x415A4F: received_data (genl.c:492)
==2469== by 0x413184: io_callback (io.c:120)
==2469== by 0x4127C2: l_main_run (main.c:346)
==2469== by 0x40253E: main (main.c:171)
Refactoring the entire scan code, and this part seems to not be
supported by the target kernels. Revisit / redo this functionality once
things become a bit clearer.
In the D-bus .Connect call return an error immediately if we
find that there's no common cipher supported between iwd, the
network adapter and the AP. This is to avoid asking the agent
for the passkey if we know the connection will fail.
An alternative would be to only show networks that we can connect
to in the scan results on D-bus but I suspect that would cause
more pain to users debugging their wifi setups on average.
For now, if a passphrase is needed we check once before querying
for passphrase and recheck afterwards when we're about to
associate.
Instead of passing in the RSN/WPA elements, simply pass in the
configured cipher. This will make the implementation of the install_gtk
callback much simpler.
Step 4 is always sent without encrypted Key Data according to Section
11.6.6.5. In the case of WPA, Encrypted Key Data field is reserved, and
should always be 0. Thus it is safe to drop the !is_wpa condition.
When handling repeated 4-Way Handshakes from the AP there will be no
.Connect() call pending so we need to check that netdev->connect_pending
is non-NULL. It may be a good idea to check this even during initial
handshake.
When disconnect is triggered locally, we do not clean up properly.
==4336== at 0x4C2B970: malloc (vg_replace_malloc.c:296)
==4336== by 0x40CEED: l_malloc (util.c:62)
==4336== by 0x40F46A: l_settings_new (settings.c:82)
==4336== by 0x40CE2E: storage_network_open (storage.c:180)
==4336== by 0x40498E: network_connect_psk (wiphy.c:307)
==4336== by 0x40498E: network_connect (wiphy.c:359)
==4336== by 0x41D7EE: _dbus_object_tree_dispatch (dbus-service.c:845)
==4336== by 0x416A16: message_read_handler (dbus.c:297)
==4336== by 0x411984: io_callback (io.c:120)
==4336== by 0x410FC2: l_main_run (main.c:346)
==4336== by 0x40253E: main (main.c:171)
This happens when connecting / disconnecting successfully multiple
times.
==4336== 64 bytes in 2 blocks are definitely lost in loss record 9 of 11
==4336== at 0x4C2B970: malloc (vg_replace_malloc.c:296)
==4336== by 0x40CEED: l_malloc (util.c:62)
==4336== by 0x40D6D9: l_util_from_hexstring (util.c:493)
==4336== by 0x4049C6: network_connect_psk (wiphy.c:315)
==4336== by 0x4049C6: network_connect (wiphy.c:359)
==4336== by 0x41D7EE: _dbus_object_tree_dispatch (dbus-service.c:845)
==4336== by 0x416A16: message_read_handler (dbus.c:297)
==4336== by 0x411984: io_callback (io.c:120)
==4336== by 0x410FC2: l_main_run (main.c:346)
==4336== by 0x40253E: main (main.c:171)
Instead of storing the network pointer for each BSS, store it on the
netdev object. This saves space inside struct bss and makes longer term
refactoring simpler.
==4249== 231 (32 direct, 199 indirect) bytes in 1 blocks are definitely
lost in loss record 10 of 10
==4249== at 0x4C2B970: malloc (vg_replace_malloc.c:296)
==4249== by 0x40CF5D: l_malloc (util.c:62)
==4249== by 0x40F4DA: l_settings_new (settings.c:82)
==4249== by 0x40CE9E: storage_network_open (storage.c:180)
==4249== by 0x40499E: network_connect_psk (wiphy.c:307)
==4249== by 0x40499E: network_connect (wiphy.c:359)
==4249== by 0x41D85E: _dbus_object_tree_dispatch (dbus-service.c:845)
==4249== by 0x416A86: message_read_handler (dbus.c:297)
==4249== by 0x4119F4: io_callback (io.c:120)
==4249== by 0x411032: l_main_run (main.c:346)
==4249== by 0x40253E: main (main.c:171)
This patch saves off the PSK generated based on the passphrase provided
by the agent/user. The PSK is saved only if the connection is
successful.
Subsequent connection attempts to the known AP use the PSK saved on the
filesystem (default /var/lib/iwd/<ssid>.psk). If the connection fails,
the agent will again be asked for the passphrase on the next attempt.
CMD_DEAUTHENTICATE seems to carry only the management frame pdu
information. CMD_DISCONNECT is carrying the information that is
actually needed by us:
> Event: Disconnect (0x30) len 28 1140.118545
Wiphy: 0 (0x00000000)
Interface Index: 3 (0x00000003)
Reason Code: 2 (0x0002)
Disconnect by AP: true
We will ignore non-UTF8 based SSIDs. Support for non-UTF8 SSIDs seems
to be of dubious value in the real world as the vast majority of
consumer devices would not even allow such SSIDs to be configured or
used.
There also seems to be no compelling argument to support such SSIDs, so
until that argument arrives, non-UTF8 SSIDs will be filtered out. This
makes the D-Bus API and implementation much easier.
We start a timer. This handles the case that the Authenticator does
not send us the first message of the 4-way handshake, or disappears
before sending us the 3rd message.
We need to set the linkmode and operstate after successful
authentication.
Initial value for linkmode is 1 (user space controlled) and
IF_OPER_DORMANT for opermode. After successful authentication,
the operstate is set to IF_OPER_UP.
More specific details can be seen in kernel sources at
https://www.kernel.org/doc/Documentation/networking/operstates.txt