mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 21:57:55 +00:00
driver/wifi: rework CTRL interface manager
This commit streamlines the interaction between the Wifi::Manager and the wpa_supplicant's CTRL interface. As user-facing changes it alters some default settings and introduces new features: * Every configured network now needs to explicitly have its 'auto_connect' (to be considered an option for joining) attribute set to 'true' whereas this was previously the default value if the attribute was not set at all. * The 'log_level' attribute is added and configures the supplicant's verbosity. Valid values correspond to levels used by the supplicant and are as follows 'excessive', 'msgdump', 'debug', 'info', 'warning' and 'error'. The default value is 'error' and configures the least amount of verbosity. * The 'bgscan' attribute may be used to configure the way the supplicant performs background-scanning to steer or rather optimize roaming decision within the same network. The default value is set to 'simple:30:-70:600'. It can be disabled by specifying an empty value, e.g. 'bgscan=""'. * The 'verbose_state' attribute was removed alltogether and similar functionality is now coverted by 'verbose' attribute. Implementation-wise the internals changed significantly and are outlined in the following paragraphs. Formerly the interaction between the manager and the supplicant was handled in an apparent way where the internal state of each interaction was in plain sight. This made the flow cumbersome to follow and therefor each interaction is now confined to its own 'Action' object that encapsulates the ping-pong of commands and responses between the manager and the supplicant. All actions are processed in an sequential way and thus there is no longer any need to defer pending actions depending on the interal state of the current interaction. Configuration changes as well as events issued by the supplicant where new actions can be created are handled in this fashion. Of note are both signal-handlers, '_handle_cmds' and '_handle_events' respectively. The state report, which provides the information about the current state of connectivity to a given wireless network, was dealt with in the same vein and its handling was spread across the manager implementation. Again, to make it easier to follow, the generation of the state report is now purely driven by the 'Join_state' object. This object encapsulates the state of connectivity and is normally updated by events issued from the supplicant (see '_handle_events'). It is also incorporated when handling command responses (see '_handle_cmds'). Handling of timed-actions, like scan and signal quality update requests, was done by setting a timeout at the Timer session directly and thus only one timed-action could be pending at any time. This excluded dealing with timed-actions like connected-scanning and signal quality polling concurrently. This was changed and now a One_shot_timeout is used to programm each concurrent timed-action. For implementing the communication channel for the CTRL interface the manager and supplicant use a shared memory buffer, the Msg_buffer. Since the CTRL interface for Genode was implemented using C, some shenanigans were performed to access the memory buffer. Now the CTRL interface implementation uses C++ and only exports the functions required by the supplicant as C. This simplifies the usage of the Msg_buffer and allows for removing the global functions needed for synchronizing the Msg_buffer access as those are now part of the object itself via the 'Notify_interface'. Fixes #5341.
This commit is contained in:
parent
6b474e059c
commit
d4e4b8bf60
@ -14,33 +14,90 @@
|
|||||||
#ifndef _WIFI__CTRL_H_
|
#ifndef _WIFI__CTRL_H_
|
||||||
#define _WIFI__CTRL_H_
|
#define _WIFI__CTRL_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include <util/string.h>
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#define WPA_CTRL_FD 51
|
namespace Wifi {
|
||||||
|
|
||||||
struct Msg_buffer
|
/*
|
||||||
|
* FD used to poll CTRL state from the supplicant.
|
||||||
|
*/
|
||||||
|
enum { CTRL_FD = 51, };
|
||||||
|
|
||||||
|
struct Msg_buffer;
|
||||||
|
|
||||||
|
struct Notify_interface : Genode::Interface
|
||||||
|
{
|
||||||
|
virtual void submit_response() = 0;
|
||||||
|
virtual void submit_event() = 0;
|
||||||
|
virtual void block_for_processing() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ctrl_init(Msg_buffer &);
|
||||||
|
|
||||||
|
} /* namespace Wifi */
|
||||||
|
|
||||||
|
|
||||||
|
struct Wifi::Msg_buffer
|
||||||
{
|
{
|
||||||
unsigned char recv[4096*8];
|
char send[4096];
|
||||||
unsigned char send[4096];
|
|
||||||
unsigned recv_id;
|
|
||||||
unsigned send_id;
|
unsigned send_id;
|
||||||
unsigned char event[1024];
|
|
||||||
|
char recv[4096*8];
|
||||||
|
unsigned recv_id;
|
||||||
|
unsigned last_recv_id;
|
||||||
|
|
||||||
|
char event[1024];
|
||||||
unsigned event_id;
|
unsigned event_id;
|
||||||
} __attribute__((packed));
|
unsigned last_event_id;
|
||||||
|
|
||||||
|
Notify_interface &_notify;
|
||||||
|
|
||||||
|
Msg_buffer(Notify_interface ¬ify)
|
||||||
|
: _notify { notify } { }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Member functions below are called by the
|
||||||
|
* CTRL interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void notify_response() const {
|
||||||
|
_notify.submit_response(); }
|
||||||
|
|
||||||
|
void notify_event() const {
|
||||||
|
_notify.submit_event(); }
|
||||||
|
|
||||||
|
void block_for_processing() {
|
||||||
|
_notify.block_for_processing(); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Member functions below are called by the
|
||||||
|
* Manager.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void with_new_reply(auto const &fn)
|
||||||
|
{
|
||||||
|
char const *msg = reinterpret_cast<char const*>(recv);
|
||||||
|
/* return early */
|
||||||
|
if (last_recv_id == recv_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
last_recv_id = recv_id;
|
||||||
|
fn(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void with_new_event(auto const &fn)
|
||||||
|
{
|
||||||
|
char const *msg = reinterpret_cast<char const*>(event);
|
||||||
|
|
||||||
|
if (last_event_id == event_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
last_event_id = event_id;
|
||||||
|
fn(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void wpa_ctrl_set_fd(void);
|
void wpa_ctrl_set_fd(void);
|
||||||
|
|
||||||
void *wifi_get_buffer(void);
|
|
||||||
void wifi_notify_cmd_result(void);
|
|
||||||
void wifi_block_for_processing(void);
|
|
||||||
void wifi_notify_event(void);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif /* _WIFI__CTRL_H_ */
|
#endif /* _WIFI__CTRL_H_ */
|
||||||
|
@ -36,12 +36,20 @@ namespace Wifi {
|
|||||||
bool rfkill_blocked();
|
bool rfkill_blocked();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set RFKILL state from the frontend
|
* Set RFKILL state from the manager
|
||||||
*
|
*
|
||||||
* May be only called from an EP context.
|
* May be only called from an EP context.
|
||||||
*/
|
*/
|
||||||
void set_rfkill(bool);
|
void set_rfkill(bool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger RFKILL notification signal
|
||||||
|
*
|
||||||
|
* Used by the supplicants RFKILL driver to notify
|
||||||
|
* the management-layer.
|
||||||
|
*/
|
||||||
|
void rfkill_notify();
|
||||||
|
|
||||||
} /* namespace Wifi */
|
} /* namespace Wifi */
|
||||||
|
|
||||||
#endif /* _WIFI__RFKILL_H_ */
|
#endif /* _WIFI__RFKILL_H_ */
|
||||||
|
@ -10,7 +10,8 @@ CC_OPT += -Wno-unused-function
|
|||||||
|
|
||||||
CC_CXX_OPT += -fpermissive
|
CC_CXX_OPT += -fpermissive
|
||||||
|
|
||||||
SRC_C += main.c ctrl_iface_genode.c
|
SRC_C += main.c
|
||||||
|
SRC_CC += ctrl_iface_genode.cc
|
||||||
INC_DIR += $(REP_DIR)/include
|
INC_DIR += $(REP_DIR)/include
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ wifi_ifname T
|
|||||||
_ZN4Wifi20firmware_get_requestEv T
|
_ZN4Wifi20firmware_get_requestEv T
|
||||||
_ZN4Wifi26firmware_establish_handlerERNS_24Firmware_request_handlerE T
|
_ZN4Wifi26firmware_establish_handlerERNS_24Firmware_request_handlerE T
|
||||||
_ZN4Wifi10set_rfkillEb T
|
_ZN4Wifi10set_rfkillEb T
|
||||||
|
_ZN4Wifi13rfkill_notifyEv T
|
||||||
_ZN4Wifi14rfkill_blockedEv T
|
_ZN4Wifi14rfkill_blockedEv T
|
||||||
_ZN4Wifi24rfkill_establish_handlerERNS_27Rfkill_notification_handlerE T
|
_ZN4Wifi24rfkill_establish_handlerERNS_27Rfkill_notification_handlerE T
|
||||||
convert_errno_from_linux T
|
convert_errno_from_linux T
|
||||||
|
@ -93,7 +93,7 @@ The nl80211 driver patch contains the following changes:
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
- global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
|
- global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
+ global->ioctl_sock = 42;
|
+ global->ioctl_sock = 12345; /* arbitrarily chosen number b/c it won't be used anyway */
|
||||||
if (global->ioctl_sock < 0) {
|
if (global->ioctl_sock < 0) {
|
||||||
wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
|
wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -1 +1 @@
|
|||||||
aa7af61abdac82e5a783d8371be9cb8d1a41fceb
|
15974e67af9112d919f1625a5c2ed2d996cdbdfb
|
||||||
|
@ -133,8 +133,8 @@ install_config {
|
|||||||
<config>
|
<config>
|
||||||
<rom name="wifi_config">
|
<rom name="wifi_config">
|
||||||
<inline description="CONNECT">
|
<inline description="CONNECT">
|
||||||
<wifi_config connected_scan_interval="0" scan_interval="5" rfkill="no" verbose="no" verbose_state="no">
|
<wifi_config>
|
||||||
<network ssid="} [wifi_ssid] {" protection="WPA2" passphrase="} [wifi_psk] {"/>
|
<network ssid="} [wifi_ssid] {" protection="WPA2" passphrase="} [wifi_psk] {" auto_connect="true"/>
|
||||||
</wifi_config>
|
</wifi_config>
|
||||||
</inline>
|
</inline>
|
||||||
<sleep milliseconds="600000"/> <!-- 10 minutes -->
|
<sleep milliseconds="600000"/> <!-- 10 minutes -->
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
The wifi component is a port of the Linux mac802.11 stack as well as
|
The wifi component consists of a port of the Linux mac802.11 stack as well
|
||||||
libnl and wpa_supplicant to Genode. Depending on the used platform it
|
as libnl and wpa_supplicant to Genode. Depending on the used platform it
|
||||||
features a selection of drivers for wireless devices. For example on the
|
features a selection of drivers for wireless devices. For example on the
|
||||||
PC platform it contains the ath9k, iwlwifi and rtlwifi drivers for PCI(e)
|
PC platform it contains the ath9k, iwlwifi and rtlwifi drivers for PCI(e)
|
||||||
devices.
|
devices.
|
||||||
@ -10,14 +10,18 @@ The 'wifi' binary is the generic management part that includes the Wifi
|
|||||||
configuration interface and the 'wpa_supplicant'. A suitable driver library
|
configuration interface and the 'wpa_supplicant'. A suitable driver library
|
||||||
is loaded at run-time (see section [Debugging]).
|
is loaded at run-time (see section [Debugging]).
|
||||||
|
|
||||||
To start the component on the PC platform the following configuration snippet
|
|
||||||
can be used:
|
Configuration
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This configuration snippet shows how to start the component on the PC
|
||||||
|
platform.
|
||||||
|
|
||||||
!<start name="wifi" caps="250">
|
!<start name="wifi" caps="250">
|
||||||
! <resource name="RAM" quantum="32M"/>
|
! <resource name="RAM" quantum="32M"/>
|
||||||
! <provides><service name="Nic"/></provides>
|
! <provides><service name="Nic"/></provides>
|
||||||
! <config>
|
! <config>
|
||||||
! <libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
|
! <libc stdout="/dev/log" stderr="/dev/null" rtc="/dev/rtc"/>
|
||||||
! <vfs>
|
! <vfs>
|
||||||
! <dir name="dev"> <log/> <null/> <rtc/>
|
! <dir name="dev"> <log/> <null/> <rtc/>
|
||||||
! <jitterentropy name="random"/>
|
! <jitterentropy name="random"/>
|
||||||
@ -38,14 +42,14 @@ can be used:
|
|||||||
! </route>
|
! </route>
|
||||||
!</start>
|
!</start>
|
||||||
|
|
||||||
On other platforms the wifi library will be different. The following
|
On other platforms the wifi library will be different. So, the
|
||||||
snippet illustrates the use of the driver on the PinePhone:
|
following snippet illustrates the use of the driver on the PinePhone.
|
||||||
|
|
||||||
!<start name="wifi" caps="250">
|
!<start name="wifi" caps="250">
|
||||||
! <resource name="RAM" quantum="32M"/>
|
! <resource name="RAM" quantum="32M"/>
|
||||||
! <provides><service name="Nic"/></provides>
|
! <provides><service name="Nic"/></provides>
|
||||||
! <config>
|
! <config>
|
||||||
! <libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
|
! <libc stdout="/dev/log" stderr="/dev/null" rtc="/dev/rtc"/>
|
||||||
! <vfs>
|
! <vfs>
|
||||||
! <dir name="dev"> <log/> <null/> <rtc/>
|
! <dir name="dev"> <log/> <null/> <rtc/>
|
||||||
! <jitterentropy name="random"/>
|
! <jitterentropy name="random"/>
|
||||||
@ -79,55 +83,95 @@ directory in the driver's local VFS. It is up to the configuration
|
|||||||
how those files are made available. In these examples they are
|
how those files are made available. In these examples they are
|
||||||
contained in an '.tar' archive that is request as a ROM module.
|
contained in an '.tar' archive that is request as a ROM module.
|
||||||
|
|
||||||
The driver will request access to the ROM module 'wifi_config' to
|
The driver will request access to the 'wifi_config' ROM module that
|
||||||
connect to a network:
|
contains its actual configuration in the '<wifi_config>' node. This
|
||||||
|
node features the following attributes.
|
||||||
|
|
||||||
!<wifi_config connected_scan_interval="30" scan_interval="10" rfkill="no">
|
* :scan_interval: sets the time interval in seconds in which scan
|
||||||
! <network ssid="Foobar" protection="WPA2" passphrase="allyourbase"/>
|
operations are requested and is used when not already connected
|
||||||
!</wifi_config>
|
to a network. The default is 5 seconds.
|
||||||
|
|
||||||
To temporarily prevent any radio activity, the 'rfkill' attribute
|
* :update_quality_interval: sets the time interval in which the current
|
||||||
can be set to 'true'.
|
signal quality of the connected access point is updated (RSSI polling).
|
||||||
|
The default value is 30 seconds.
|
||||||
|
|
||||||
If the network is protected by, e.g., WPA/WPA2/WPA3, the protection type,
|
* :rfkill: allows to temporarily prevent any radio activity. The
|
||||||
either 'WPA', 'WPA2' or 'WPA3' as well as the the passphrase have to be
|
default is 'false'.
|
||||||
specified.
|
|
||||||
The 'bssid' attribute can be used to select a specifc accesspoint within a
|
|
||||||
network. Of all attributes only the 'ssid' attribute is mandatory, all others
|
|
||||||
are optional and should only be used when needed.
|
|
||||||
|
|
||||||
The configuration may contain more than one network. In This case the driver
|
* :bgscan: is an expert option that configures the way the
|
||||||
will try to select the best one it gets a response from. To prevent it
|
supplicant performs background scanning to steer or rather optimize
|
||||||
from automatically joining the network the 'auto_connect' attribute must be
|
roaming decisions within the same network (SSID). The syntax of the
|
||||||
set to 'false'; the default value is 'true'. If the 'explicit_scan' attribute
|
option string corresponds to the original WPA-supplicant 'bgscan' option.
|
||||||
is set, the driver will pro-actively scan for a hidden network with the given
|
The default value is set to 'simple:30:-70:600'. This functionality can
|
||||||
SSID:
|
be disabled by specifying an empty value, e.g. 'bgscan=""'. If bgscan is
|
||||||
|
disabled the 'accesspoints' report will not be updated while the
|
||||||
|
supplicant is connected to a network.
|
||||||
|
|
||||||
!<wifi_config connected_scan_interval="30" scan_interval="10">
|
* :log_level: allows for steering the verbosity of the supplicant
|
||||||
! <network ssid="Zero" protection="WPA2" passphrase="allyourbase"/>
|
and may assist while diagnosing problems with the driver.
|
||||||
|
Valid values correspond to levels used by the supplicant
|
||||||
|
and are as follows 'excessive', 'msgdump', 'debug', 'info',
|
||||||
|
'warning' and 'error'. The default value is 'error' and configures
|
||||||
|
the least amount of verbosity.
|
||||||
|
|
||||||
|
* :verbose: allows for logging of diagnostic messages generated
|
||||||
|
by the managing portion of the driver. The default is 'false'.
|
||||||
|
|
||||||
|
Besides those attributes the '<wifi_config>' node can host one or
|
||||||
|
more '<network>' nodes. Such a node describes the parameters of
|
||||||
|
a network and has the following attributes.
|
||||||
|
|
||||||
|
* :ssid: sets the name of the network.
|
||||||
|
|
||||||
|
Note: the SSID is copied verbatim and at the moment, there is no way
|
||||||
|
to express or escape non alphanumeric characters.
|
||||||
|
|
||||||
|
* :bssid: can be used to select a specific access point within a
|
||||||
|
network.
|
||||||
|
|
||||||
|
* :protection: specifies the used protection mechanism of the
|
||||||
|
network. Valid values are 'WPA', 'WPA2', 'WPA3' and 'NONE'.
|
||||||
|
The last one is used in case the network uses other means of
|
||||||
|
protection and access is open.
|
||||||
|
|
||||||
|
Note: currently only personal WPA protection using a pre-shared-key
|
||||||
|
(PSK) is supported.
|
||||||
|
|
||||||
|
* :passphrase: sets the PSK that is required should the
|
||||||
|
network be protected.
|
||||||
|
|
||||||
|
* :auto_connect: allows for joining a network automatically. The
|
||||||
|
default value is 'true'. When more than one network is configured
|
||||||
|
with enabled 'auto_connect' the driver will try to select the best
|
||||||
|
one it gets a response from.
|
||||||
|
|
||||||
|
Note: If configured auto-connect networks overlap in locality, the
|
||||||
|
driver might switch dynamically between the networks.
|
||||||
|
|
||||||
|
* :explicit_scan: must be set to explicitly scan for hidden networks.
|
||||||
|
The default is 'false' and it should only be set for networks
|
||||||
|
that are hidden indeed.
|
||||||
|
|
||||||
|
Of all attributes solely the 'ssid' attribute is mandatory and all
|
||||||
|
others are optional. They should be used when needed only.
|
||||||
|
|
||||||
|
The following exemplary snippet showcases a config for two networks where
|
||||||
|
the first one should be automatically considered for joining and uses 'WPA2'
|
||||||
|
while the second one is hidden but should show up in the scan results and
|
||||||
|
uses 'WPA'.
|
||||||
|
|
||||||
|
!<wifi_config scan_interval="10" update_quality_interval="30">
|
||||||
|
! <network ssid="Zero" protection="WPA2" passphrase="allyourbase"
|
||||||
|
! auto_connect="true"/>
|
||||||
! <network ssid="Skynet" protection="WPA" passphrase="12345678"
|
! <network ssid="Skynet" protection="WPA" passphrase="12345678"
|
||||||
! explicit_scan="true" auto_connect="false"/>
|
! explicit_scan="true"/>
|
||||||
!</wifi_config>
|
!</wifi_config>
|
||||||
|
|
||||||
By default, the driver scans for available networks only when not
|
|
||||||
connected. This can be changed with the 'connected_scan_interval'
|
|
||||||
attribute, which specifies the interval for connected scans in
|
|
||||||
seconds and directly influences any roaming decision, i.e., select
|
|
||||||
a better fit accesspoint for the configured network.
|
|
||||||
|
|
||||||
In addition, by specifing 'update_quality_interval', the driver will
|
The wifi driver uses two distinct reports, 'state' and 'accesspoints',
|
||||||
every so often update the current signal quality of the established
|
to communicate its state of connectivity and information about the wireless
|
||||||
connection to the accesspoint. Note that this option is only useable when
|
access points in the vicinity to other components.
|
||||||
the 'connected_scan_interval' is set to '0' as both options are mutually
|
This exemplary 'accesspoints' report shows its general structure.
|
||||||
exclusive.
|
|
||||||
|
|
||||||
Also, the driver can be switched to verbose logging during runtime
|
|
||||||
by setting the 'verbose' or 'verbose_state' attribute to 'true'.
|
|
||||||
|
|
||||||
The wifi driver creates two distinct reports to communicate its state and
|
|
||||||
information about the wireless infrastructure to other components. The
|
|
||||||
first one is a list of all available accesspoints. The following examplary
|
|
||||||
report shows its general structure:
|
|
||||||
|
|
||||||
!<accesspoints>
|
!<accesspoints>
|
||||||
! <accesspoint ssid="skynet" bssid="00:01:02:03:04:05" quality="40"/>
|
! <accesspoint ssid="skynet" bssid="00:01:02:03:04:05" quality="40"/>
|
||||||
@ -135,32 +179,50 @@ report shows its general structure:
|
|||||||
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:07" quality="10" protection="WPA2"/>
|
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:07" quality="10" protection="WPA2"/>
|
||||||
!</accesspoints>
|
!</accesspoints>
|
||||||
|
|
||||||
Each accesspoint node has attributes that contain the SSID and the BSSID
|
The '<accesspoints>' node can contain a fluctuating number of '<accesspoint>'
|
||||||
of the accesspoint as well as the link quality (signal strength). These
|
nodes that describe an access point with the following attributes.
|
||||||
attributes are mandatory. If the network is protected, the node will also
|
|
||||||
have an attribute describing the type of protection in addition.
|
|
||||||
|
|
||||||
The second report provides information about the state of the connection
|
* :ssid: specifies the name of the network the access point advertises.
|
||||||
to the currently connected accesspoint:
|
Empty SSIDs are not reported.
|
||||||
|
|
||||||
|
* :bssid: specifies the physical address of the access point.
|
||||||
|
|
||||||
|
* :freq: specifies the frequency used by the access point.
|
||||||
|
|
||||||
|
* :quality: specifies the approximated link quality (calculated from the
|
||||||
|
RSSI value).
|
||||||
|
|
||||||
|
* :protection: specifies which kind of protection is employed by the access
|
||||||
|
point.
|
||||||
|
|
||||||
|
Note: when a mixed protection is used by the network, like WPA2-PSK and
|
||||||
|
WPA3-PSK mixed-mode, only the strongest protection (WPA3-PSK) is
|
||||||
|
advertised.
|
||||||
|
|
||||||
|
The 'state' report provides information about the state of the connectivity
|
||||||
|
and looks as follows.
|
||||||
|
|
||||||
!<state>
|
!<state>
|
||||||
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:06" quality="70" freq="2418" state="connected"/>
|
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:06" quality="70" freq="2418" state="connected"/>
|
||||||
!</state>
|
!</state>
|
||||||
|
|
||||||
Valid state values are 'connected', 'disconnected', 'connecting'. Depending
|
The '<state>' node encompasses one '<accesspoint>' node that has the
|
||||||
on the state, there are additional attributes that can be checked. In case
|
following additional attributes beside the ones already discussed.
|
||||||
of an authentication error, e.g. the passphrase is wrong, the 'auth_failure'
|
|
||||||
attribute will be set to 'true'. The 'rfkilled' attribute is set to 'true'
|
|
||||||
if a disconnect was triggered by disabling the radio activity via setting
|
|
||||||
the 'rfkill' attribute. It can also contain the optional 'quality' attribute
|
|
||||||
to denote the current signal quality (see 'update_quality_interval').
|
|
||||||
|
|
||||||
By subscribing to both reports and providing the required 'wifi_config' ROM
|
* :state: specifies the actual state of connectivity. Valid values
|
||||||
module, a component is able control the wireless driver.
|
are 'connected', 'connecting' and 'disconnected'.
|
||||||
|
|
||||||
Currently only WPA/WPA2/WPA3 protection using a passphrase is supported and
|
* :auth_failure: is an optional attribute and set to 'true' in case
|
||||||
the SSID is copied verbatim. At the moment, there is no way to express or
|
the PSK was wrong
|
||||||
escape non alphanumeric characters.
|
|
||||||
|
* :rfkilled: is an optional attribute and set to 'true' whenever
|
||||||
|
radio activity was temporarily disabled.
|
||||||
|
|
||||||
|
* :not_found: is an optional attribute and is only set when a single
|
||||||
|
auto-connect network was configured but could not be found.
|
||||||
|
|
||||||
|
By subscribing to both reports and providing the required 'wifi_config'
|
||||||
|
ROM module, a component is able control the wireless driver.
|
||||||
|
|
||||||
The driver optionally reports the following information under the
|
The driver optionally reports the following information under the
|
||||||
label "devices" if requested in the config as depicted.
|
label "devices" if requested in the config as depicted.
|
||||||
@ -177,7 +239,7 @@ As mentioned in the introduction the 'wifi' component is special in the
|
|||||||
regard that the actual driver is provided as a shared-object to better isolate
|
regard that the actual driver is provided as a shared-object to better isolate
|
||||||
it from the the driver binary that is a Libc::Component managing the
|
it from the the driver binary that is a Libc::Component managing the
|
||||||
'wpa_supplicant'. Since this code and in return the binary is the same for each
|
'wpa_supplicant'. Since this code and in return the binary is the same for each
|
||||||
platform it is linked against an artifical 'wifi' library that only exists as
|
platform it is linked against an artificial 'wifi' library that only exists as
|
||||||
an ABI stub created via 'lib/symbols/wifi'. In case the driver is integrated
|
an ABI stub created via 'lib/symbols/wifi'. In case the driver is integrated
|
||||||
via depot archives this is, besides setting the proper ROM routes, of no
|
via depot archives this is, besides setting the proper ROM routes, of no
|
||||||
concern. However, when the driver is built without the depot, the boot image
|
concern. However, when the driver is built without the depot, the boot image
|
||||||
@ -198,7 +260,7 @@ rather then stub ABI library. This is achieved by adapting the driver's
|
|||||||
![…]
|
![…]
|
||||||
|
|
||||||
'LIBS' must be changed as follows in case the PC wifi driver library is
|
'LIBS' must be changed as follows in case the PC wifi driver library is
|
||||||
used:
|
used.
|
||||||
|
|
||||||
!LIBS := base pc_wifi
|
!LIBS := base pc_wifi
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,68 +28,12 @@
|
|||||||
/* local includes */
|
/* local includes */
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wpa.h"
|
#include "wpa.h"
|
||||||
#include "frontend.h"
|
#include "manager.h"
|
||||||
#include "access_firmware.h"
|
#include "access_firmware.h"
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
static Msg_buffer _wifi_msg_buffer;
|
|
||||||
static Wifi::Frontend *_wifi_frontend = nullptr;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify front end about command processing
|
|
||||||
*
|
|
||||||
* Called by the CTRL interface after wpa_supplicant has processed
|
|
||||||
* the command.
|
|
||||||
*/
|
|
||||||
void wifi_block_for_processing(void)
|
|
||||||
{
|
|
||||||
if (!_wifi_frontend) {
|
|
||||||
warning("frontend not available, dropping notification");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Next time we block as long as the front end has not finished
|
|
||||||
* handling our previous request
|
|
||||||
*/
|
|
||||||
_wifi_frontend->block_for_processing();
|
|
||||||
|
|
||||||
/* XXX hack to trick poll() into returning faster */
|
|
||||||
wpa_ctrl_set_fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wifi_notify_cmd_result(void)
|
|
||||||
{
|
|
||||||
if (!_wifi_frontend) {
|
|
||||||
warning("frontend not available, dropping notification");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Signal_transmitter(_wifi_frontend->result_sigh()).submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify front end about triggered event
|
|
||||||
*
|
|
||||||
* Called by the CTRL interface whenever wpa_supplicant has triggered
|
|
||||||
* a event.
|
|
||||||
*/
|
|
||||||
void wifi_notify_event(void)
|
|
||||||
{
|
|
||||||
if (!_wifi_frontend) {
|
|
||||||
Genode::warning("frontend not available, dropping notification");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Signal_transmitter(_wifi_frontend->event_sigh()).submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* exported by wifi.lib.so */
|
/* exported by wifi.lib.so */
|
||||||
extern void wifi_init(Genode::Env&, Genode::Blockade&);
|
extern void wifi_init(Genode::Env&, Genode::Blockade&);
|
||||||
extern void wifi_set_rfkill_sigh(Genode::Signal_context_capability);
|
extern void wifi_set_rfkill_sigh(Genode::Signal_context_capability);
|
||||||
@ -101,8 +45,8 @@ struct Main
|
|||||||
{
|
{
|
||||||
Env &env;
|
Env &env;
|
||||||
|
|
||||||
Constructible<Wpa_thread> _wpa;
|
Constructible<Wpa_thread> _wpa;
|
||||||
Constructible<Wifi::Frontend> _frontend;
|
Constructible<Wifi::Manager> _manager;
|
||||||
|
|
||||||
struct Request_handler : Wifi::Firmware_request_handler
|
struct Request_handler : Wifi::Firmware_request_handler
|
||||||
{
|
{
|
||||||
@ -173,28 +117,17 @@ struct Main
|
|||||||
/* prepare Lx_kit::Env */
|
/* prepare Lx_kit::Env */
|
||||||
wifi_init(env, _wpa_startup_blockade);
|
wifi_init(env, _wpa_startup_blockade);
|
||||||
|
|
||||||
_frontend.construct(env, _wifi_msg_buffer);
|
_manager.construct(env);
|
||||||
_wifi_frontend = &*_frontend;
|
|
||||||
|
|
||||||
Wifi::rfkill_establish_handler(*_wifi_frontend);
|
Wifi::rfkill_establish_handler(*_manager);
|
||||||
Wifi::firmware_establish_handler(_request_handler);
|
Wifi::firmware_establish_handler(_request_handler);
|
||||||
|
|
||||||
|
Wifi::ctrl_init(_manager->msg_buffer());
|
||||||
_wpa.construct(env, _wpa_startup_blockade);
|
_wpa.construct(env, _wpa_startup_blockade);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return shared-memory message buffer
|
|
||||||
*
|
|
||||||
* It is used by the wpa_supplicant CTRL interface.
|
|
||||||
*/
|
|
||||||
void *wifi_get_buffer(void)
|
|
||||||
{
|
|
||||||
return &_wifi_msg_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Libc::Component::construct(Libc::Env &env)
|
void Libc::Component::construct(Libc::Env &env)
|
||||||
{
|
{
|
||||||
static Main server(env);
|
static Main server(env);
|
||||||
|
2131
repos/dde_linux/src/driver/wifi/manager.h
Normal file
2131
repos/dde_linux/src/driver/wifi/manager.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Wifi front end utilities
|
* \brief Wifi manager utilities
|
||||||
* \author Josef Soentgen
|
* \author Josef Soentgen
|
||||||
* \date 2018-07-23
|
* \date 2018-07-23
|
||||||
*/
|
*/
|
||||||
@ -59,9 +59,9 @@ namespace Util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************
|
/********************************
|
||||||
** Front end specific utilities **
|
** Manager-specific utilities **
|
||||||
**********************************/
|
********************************/
|
||||||
|
|
||||||
inline unsigned approximate_quality(char const *str)
|
inline unsigned approximate_quality(char const *str)
|
||||||
{
|
{
|
||||||
|
@ -460,10 +460,10 @@ static int rfkill_task_function(void *arg)
|
|||||||
|
|
||||||
bool rfkilled = !!rfkill_get_global_sw_state(RFKILL_TYPE_WLAN);
|
bool rfkilled = !!rfkill_get_global_sw_state(RFKILL_TYPE_WLAN);
|
||||||
|
|
||||||
if (rfkilled != _rfkill_state.blocked)
|
if (rfkilled != _rfkill_state.blocked) {
|
||||||
rfkill_switch_all(RFKILL_TYPE_WLAN, !!_rfkill_state.blocked);
|
rfkill_switch_all(RFKILL_TYPE_WLAN, !!_rfkill_state.blocked);
|
||||||
|
_rfkill_state.rfkilled = !!_rfkill_state.blocked;
|
||||||
_rfkill_state.rfkilled = rfkilled;
|
}
|
||||||
|
|
||||||
lx_emul_task_schedule(true);
|
lx_emul_task_schedule(true);
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,11 @@ void Wifi::set_rfkill(bool blocked)
|
|||||||
*/
|
*/
|
||||||
lx_emul_task_unblock(uplink_task_struct_ptr);
|
lx_emul_task_unblock(uplink_task_struct_ptr);
|
||||||
Lx_kit::env().scheduler.execute();
|
Lx_kit::env().scheduler.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Wifi::rfkill_notify()
|
||||||
|
{
|
||||||
if (_wlan_ptr->rfkill_helper.constructed())
|
if (_wlan_ptr->rfkill_helper.constructed())
|
||||||
_wlan_ptr->rfkill_helper->submit_notification();
|
_wlan_ptr->rfkill_helper->submit_notification();
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,8 @@ static void rfkill_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
|||||||
} else {
|
} else {
|
||||||
rfkill->cfg->unblocked_cb(rfkill->cfg->ctx);
|
rfkill->cfg->unblocked_cb(rfkill->cfg->ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Wifi::rfkill_notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,250 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief WPA Supplicant frontend
|
|
||||||
* \author Josef Soentgen
|
|
||||||
* \date 2018-07-18
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2018 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is distributed under the terms of the GNU General Public License
|
|
||||||
* version 2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* based on:
|
|
||||||
*
|
|
||||||
* WPA Supplicant / UNIX domain socket -based control interface
|
|
||||||
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
|
|
||||||
*
|
|
||||||
* This software may be distributed under the terms of the BSD license.
|
|
||||||
* See README for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* wpa_supplicant includes */
|
|
||||||
#include "includes.h"
|
|
||||||
#include "utils/common.h"
|
|
||||||
#include "utils/eloop.h"
|
|
||||||
#include "utils/list.h"
|
|
||||||
#include "common/ctrl_iface_common.h"
|
|
||||||
#include "eapol_supp/eapol_supp_sm.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "wpa_supplicant_i.h"
|
|
||||||
#include "ctrl_iface.h"
|
|
||||||
|
|
||||||
/* rep includes */
|
|
||||||
#include <wifi/ctrl.h>
|
|
||||||
|
|
||||||
typedef unsigned unaligned_unsigned __attribute__ ((aligned (1)));
|
|
||||||
|
|
||||||
struct ctrl_iface_priv {
|
|
||||||
struct wpa_supplicant *wpa_s;
|
|
||||||
int fd;
|
|
||||||
int level;
|
|
||||||
|
|
||||||
/* TODO replace w/ Msg_buffer */
|
|
||||||
char *send_buffer;
|
|
||||||
size_t send_buffer_size;
|
|
||||||
unaligned_unsigned *send_id;
|
|
||||||
|
|
||||||
char *recv_buffer;
|
|
||||||
size_t recv_buffer_size;
|
|
||||||
unaligned_unsigned *recv_id;
|
|
||||||
|
|
||||||
unsigned last_recv_id;
|
|
||||||
|
|
||||||
char *event_buffer;
|
|
||||||
size_t event_buffer_size;
|
|
||||||
unaligned_unsigned *event_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ctrl_iface_global_priv {
|
|
||||||
struct wpa_global *global;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern void nl_set_wpa_ctrl_fd(void);
|
|
||||||
|
|
||||||
|
|
||||||
void wpa_ctrl_set_fd()
|
|
||||||
{
|
|
||||||
nl_set_wpa_ctrl_fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void send_reply(struct ctrl_iface_priv *priv, char const *txt, size_t len)
|
|
||||||
{
|
|
||||||
char *msg = priv->send_buffer;
|
|
||||||
size_t mlen = priv->send_buffer_size;
|
|
||||||
|
|
||||||
if (len >= mlen) {
|
|
||||||
len = mlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(msg, txt, len);
|
|
||||||
msg[len] = 0;
|
|
||||||
(*priv->send_id)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is called by wpa_supplicant whenever it receives a
|
|
||||||
* command via the CTRL interface, i.e. the front end has sent a new
|
|
||||||
* message.
|
|
||||||
*/
|
|
||||||
static void wpa_supplicant_ctrl_iface_receive(int fd, void *eloop_ctx,
|
|
||||||
void *sock_ctx)
|
|
||||||
{
|
|
||||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
|
||||||
struct ctrl_iface_priv *priv = sock_ctx;
|
|
||||||
|
|
||||||
char *msg = priv->recv_buffer;
|
|
||||||
|
|
||||||
unsigned const recv_id = *priv->recv_id;
|
|
||||||
|
|
||||||
char *reply = NULL;
|
|
||||||
size_t reply_len = 0;
|
|
||||||
|
|
||||||
if (msg[0] == 0 || recv_id == priv->last_recv_id) { return; }
|
|
||||||
|
|
||||||
priv->last_recv_id = recv_id;
|
|
||||||
|
|
||||||
reply = wpa_supplicant_ctrl_iface_process(wpa_s, msg,
|
|
||||||
&reply_len);
|
|
||||||
|
|
||||||
if (reply) {
|
|
||||||
wifi_block_for_processing();
|
|
||||||
send_reply(priv, reply, reply_len);
|
|
||||||
wifi_notify_cmd_result();
|
|
||||||
os_free(reply);
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (reply_len == 1) {
|
|
||||||
wifi_block_for_processing();
|
|
||||||
send_reply(priv, "FAIL", 4);
|
|
||||||
wifi_notify_cmd_result();
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (reply_len == 2) {
|
|
||||||
wifi_block_for_processing();
|
|
||||||
send_reply(priv, "OK", 2);
|
|
||||||
wifi_notify_cmd_result();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void send_event(struct ctrl_iface_priv *priv, char const *txt, size_t len)
|
|
||||||
{
|
|
||||||
char *msg = priv->event_buffer;
|
|
||||||
size_t mlen = priv->event_buffer_size;
|
|
||||||
|
|
||||||
if (len >= mlen) {
|
|
||||||
len = mlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(msg, txt, len);
|
|
||||||
msg[len] = 0;
|
|
||||||
(*priv->event_id)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is called by wpa_supplicant whenever it wants to
|
|
||||||
* forward some message. We filter these messages and forward only
|
|
||||||
* those, which are of interest to the front end.
|
|
||||||
*/
|
|
||||||
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
|
|
||||||
enum wpa_msg_type type,
|
|
||||||
const char *txt, size_t len)
|
|
||||||
{
|
|
||||||
/* there is not global support */
|
|
||||||
if (type == WPA_MSG_ONLY_GLOBAL) { return; }
|
|
||||||
|
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
|
||||||
if (wpa_s == NULL) { return; }
|
|
||||||
|
|
||||||
struct ctrl_iface_priv *priv = wpa_s->ctrl_iface;
|
|
||||||
if (!priv || level < priv->level) { return; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Filter messages and only forward events the front end cares
|
|
||||||
* about or rather knows how to handle.
|
|
||||||
*/
|
|
||||||
int const forward =
|
|
||||||
strncmp(txt, "CTRL-EVENT-SCAN-RESULTS", 23) == 0
|
|
||||||
|| strncmp(txt, "CTRL-EVENT-CONNECTED", 20) == 0
|
|
||||||
|| strncmp(txt, "CTRL-EVENT-DISCONNECTED", 23) == 0
|
|
||||||
|| strncmp(txt, "CTRL-EVENT-NETWORK-NOT-FOUND", 28) == 0
|
|
||||||
/* needed to detect connecting state */
|
|
||||||
|| strncmp(txt, "SME: Trying to authenticate", 27) == 0
|
|
||||||
;
|
|
||||||
if (!forward) { return; }
|
|
||||||
|
|
||||||
wifi_notify_event();
|
|
||||||
send_event(priv, txt, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct ctrl_iface_priv *
|
|
||||||
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
|
||||||
{
|
|
||||||
struct ctrl_iface_priv *priv;
|
|
||||||
|
|
||||||
priv = os_zalloc(sizeof(*priv));
|
|
||||||
if (priv == NULL) { return NULL; }
|
|
||||||
|
|
||||||
if (wpa_s->conf->ctrl_interface == NULL) {
|
|
||||||
return priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Msg_buffer *msg_buffer = (struct Msg_buffer*)wifi_get_buffer();
|
|
||||||
priv->recv_buffer = (char *)msg_buffer->send;
|
|
||||||
priv->recv_buffer_size = sizeof(msg_buffer->send);
|
|
||||||
priv->send_buffer = (char *)msg_buffer->recv;
|
|
||||||
priv->send_buffer_size = sizeof(msg_buffer->recv);
|
|
||||||
priv->send_id = &msg_buffer->recv_id;
|
|
||||||
priv->recv_id = &msg_buffer->send_id;
|
|
||||||
|
|
||||||
priv->event_buffer = (char *)msg_buffer->event;
|
|
||||||
priv->event_buffer_size = sizeof(msg_buffer->event);
|
|
||||||
priv->event_id = &msg_buffer->event_id;
|
|
||||||
|
|
||||||
priv->level = MSG_INFO;
|
|
||||||
priv->fd = WPA_CTRL_FD;
|
|
||||||
|
|
||||||
eloop_register_read_sock(priv->fd,
|
|
||||||
wpa_supplicant_ctrl_iface_receive,
|
|
||||||
wpa_s, priv);
|
|
||||||
|
|
||||||
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
|
|
||||||
return priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
|
||||||
struct ctrl_iface_priv *priv)
|
|
||||||
{
|
|
||||||
(void)wpa_s;
|
|
||||||
|
|
||||||
os_free(priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) { }
|
|
||||||
|
|
||||||
|
|
||||||
struct ctrl_iface_global_priv *
|
|
||||||
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
|
|
||||||
{
|
|
||||||
struct ctrl_iface_global_priv *priv;
|
|
||||||
|
|
||||||
priv = os_zalloc(sizeof(*priv));
|
|
||||||
return priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *p)
|
|
||||||
{
|
|
||||||
os_free(p);
|
|
||||||
}
|
|
240
repos/dde_linux/src/lib/wpa_supplicant/ctrl_iface_genode.cc
Normal file
240
repos/dde_linux/src/lib/wpa_supplicant/ctrl_iface_genode.cc
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* \brief Genode-specific WPA supplicant ctrl_iface
|
||||||
|
* \author Josef Soentgen
|
||||||
|
* \date 2018-07-18
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is distributed under the terms of the GNU General Public License
|
||||||
|
* version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* based on:
|
||||||
|
*
|
||||||
|
* WPA Supplicant / UNIX domain socket -based control interface
|
||||||
|
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* wpa_supplicant includes */
|
||||||
|
extern "C" {
|
||||||
|
#include "includes.h"
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "utils/eloop.h"
|
||||||
|
#include "utils/list.h"
|
||||||
|
#include "common/ctrl_iface_common.h"
|
||||||
|
#include "eapol_supp/eapol_supp_sm.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "wpa_supplicant_i.h"
|
||||||
|
#include "ctrl_iface.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rep includes */
|
||||||
|
#include <wifi/ctrl.h>
|
||||||
|
|
||||||
|
|
||||||
|
static Wifi::Msg_buffer *_msg_buffer;
|
||||||
|
|
||||||
|
|
||||||
|
void Wifi::ctrl_init(Msg_buffer &buffer)
|
||||||
|
{
|
||||||
|
_msg_buffer = &buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ctrl_iface_priv {
|
||||||
|
struct wpa_supplicant *wpa_s;
|
||||||
|
int fd;
|
||||||
|
int level;
|
||||||
|
|
||||||
|
Wifi::Msg_buffer *buffer;
|
||||||
|
unsigned last_send_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ctrl_iface_global_priv {
|
||||||
|
struct wpa_global *global;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void nl_set_wpa_ctrl_fd(void);
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_ctrl_set_fd()
|
||||||
|
{
|
||||||
|
nl_set_wpa_ctrl_fd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void send_reply(Wifi::Msg_buffer &buffer, char const *txt, size_t len)
|
||||||
|
{
|
||||||
|
buffer.block_for_processing();
|
||||||
|
|
||||||
|
/* XXX hack to trick poll() into returning faster */
|
||||||
|
wpa_ctrl_set_fd();
|
||||||
|
|
||||||
|
if (len >= sizeof(buffer.recv))
|
||||||
|
len = sizeof(buffer.recv) - 1;
|
||||||
|
|
||||||
|
memcpy(buffer.recv, txt, len);
|
||||||
|
buffer.recv[len] = 0;
|
||||||
|
buffer.recv_id++;
|
||||||
|
|
||||||
|
buffer.notify_response();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called by wpa_supplicant whenever it receives a
|
||||||
|
* command via the CTRL interface, i.e. the manager has sent a new
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
static void wpa_supplicant_ctrl_iface_receive(int fd, void *eloop_ctx,
|
||||||
|
void *sock_ctx)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = static_cast<wpa_supplicant*>(eloop_ctx);
|
||||||
|
struct ctrl_iface_priv *priv = static_cast<ctrl_iface_priv*>(sock_ctx);
|
||||||
|
|
||||||
|
Wifi::Msg_buffer &buffer = *priv->buffer;
|
||||||
|
|
||||||
|
char *reply = NULL;
|
||||||
|
size_t reply_len = 0;
|
||||||
|
|
||||||
|
if (buffer.send[0] == 0 || buffer.send_id == priv->last_send_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->last_send_id = buffer.send_id;
|
||||||
|
|
||||||
|
reply = wpa_supplicant_ctrl_iface_process(wpa_s,
|
||||||
|
buffer.send,
|
||||||
|
&reply_len);
|
||||||
|
|
||||||
|
if (reply) {
|
||||||
|
send_reply(buffer, reply, reply_len);
|
||||||
|
os_free(reply);
|
||||||
|
} else
|
||||||
|
|
||||||
|
if (reply_len == 1) {
|
||||||
|
send_reply(buffer, "FAIL", 4);
|
||||||
|
} else
|
||||||
|
|
||||||
|
if (reply_len == 2) {
|
||||||
|
send_reply(buffer, "OK", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void send_event(Wifi::Msg_buffer &buffer, char const *txt, size_t len)
|
||||||
|
{
|
||||||
|
buffer.block_for_processing();
|
||||||
|
|
||||||
|
/* XXX hack to trick poll() into returning faster */
|
||||||
|
wpa_ctrl_set_fd();
|
||||||
|
|
||||||
|
if (len >= sizeof(buffer.event))
|
||||||
|
len = sizeof(buffer.event) - 1;
|
||||||
|
|
||||||
|
memcpy(buffer.event, txt, len);
|
||||||
|
buffer.event[len] = 0;
|
||||||
|
buffer.event_id++;
|
||||||
|
|
||||||
|
buffer.notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called by wpa_supplicant whenever it wants to
|
||||||
|
* forward some message. We filter these messages and forward only
|
||||||
|
* those, which are of interest to the Wifi manager.
|
||||||
|
*/
|
||||||
|
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
|
||||||
|
enum wpa_msg_type type,
|
||||||
|
const char *txt, size_t len)
|
||||||
|
{
|
||||||
|
/* there is not global support */
|
||||||
|
if (type == WPA_MSG_ONLY_GLOBAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct wpa_supplicant *wpa_s = static_cast<wpa_supplicant*>(ctx);
|
||||||
|
if (wpa_s == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct ctrl_iface_priv *priv = wpa_s->ctrl_iface;
|
||||||
|
if (!priv || level < priv->level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Filter messages and only forward events the manager cares
|
||||||
|
* about or rather knows how to handle.
|
||||||
|
*/
|
||||||
|
bool const forward =
|
||||||
|
strncmp(txt, "CTRL-EVENT-SCAN-RESULTS", 23) == 0
|
||||||
|
|| strncmp(txt, "CTRL-EVENT-CONNECTED", 20) == 0
|
||||||
|
|| strncmp(txt, "CTRL-EVENT-DISCONNECTED", 23) == 0
|
||||||
|
|| strncmp(txt, "CTRL-EVENT-NETWORK-NOT-FOUND", 28) == 0
|
||||||
|
/* needed to detect connecting state */
|
||||||
|
|| strncmp(txt, "SME: Trying to authenticate", 27) == 0;
|
||||||
|
if (!forward)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Wifi::Msg_buffer &buffer = *priv->buffer;
|
||||||
|
send_event(buffer, txt, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" struct ctrl_iface_priv *
|
||||||
|
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct ctrl_iface_priv *priv = (ctrl_iface_priv*)os_zalloc(sizeof(*priv));
|
||||||
|
if (priv == NULL) { return NULL; }
|
||||||
|
|
||||||
|
if (wpa_s->conf->ctrl_interface == NULL) {
|
||||||
|
return priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->buffer = _msg_buffer;
|
||||||
|
priv->level = MSG_INFO;
|
||||||
|
priv->fd = Wifi::CTRL_FD;
|
||||||
|
|
||||||
|
eloop_register_read_sock(priv->fd,
|
||||||
|
wpa_supplicant_ctrl_iface_receive,
|
||||||
|
wpa_s, priv);
|
||||||
|
|
||||||
|
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
|
||||||
|
return priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||||
|
struct ctrl_iface_priv *priv)
|
||||||
|
{
|
||||||
|
(void)wpa_s;
|
||||||
|
|
||||||
|
os_free(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) { }
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" struct ctrl_iface_global_priv *
|
||||||
|
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
|
||||||
|
{
|
||||||
|
struct ctrl_iface_global_priv *priv =
|
||||||
|
(ctrl_iface_global_priv*)os_zalloc(sizeof(*priv));
|
||||||
|
return priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *p)
|
||||||
|
{
|
||||||
|
os_free(p);
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief WPA Supplicant frontend
|
* \brief Custom WPA Supplicant main routine
|
||||||
* \author Josef Soentgen
|
* \author Josef Soentgen
|
||||||
* \date 2014-12-08
|
* \date 2014-12-08
|
||||||
*/
|
*/
|
||||||
@ -45,8 +45,7 @@ int wpa_main(void)
|
|||||||
|
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
// TODO use CTRL interface for setting debug level
|
params.wpa_debug_level = MSG_ERROR;
|
||||||
params.wpa_debug_level = 1 ? MSG_DEBUG : MSG_INFO;
|
|
||||||
params.ctrl_interface = "GENODE";
|
params.ctrl_interface = "GENODE";
|
||||||
|
|
||||||
global = wpa_supplicant_init(¶ms);
|
global = wpa_supplicant_init(¶ms);
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
/* needed by wifi driver */
|
/* needed by wifi driver */
|
||||||
wpa_main;
|
wpa_main;
|
||||||
wpa_reporter_init;
|
wpa_reporter_init;
|
||||||
wpa_ctrl_set_fd;
|
*wpa_ctrl_set_fd*;
|
||||||
|
*ctrl_init*;
|
||||||
|
|
||||||
/* needed by wpa_driver_nl80211 */
|
/* needed by wpa_driver_nl80211 */
|
||||||
__hide_aliasing_typecast;
|
__hide_aliasing_typecast;
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<wifi connected_scan_interval="0" scan_interval="5" rfkill="no" verbose="no">
|
<wifi scan_interval="5" rfkill="no" verbose="no">
|
||||||
<network ssid="" protection="NONE" passphrase=""/>
|
<network ssid="" protection="NONE" passphrase=""/>
|
||||||
</wifi>
|
</wifi>
|
||||||
|
@ -141,7 +141,6 @@ struct Sculpt::Network : Noncopyable
|
|||||||
|
|
||||||
_wlan_config.generate([&] (Xml_generator &xml) {
|
_wlan_config.generate([&] (Xml_generator &xml) {
|
||||||
|
|
||||||
xml.attribute("connected_scan_interval", 0U);
|
|
||||||
xml.attribute("scan_interval", 10U);
|
xml.attribute("scan_interval", 10U);
|
||||||
xml.attribute("update_quality_interval", 30U);
|
xml.attribute("update_quality_interval", 30U);
|
||||||
|
|
||||||
@ -172,7 +171,6 @@ struct Sculpt::Network : Noncopyable
|
|||||||
|
|
||||||
_wlan_config.generate([&] (Xml_generator &xml) {
|
_wlan_config.generate([&] (Xml_generator &xml) {
|
||||||
|
|
||||||
xml.attribute("connected_scan_interval", 0U);
|
|
||||||
xml.attribute("scan_interval", 10U);
|
xml.attribute("scan_interval", 10U);
|
||||||
xml.attribute("update_quality_interval", 30U);
|
xml.attribute("update_quality_interval", 30U);
|
||||||
|
|
||||||
|
@ -30,29 +30,27 @@ proc wifi_wpa { } {
|
|||||||
# You may script your tests with this function in the dynamic_rom config below.
|
# You may script your tests with this function in the dynamic_rom config below.
|
||||||
# The syntax for the networks parameter is
|
# The syntax for the networks parameter is
|
||||||
#
|
#
|
||||||
# { ssid protection passphrase explicit_scan }
|
# { ssid protection passphrase auto_connect explicit_scan }
|
||||||
#
|
#
|
||||||
# Example dynamic_rom config:
|
# Example dynamic_rom config:
|
||||||
#
|
#
|
||||||
# {<inline description="auto-connect both networks">
|
# {<inline description="auto-connect both networks">
|
||||||
# } [wifi_config 30 5 no [list "net1 WPA2 net1_psk no" "net2 WPA2 net2_psk no"]] {
|
# } [wifi_config 5 no [list "net1 WPA2 net1_psk yes no" "net2 WPA2 net2_psk yes no"]] {
|
||||||
# </inline>
|
# </inline>
|
||||||
# <inline description="aquto-connect both, but net2 explicitly">
|
# <inline description="aquto-connect both, but net2 explicitly">
|
||||||
# } [wifi_config 30 5 no [list "net1 WPA2 net1_psk no" "net2 WPA2 net2_psk yes"]] {
|
# } [wifi_config 5 no [list "net1 WPA2 net1_psk yes no" "net2 WPA2 net2_psk yes yes"]] {
|
||||||
# </inline>}
|
# </inline>}
|
||||||
|
|
||||||
set wifi_verbose false
|
set wifi_verbose false
|
||||||
set wifi_verbose_state false
|
|
||||||
|
|
||||||
proc wifi_config { connected_scan_interval scan_interval rfkill networks } {
|
proc wifi_config { scan_interval update_quality_interval rfkill networks } {
|
||||||
global wifi_verbose
|
global wifi_verbose
|
||||||
global wifi_verbose_state
|
global wifi_verbose_state
|
||||||
|
|
||||||
set config "<wifi_config"
|
set config "<wifi_config"
|
||||||
append config " verbose=\"$wifi_verbose\""
|
append config " verbose=\"$wifi_verbose\""
|
||||||
append config " verbose_state=\"$wifi_verbose_state\""
|
|
||||||
append config " connected_scan_interval=\"$connected_scan_interval\""
|
|
||||||
append config " scan_interval=\"$scan_interval\""
|
append config " scan_interval=\"$scan_interval\""
|
||||||
|
append config " update_quality_interval=\"$update_quality_interval\""
|
||||||
append config " rfkill=\"$rfkill\""
|
append config " rfkill=\"$rfkill\""
|
||||||
append config ">\n"
|
append config ">\n"
|
||||||
foreach n $networks {
|
foreach n $networks {
|
||||||
@ -60,7 +58,8 @@ proc wifi_config { connected_scan_interval scan_interval rfkill networks } {
|
|||||||
append config " ssid=\"[lindex $n 0]\""
|
append config " ssid=\"[lindex $n 0]\""
|
||||||
append config " protection=\"[lindex $n 1]\""
|
append config " protection=\"[lindex $n 1]\""
|
||||||
append config " passphrase=\"[lindex $n 2]\""
|
append config " passphrase=\"[lindex $n 2]\""
|
||||||
append config " explicit_scan=\"[lindex $n 3]\""
|
append config " auto_connect=\"[lindex $n 3]\""
|
||||||
|
append config " explicit_scan=\"[lindex $n 4]\""
|
||||||
append config "/>\n"
|
append config "/>\n"
|
||||||
}
|
}
|
||||||
append config "</wifi_config>\n"
|
append config "</wifi_config>\n"
|
||||||
@ -236,19 +235,19 @@ append config {
|
|||||||
<config verbose="yes">
|
<config verbose="yes">
|
||||||
<rom name="wifi_config">
|
<rom name="wifi_config">
|
||||||
<inline description="disconnect">
|
<inline description="disconnect">
|
||||||
} [wifi_config 30 5 no {}] {
|
} [wifi_config 5 10 no {}] {
|
||||||
</inline>
|
</inline>
|
||||||
<sleep milliseconds="15000"/>
|
<sleep milliseconds="15000"/>
|
||||||
<inline description="connect">
|
<inline description="connect">
|
||||||
} [wifi_config 30 5 no [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes"]] {
|
} [wifi_config 5 10 no [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes no "]] {
|
||||||
</inline>
|
</inline>
|
||||||
<sleep milliseconds="60000"/>
|
<sleep milliseconds="60000"/>
|
||||||
<inline description="rfkill block">
|
<inline description="rfkill block">
|
||||||
} [wifi_config 30 5 yes [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes"]] {
|
} [wifi_config 5 10 yes [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes no "]] {
|
||||||
</inline>
|
</inline>
|
||||||
<sleep milliseconds="30000"/>
|
<sleep milliseconds="30000"/>
|
||||||
<inline description="rfkill unblock">
|
<inline description="rfkill unblock">
|
||||||
} [wifi_config 30 5 no [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes"]] {
|
} [wifi_config 5 10 no [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes no "]] {
|
||||||
</inline>
|
</inline>
|
||||||
<sleep milliseconds="30000"/>
|
<sleep milliseconds="30000"/>
|
||||||
</rom>
|
</rom>
|
||||||
@ -327,7 +326,7 @@ install_config $config
|
|||||||
# boot-module assembly
|
# boot-module assembly
|
||||||
#
|
#
|
||||||
if {$debug_driver} {
|
if {$debug_driver} {
|
||||||
exec rm bin/wifi.lib.so
|
catch {exec rm bin/wifi.lib.so}
|
||||||
exec echo dummy > bin/wifi.lib.so
|
exec echo dummy > bin/wifi.lib.so
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,8 +244,8 @@ if { $use_wifi_driver } {
|
|||||||
<ram/>
|
<ram/>
|
||||||
<import>
|
<import>
|
||||||
<inline name="wifi_config">
|
<inline name="wifi_config">
|
||||||
<wifi_config connected_scan_interval="0" scan_interval="10" rfkill="no" verbose="no" verbose_state="no">}
|
<wifi_config>}
|
||||||
append config "<network ssid=\"$wifi_ssid\" protection=\"WPA2\" passphrase=\"$wifi_psk\"/>"
|
append config "<network ssid=\"$wifi_ssid\" protection=\"WPA2\" passphrase=\"$wifi_psk\" auto_connect=\"true\"/>"
|
||||||
append config { </wifi_config>
|
append config { </wifi_config>
|
||||||
</inline>
|
</inline>
|
||||||
</import>
|
</import>
|
||||||
|
Loading…
Reference in New Issue
Block a user