wifi_drv: enable soft RFKILL and new front end

* TODO
This commit is contained in:
Josef Söntgen 2018-07-04 17:13:16 +02:00 committed by Christian Helmuth
parent 4a47b7cb41
commit ec9e8ecfaa
35 changed files with 2545 additions and 669 deletions

View File

@ -0,0 +1,45 @@
/*
* \brief Wpa_supplicant CTRL interface
* \author Josef Soentgen
* \date 2018-07-31
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _WIFI__CTRL_H_
#define _WIFI__CTRL_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define WPA_CTRL_FD 51
struct Msg_buffer
{
unsigned char recv[4096];
unsigned char send[1024];
unsigned recv_id;
unsigned send_id;
unsigned char event[1024];
unsigned event_id;
} __attribute__((packed));
void wpa_ctrl_set_fd(void);
void *wifi_get_buffer(void);
void wifi_notify_cmd_result(void);
void wifi_notify_event(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _WIFI__CTRL_H_ */

View File

@ -0,0 +1,26 @@
/*
* \brief RFKILL interface
* \author Josef Soentgen
* \date 2018-07-11
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _WIFI__RFKILL_H_
#define _WIFI__RFKILL_H_
namespace Wifi {
enum { RFKILL_FD = 42, };
}
bool wifi_get_rfkill(void);
void wifi_set_rfkill(bool);
#endif /* _WIFI__RFKILL_H_ */

View File

@ -8,6 +8,7 @@ SHARED_LIB = yes
LD_OPT += --version-script=$(LIB_DIR)/symbol.map
SRC_CC += dummies.cc ioctl.cc
SRC_CC += rfkill_genode.cc
WS_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/app/wpa_supplicant
@ -22,8 +23,8 @@ SRC_C_drivers = drivers.c \
driver_nl80211_event.c \
driver_nl80211_monitor.c \
driver_nl80211_scan.c \
netlink.c \
rfkill.c
netlink.c
SRC_C += $(addprefix src/drivers/, $(SRC_C_drivers))
INC_DIR += $(WS_CONTRIB_DIR)/src/drivers \
$(WS_CONTRIB_DIR)/src/utils \

View File

@ -11,10 +11,13 @@ CC_OPT += -Wno-unused-function
CC_CXX_OPT += -fpermissive
SRC_C += main.c ctrl_iface_genode.c
SRC_CC += reporter.cc
INC_DIR += $(REP_DIR)/include
# wpa_supplicant
SRC_C_wpa_supplicant = blacklist.c \
bgscan.c \
bgscan_simple.c \
bss.c \
config.c \
config_file.c \
@ -32,7 +35,8 @@ SRC_C_wpa_supplicant = blacklist.c \
SRC_C += $(addprefix wpa_supplicant/, $(SRC_C_wpa_supplicant))
INC_DIR += $(WS_CONTRIB_DIR)/wpa_supplicant
CC_OPT += -DCONFIG_BACKEND_FILE -DCONFIG_NO_CONFIG_WRITE \
-DCONFIG_SME -DCONFIG_CTRL_IFACE
-DCONFIG_SME -DCONFIG_CTRL_IFACE \
-DCONFIG_BGSCAN -DCONFIG_BGSCAN_SIMPLE
CC_OPT += -DTLS_DEFAULT_CIPHERS=\"DEFAULT:!EXP:!LOW\"

View File

@ -53,7 +53,7 @@ CC_OPT += -DCONFIG_MAC80211_MESH
CC_OPT += -DCONFIG_PM -DCONFIG_PM_SLEEP
# rfkill
CC_OPT += -DCONFIG_RFKILL
CC_OPT += -DCONFIG_RFKILL -DCONFIG_RFKILL_INPUT
# choose default pid algorithm
CC_OPT += -DCONFIG_MAC80211_RC_PID -DCONFIG_MAC80211_RC_DEFAULT=\"pid\"

View File

@ -80,6 +80,19 @@ index 7152fdc..5d133e5 100644
.configure_filter = iwl_mvm_configure_filter,
.config_iface_filter = iwl_mvm_config_iface_filter,
.bss_info_changed = iwl_mvm_bss_info_changed,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5d133e5..ec770d4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1573,7 +1573,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(!mvm->mcast_filter_cmd))
+ if (!mvm->mcast_filter_cmd)
return;
ieee80211_iterate_active_interfaces_atomic(
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index f25ce3a..85007fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@ -106,27 +119,28 @@ index 99df171..4632cdf 100644
}
delta = remcsum_adjust(ptr, skb->csum, start, offset);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 1fdcde9..5f221bd 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -97,9 +97,13 @@ void rtnetlink_init(void);
void __rtnl_unlock(void);
void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail);
+#if 1
+#define ASSERT_RTNL()
+# else
#define ASSERT_RTNL() \
WARN_ONCE(!rtnl_is_locked(), \
"RTNL: assertion failed at %s (%d)\n", __FILE__, __LINE__)
+#endif
extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index e0f3f4a..a309257 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3977,6 +3977,8 @@ static int packet_notifier(struct notifier_block *this,
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct net *net = dev_net(dev);
+// XXX check if still needed
+#if 0
rcu_read_lock();
sk_for_each_rcu(sk, &net->packet.sklist) {
struct packet_sock *po = pkt_sk(sk);
@@ -4017,6 +4019,7 @@ static int packet_notifier(struct notifier_block *this,
}
}
rcu_read_unlock();
+#endif
return NOTIFY_DONE;
}
@@ -4544,8 +4547,10 @@ static int __net_init packet_net_init(struct net *net)
mutex_init(&net->packet.sklist_lock);
INIT_HLIST_HEAD(&net->packet.sklist);

View File

@ -0,0 +1,22 @@
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -911,6 +911,19 @@ bool rfkill_blocked(struct rfkill *rfkill)
}
EXPORT_SYMBOL(rfkill_blocked);
+bool rfkill_get_any(enum rfkill_type type)
+{
+ bool blocked = false;
+
+ struct rfkill *rfkill;
+ list_for_each_entry(rfkill, &rfkill_list, node) {
+ if (rfkill->type != type && type != RFKILL_TYPE_ALL)
+ continue;
+
+ blocked |= rfkill_blocked(rfkill);
+ }
+ return blocked;
+}
struct rfkill * __must_check rfkill_alloc(const char *name,
struct device *parent,

View File

@ -1,7 +1,41 @@
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5cff47fab..5cba03efe 100644
index 5cff47fab..af08177b2 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1682,13 +1682,13 @@ static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
{
struct wpa_driver_nl80211_data *drv = ctx;
- wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
+ wpa_printf(MSG_INFO, "nl80211: RFKILL blocked");
/*
* rtnetlink ifdown handler will report interfaces other than the P2P
* Device interface as disabled.
*/
- if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ // if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
}
@@ -1696,7 +1696,7 @@ static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
{
struct wpa_driver_nl80211_data *drv = ctx;
- wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
+ wpa_printf(MSG_INFO, "nl80211: RFKILL unblocked");
if (i802_set_iface_flags(drv->first_bss, 1)) {
wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
"after rfkill unblock");
@@ -1710,7 +1710,7 @@ static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
* rtnetlink ifup handler will report interfaces other than the P2P
* Device interface as enabled.
*/
- if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ // if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
}
@@ -7645,7 +7645,7 @@ static void * nl80211_global_init(void *ctx)
if (wpa_driver_nl80211_init_nl_global(global) < 0)
goto err;
@ -24,8 +58,30 @@ index 0e960f48c..38fb26c18 100644
struct netlink_data {
struct netlink_config *cfg;
diff --git a/src/utils/common.c b/src/utils/common.c
index 1eb33705b..e4447306a 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -498,12 +498,12 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
*txt++ = 't';
break;
default:
- if (data[i] >= 32 && data[i] <= 126) {
+ // if (data[i] >= 32 && data[i] <= 126) {
*txt++ = data[i];
- } else {
- txt += os_snprintf(txt, end - txt, "\\x%02x",
- data[i]);
- }
+ // } else {
+ // txt += os_snprintf(txt, end - txt, "\\x%02x",
+ // data[i]);
+ // }
break;
}
}
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 436bc8c99..fd72eaef3 100644
index 436bc8c99..f5ff4facb 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -28,7 +28,7 @@
@ -37,75 +93,3 @@ index 436bc8c99..fd72eaef3 100644
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_EPOLL
@@ -961,7 +961,7 @@ static void eloop_handle_alarm(int sig)
#endif /* CONFIG_NATIVE_WINDOWS */
-static void eloop_handle_signal(int sig)
+void eloop_handle_signal(int sig)
{
int i;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index fb77f1dbd..9142f3f1b 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1754,6 +1754,9 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
}
+extern void wpa_report_scan_results(struct wpa_supplicant *);
+
+
/*
* Return a negative value if no scan results could be fetched or if scan
* results should not be shared with other virtual interfaces.
@@ -1799,6 +1802,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
goto scan_work_done;
}
+ wpa_report_scan_results(wpa_s);
+
#ifndef CONFIG_NO_RANDOM_POOL
num = scan_res->num;
if (num > 10)
@@ -2813,6 +2818,9 @@ static int disconnect_reason_recoverable(u16 reason_code)
}
+void wpa_report_disconnect_event(struct wpa_supplicant *);
+
+
static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
u16 reason_code,
int locally_generated)
@@ -2834,6 +2842,7 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
if (!is_zero_ether_addr(bssid) ||
wpa_s->wpa_state >= WPA_AUTHENTICATING) {
+ wpa_report_disconnect_event(wpa_s);
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
" reason=%d%s",
MAC2STR(bssid), reason_code,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 185a8d50f..4baedabb3 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -822,6 +822,9 @@ void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
}
+void wpa_report_connect_event(struct wpa_supplicant *);
+
+
/**
* wpa_supplicant_set_state - Set current connection state
* @wpa_s: Pointer to wpa_supplicant data
@@ -879,6 +882,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
if (state == WPA_COMPLETED && wpa_s->new_connection) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
+ wpa_report_connect_event(wpa_s);
int fils_hlp_sent = 0;
#ifdef CONFIG_SME

View File

@ -1 +1 @@
d2628a8fe8df14dd00d5fa8ef6bbea527d319bee
f8b3fc722728da35627dcd064209debe9e6aed92

View File

@ -129,6 +129,7 @@ PATCH_OPT(patches/lxip_skbuff_cast.patch) := $(LXIP_OPT)
WIFI_OPT = -p1 -d$(SRC_DIR_WIFI)
PATCH_OPT(patches/wifi.patch) := $(WIFI_OPT)
PATCH_OPT(patches/wifi_mem.patch) := $(WIFI_OPT)
PATCH_OPT(patches/wifi_rfkill.patch) := $(WIFI_OPT)
# libnl
PATCH_OPT(patches/libnl.patch) := -p1 -d ${DIR(libnl)}

View File

@ -1,17 +1,16 @@
<runtime ram="54M" caps="300" binary="wifi_drv">
<runtime ram="32M" caps="300" binary="wifi_drv">
<requires> <rom label="wlan_configuration"/> </requires>
<requires> <rom label="wifi_config"/> </requires>
<provides> <nic/> </provides>
<config ld_verbose="yes" verbose="yes" use_11n="no" connected_scan_interval="0">
<config ld_verbose="yes" verbose="no">
<vfs>
<dir name="dev"> <log/> <rtc/> <null/>
<jitterentropy name="random"/>
<jitterentropy name="urandom"/>
</dir>
<dir name="config"> <ram/> </dir>
</vfs>
<libc stdout="/dev/null" stderr="/dev/log" rtc="/dev/rtc"/>
<libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
</config>
<content>

View File

@ -1,23 +1,36 @@
#
# Configure wireless lan
#
proc wifi_ssid { } {
return $::env(GENODE_WIFI_SSID)
}
proc wifi_psk { } {
return $::env(GENODE_WIFI_PSK)
}
#
# Restrict platforms
#
assert_spec x86
#
# Build
#
set build_components {
core init
drivers/timer drivers/wifi
drivers/rtc
drivers/timer
drivers/wifi
server/report_rom
server/dynamic_rom
test/lwip/http_srv
lib/vfs/jitterentropy
lib/vfs/lwip
}
proc gpio_drv { } { if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv }
if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv }
return gpio_drv }
lappend_if [have_spec gpio] build_components drivers/gpio
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
@ -29,7 +42,7 @@ create_boot_directory
# Generate config
#
set config {
append config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
@ -49,69 +62,85 @@ set config {
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="rtc_drv">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Rtc"/> </provides>
</start>
<start name="test-lwip_httpsrv">
<resource name="RAM" quantum="5M"/>
<resource name="RAM" quantum="16M"/>
<config>
<libc stdout="/dev/log" stderr="/dev/log">
<vfs> <dir name="dev"> <log/> </dir> </vfs>
</libc>
<libc stdout="/dev/null" stderr="/dev/log" socket="/socket"/>
<vfs>
<dir name="dev"> <log/> <null/> </dir>
<dir name="socket"> <lwip dhcp="yes"/> </dir>
</vfs>
</config>
</start>
<start name="report_rom">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config/>
<config verbose="no"/>
</start>
<start name="config_rom">
<binary name="dynamic_rom"/>
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/></provides>
<config verbose="yes">
<rom name="wlan_configuration">
<inline description="DISCONNECT"> <selected_network/> </inline>
<sleep milliseconds="10000"/> <!-- 10 seconds -->
<inline description="CONNECT">}
append config "<selected_network ssid=\"$::env(GENODE_WIFI_SSID)\" protection=\"WPA-PSK\" psk=\"$::env(GENODE_WIFI_PSK)\"/>"
append config {
<rom name="wifi_config">
<inline description="connect">
<wifi_config connected_scan_interval="30" scan_interval="5" rfkill="no" verbose="yes">
<accesspoint ssid="} [wifi_ssid] {" protection="WPA2" passphrase="} [wifi_psk] {"/>
</wifi_config>
</inline>
<sleep milliseconds="300000"/> <!-- 5 minutes -->
<sleep milliseconds="60000"/>
<inline description="rfkill block">
<wifi_config connected_scan_interval="30" scan_interval="5" rfkill="yes" verbose="yes">
<accesspoint ssid="} [wifi_ssid] {" protection="WPA2" passphrase="} [wifi_psk] {"/>
</wifi_config>
</inline>
<sleep milliseconds="30000"/>
<inline description="rfkill unblock">
<wifi_config connected_scan_interval="30" scan_interval="5" rfkill="no" verbose="yes">
<accesspoint ssid="} [wifi_ssid] {" protection="WPA2" passphrase="} [wifi_psk] {"/>
</wifi_config>
</inline>
<sleep milliseconds="30000"/>
<inline description="disconnect">
<wifi_config connected_scan_interval="30" scan_interval="5" rfkill="no" verbose="yes">
<accesspoint ssid="} [wifi_ssid] {" protection="WPA2" passphrase="} [wifi_psk] {"/>
</wifi_config>
</inline>
<sleep milliseconds="60000"/>
</rom>
</config>
</start>
<start name="wifi_drv" caps="220">
<resource name="RAM" quantum="32M"/>
<start name="wifi_drv" caps="200">
<resource name="RAM" quantum="24M"/>
<provides> <service name="Nic"/> </provides>
<config ld_verbose="yes" verbose="yes" connected_scan_interval="30">
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
<config ld_verbose="yes">
<libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
<vfs>
<dir name="dev"> <log/> <rtc/>
<dir name="dev"> <log/> <null/> <rtc/>
<jitterentropy name="random"/>
<jitterentropy name="urandom"/>
</dir>
<dir name="config"> <ram/> </dir>
</vfs>
</config>
<route>
<service name="Rtc"> <any-child/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="ROM" label="wlan_configuration"> <child name="config_rom"/> </service>
<service name="ROM" label="wifi_config"> <child name="config_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>}
append_platform_drv_config
append_if [have_spec gpio] config "
<start name=\"[gpio_drv]\">
<resource name=\"RAM\" quantum=\"4M\"/>
<provides><service name=\"Gpio\"/></provides>
<config/>
</start>"
append config {
</config>
}
@ -137,19 +166,18 @@ set firmware_modules {
# generic modules
set boot_modules {
core ld.lib.so init timer rtc_drv report_rom dynamic_rom
vfs_jitterentropy.lib.so posix.lib.so
libc.lib.so vfs.lib.so libm.lib.so libcrypto.lib.so libssl.lib.so
vfs_jitterentropy.lib.so
libc.lib.so vfs.lib.so libcrypto.lib.so libssl.lib.so
wpa_driver_nl80211.lib.so wpa_supplicant.lib.so
wifi.lib.so
wifi_drv
test-lwip_httpsrv lwip_legacy.lib.so
test-lwip_httpsrv
vfs_lwip.lib.so
}
append boot_modules $firmware_modules
lappend_if [have_spec gpio] boot_modules [gpio_drv]
append_platform_drv_boot_modules
build_boot_image $boot_modules

File diff suppressed because it is too large Load Diff

View File

@ -13,247 +13,104 @@
/* Genode includes */
#include <libc/component.h>
#include <base/heap.h>
#include <base/attached_rom_dataspace.h>
#include <base/log.h>
#include <base/sleep.h>
#include <base/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <timer_session/connection.h>
#include <util/xml_node.h>
#include <util/string.h>
/* local includes */
#include "wpa.h"
typedef long long ssize_t;
extern void wifi_init(Genode::Env&, Genode::Lock&, bool);
extern "C" void wpa_conf_reload(void);
extern "C" ssize_t wpa_write_conf(char const *, Genode::size_t);
static Genode::Lock &wpa_startup_lock()
{
static Genode::Lock _l(Genode::Lock::LOCKED);
return _l;
}
#include <util.h>
#include <wpa.h>
#include <frontend.h>
namespace {
template <Genode::size_t CAPACITY>
class Buffer
{
private:
char _data[CAPACITY] { 0 };
Genode::size_t _length { 0 };
public:
void reset() { _data[0] = 0; _length = 0; }
char const *data() const { return _data; }
Genode::size_t length() const { return _length; }
void append(char const *format, ...)
{
va_list list;
va_start(list, format);
Genode::String_console sc(_data + _length, CAPACITY - _length);
sc.vprintf(format, list);
va_end(list);
_length += sc.len();
}
};
} /* anonymous namespace */
static Wifi::Frontend *_wifi_frontend = nullptr;
/**
* Generate wpa_supplicant.conf file
* Notify front end about command processing
*
* Called by the CTRL interface after wpa_supplicant has processed
* the command.
*/
static int generatewpa_supplicant_conf(char const **p, Genode::size_t *len, char const *ssid,
char const *bssid, bool protection = false, char const *psk = 0)
void wifi_notify_cmd_result(void)
{
static char const *start_fmt = "network={\n\tscan_ssid=1\n";
static char const *ssid_fmt = "\tssid=\"%s\"\n";
static char const *bssid_fmt = "\tbssid=%s\n";
static char const *prot_fmt = "\tkey_mgmt=%s\n";
static char const *psk_fmt = "\tpsk=\"%s\"\n";
static char const *end_fmt = "}\n";
if (!_wifi_frontend) {
Genode::warning("frontend not available, dropping notification");
return;
}
static Buffer<256> buffer;
buffer.reset();
/*
* Next time we block as long as the front end has not finished
* handling our previous request
*/
_wifi_frontend->block_for_processing();
buffer.append(start_fmt);
/* XXX hack to trick poll() into returning faster */
wpa_ctrl_set_fd();
if (ssid)
buffer.append(ssid_fmt, ssid);
if (bssid)
buffer.append(bssid_fmt, bssid);
if (protection)
buffer.append(psk_fmt, psk);
buffer.append(prot_fmt, protection ? "WPA-PSK" : "NONE");
buffer.append(end_fmt);
*p = buffer.data();
*len = buffer.length();
return 0;
Genode::Signal_transmitter(_wifi_frontend->result_sigh()).submit();
}
struct Wlan_configration
/**
* Notify front end about triggered event
*
* Called by the CTRL interface whenever wpa_supplicant has triggered
* a event.
*/
void wifi_notify_event(void)
{
Genode::Attached_rom_dataspace config_rom;
Genode::Signal_handler<Wlan_configration> dispatcher;
Genode::Lock update_lock;
char const *buffer;
Genode::size_t size;
/**
* Write configuration buffer to conf file to activate the new configuration.
*/
void _activate_configuration()
{
if (wpa_write_conf(buffer, size) == 0) {
Genode::log("Reload wpa_supplicant configuration");
wpa_conf_reload();
}
}
/**
* Write dummy configuration buffer to conf file to activate the new
* configuration.
*/
void _active_dummy_configuration()
{
generatewpa_supplicant_conf(&buffer, &size, "dummyssid", "00:00:00:00:00:00");
_activate_configuration();
}
/**
* Update the conf file used by the wpa_supplicant.
*/
void _update_configuration()
{
using namespace Genode;
Lock::Guard guard(update_lock);
config_rom.update();
/**
* We generate a dummy configuration because there is no valid
* configuration yet to fool wpa_supplicant to keep it scanning
* for the non exisiting network.
*/
if (!config_rom.valid()) {
_active_dummy_configuration();
if (!_wifi_frontend) {
Genode::warning("frontend not available, dropping notification");
return;
}
Xml_node node(config_rom.local_addr<char>(), config_rom.size());
Genode::Signal_transmitter(_wifi_frontend->event_sigh()).submit();
}
/**
* Since <selected_accesspoint/> is empty or missing an ssid attribute
* we also generate a dummy configuration.
/**
* Return shared-memory message buffer
*
* It is used by the wpa_supplicant CTRL interface.
*/
if (!node.has_attribute("ssid")) {
_active_dummy_configuration();
return;
}
void *wifi_get_buffer(void)
{
return _wifi_frontend ? &_wifi_frontend->msg_buffer() : nullptr;
}
/**
* Try to generate a valid configuration.
*/
enum { MAX_SSID_LENGTH = 32 + 1,
BSSID_LENGTH = 12 + 5 + 1,
PROT_LENGTH = 7 + 1,
MIN_PSK_LENGTH = 8 + 1,
MAX_PSK_LENGTH = 63 + 1};
String<MAX_SSID_LENGTH> ssid;
node.attribute("ssid").value(&ssid);
bool use_bssid = node.has_attribute("bssid");
String<BSSID_LENGTH> bssid;
if (use_bssid)
node.attribute("bssid").value(&bssid);
bool use_protection = false;
if (node.has_attribute("protection")) {
String<PROT_LENGTH> prot;
node.attribute("protection").value(&prot);
use_protection = (prot == "WPA-PSK");
}
String<MAX_PSK_LENGTH> psk;
if (use_protection && node.has_attribute("psk"))
node.attribute("psk").value(&psk);
/* psk must be between 8 and 63 characters long */
if (use_protection && (psk.length() < MIN_PSK_LENGTH)) {
Genode::error("given pre-shared key is too short");
_active_dummy_configuration();
return;
}
if (generatewpa_supplicant_conf(&buffer, &size, ssid.string(),
use_bssid ? bssid.string() : 0,
use_protection, psk.string()) == 0)
_activate_configuration();
}
void _handle_update()
{
Libc::with_libc([&] () { _update_configuration(); });
}
Wlan_configration(Genode::Env &env)
:
config_rom(env, "wlan_configuration"),
dispatcher(env.ep(), *this, &Wlan_configration::_handle_update)
{
config_rom.sigh(dispatcher);
_update_configuration();
}
};
/* exported by wifi.lib.so */
extern void wifi_init(Genode::Env&, Genode::Lock&, bool, Genode::Signal_context_capability);
struct Main
{
Genode::Env &env;
Genode::Heap heap { env.ram(), env.rm() };
Genode::Attached_rom_dataspace config_rom { env, "config" };
Genode::Constructible<Wpa_thread> _wpa;
Genode::Constructible<Wifi::Frontend> _frontend;
Wpa_thread *wpa;
Wlan_configration *wlan_config;
Genode::Lock _wpa_startup_lock { Genode::Lock::LOCKED };
Main(Genode::Env &env) : env(env)
{
bool const verbose = config_rom.xml().attribute_value("verbose", false);
long const interval = config_rom.xml().attribute_value("connected_scan_interval", 0L);
_frontend.construct(env);
_wifi_frontend = &*_frontend;
_wpa.construct(env, _wpa_startup_lock);
_wpa->start();
/*
* Forcefully disable 11n but for convenience the attribute is used the
* other way araound.
*/
bool const disable_11n = !config_rom.xml().attribute_value("use_11n", true);
wpa = new (&heap) Wpa_thread(env, wpa_startup_lock(), verbose, interval);
wpa->start();
try {
wlan_config = new (&heap) Wlan_configration(env);
} catch (...) {
Genode::warning("could not create Wlan_configration handler");
}
wifi_init(env, wpa_startup_lock(), disable_11n);
bool const disable_11n = !_frontend->use_11n();
wifi_init(env, _wpa_startup_lock, disable_11n,
_frontend->rfkill_sigh());
}
};

View File

@ -7,5 +7,6 @@ LIBS += wpa_supplicant
# needed for firmware.h
INC_DIR += $(REP_DIR)/src/lib/wifi/include
INC_DIR += $(PRG_DIR)
CC_CXX_WARN_STRICT =

View File

@ -0,0 +1,90 @@
/*
* \brief Wifi front end utilities
* \author Josef Soentgen
* \date 2018-07-23
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _WIFI__UTIL_H_
#define _WIFI__UTIL_H_
/* Genode includes */
#include <util/string.h>
typedef unsigned long size_t;
typedef long long ssize_t;
typedef unsigned char uint8_t;
namespace Util {
using size_t = Genode::size_t;
using uint8_t = Genode::uint8_t;
size_t next_char(char const *s, size_t start, char const c)
{
size_t v = start;
while (s[v]) {
if (s[v] == c) { break; }
v++;
}
return v - start;
}
bool string_contains(char const *str, char const *pattern)
{
char const *p = pattern;
while (*str && *p) {
p = *str == *p ? p + 1 : pattern;
str++;
}
return !*p;
}
void byte2hex(char *dest, uint8_t b)
{
int i = 1;
if (b < 16) { dest[i--] = '0'; }
for (; b > 0; b /= 16) {
uint8_t const v = b % 16;
uint8_t const c = (v > 9) ? v + 'a' - 10 : v + '0';
dest[i--] = (char)c;
}
}
/**********************************
** Front end specific utilities **
**********************************/
inline unsigned approximate_quality(char const *str)
{
long level = 0;
Genode::ascii_to(str, level);
/*
* We provide an quality value by transforming the actual
* signal level [-50,-100] (dBm) to [100,0] (%).
*/
if (level <= -100) { return 0; }
else if (level >= -50) { return 100; }
return 2 * (level + 100);
}
inline unsigned check_time(unsigned value, unsigned min, unsigned max)
{
if (value < min) { return min; }
else if (value > max) { return max; }
return value;
}
} /* namespace Util */
#endif /* _WIFI__UTIL_H_ */

View File

@ -18,9 +18,7 @@
#include <base/sleep.h>
/* entry function */
extern "C" int wpa_main(int debug_msg, int connected_scan_interval);
extern "C" void wpa_reporter_init(void *env);
extern "C" void wpa_conf_reload(void);
extern "C" int wpa_main(void);
class Wpa_thread : public Genode::Thread
{
@ -28,26 +26,20 @@ class Wpa_thread : public Genode::Thread
Genode::Lock &_lock;
int _exit;
bool _debug_msg;
int _connected_scan_interval;
public:
Wpa_thread(Genode::Env &env, Genode::Lock &lock,
bool debug_msg, int connected_scan_interval)
Wpa_thread(Genode::Env &env, Genode::Lock &lock)
:
Thread(env, "wpa_supplicant", 8*1024*sizeof(long)),
_lock(lock), _exit(-1),
_debug_msg(debug_msg), _connected_scan_interval(connected_scan_interval)
{
wpa_reporter_init(&env);
}
_lock(lock), _exit(-1)
{ }
void entry()
{
/* wait until the wifi driver is up and running */
_lock.lock();
_exit = wpa_main(_debug_msg, _connected_scan_interval);
_exit = wpa_main();
Genode::sleep_forever();
}
};

View File

@ -72,9 +72,9 @@ class Socket_registry
{
private :
/* abritary value (it goes to eleven!) */
enum {
SOCKETS_INITIAL_VALUE = 11,
/* lower FDs might be special */
SOCKETS_OFFSET_VALUE = 100,
MAX_SOCKETS = 7,
};
@ -99,7 +99,7 @@ class Socket_registry
if (sfd.s != nullptr) { return false; }
sfd.s = s;
sfd.fd = ++_sockets;
sfd.fd = (++_sockets & 0xff) + SOCKETS_OFFSET_VALUE;
/* return fd */
fd = sfd.fd;
@ -144,7 +144,7 @@ class Socket_registry
};
Socket_fd Socket_registry::_socket_fd[MAX_SOCKETS] = {};
unsigned Socket_registry::_sockets = Socket_registry::SOCKETS_INITIAL_VALUE;
unsigned Socket_registry::_sockets = 0;
extern "C" {
@ -480,10 +480,36 @@ int fcntl(int fd, int cmd, ... /* arg */ )
** sys/poll.h **
****************/
static bool _ctrl_fd_set = false;
extern "C" void nl_set_wpa_ctrl_fd()
{
_ctrl_fd_set = true;
}
static bool special_fd(int fd)
{
/*
* This range is used by the CTRL and RFKILL fds.
*/
return (fd > 40 && fd < 60);
}
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
Poll_socket_fd sockets[Wifi::MAX_POLL_SOCKETS];
unsigned num = 0;
int nready = 0;
/* handle special FDs first */
for (nfds_t i = 0; i < nfds; i++) {
if (!special_fd(fds[i].fd)) { continue; }
fds[i].revents = 0;
fds[i].revents |= POLLIN;
nready++;
}
for (nfds_t i = 0; i < nfds; i++) {
Socket *s = Socket_registry::find(fds[i].fd);
@ -504,11 +530,16 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
num++;
}
int nready = socket_call.poll_all(sockets, num, timeout);
if (!nready)
return 0;
if (nready < 0)
return -1;
/* make sure we do not block in poll_all */
if (_ctrl_fd_set) {
_ctrl_fd_set = false;
timeout = 0;
}
int sready = socket_call.poll_all(sockets, num, timeout);
if (sready < 0 || sready == 0) { return nready; }
nready += sready;
for (unsigned i = 0; i < num; i++) {
int revents = sockets[i].revents;

View File

@ -132,18 +132,18 @@ DUMMY_SKIP(0, in_irq) /* XXX */
DUMMY_SKIP(0, local_bh_disable)
DUMMY_SKIP(0, local_bh_enable)
DUMMY_SKIP(0, dma_unmap_page)
DUMMY_SKIP(0, dma_set_coherent_mask) /* we set the mask always to ~0UL */
DUMMY_SKIP(0, dma_set_mask) /* in the PCI driver */
DUMMY(-1, dma_sync_single_for_cpu)
DUMMY(-1, dma_sync_single_for_device)
/* XXX DUMMY_SKIP safe? */
DUMMY_SKIP(0, dma_sync_single_for_cpu)
DUMMY_SKIP(0, dma_sync_single_for_device)
/*
* There is no actual mapping going on as the memory is always
* allocated from the DMA backend. It is safe to _not_ implement
* the unmap functions.
*/
DUMMY_SKIP(0, dma_unmap_page)
DUMMY_SKIP(0, dma_unmap_single)
DUMMY_SKIP(0, kunmap)
DUMMY_SKIP(0, kunmap_atomic)
DUMMY_SKIP(-1, dump_stack)
DUMMY_SKIP(-1, gfp_pfmemalloc_allowed)
@ -189,9 +189,6 @@ DUMMY(0, device_rename)
DUMMY(0, device_unregister)
DUMMY(0, do_posix_clock_monotonic_gettime)
DUMMY(0, do_softirq)
DUMMY(0, flush_delayed_work)
DUMMY(0, flush_work)
DUMMY(0, flush_workqueue)
DUMMY(0, genl_dump_check_consistent)
DUMMY(0, genl_info_net)
DUMMY(0, genlmsg_cancel)
@ -370,9 +367,8 @@ DUMMY(0, __hw_addr_sync)
DUMMY(0, __hw_addr_unsync)
DUMMY_SKIP(0, dev_alloc_name)
DUMMY(0, dev_change_net_namespace)
DUMMY(0, dev_close)
DUMMY(0, dev_kfree_skb_any)
DUMMY_SKIP(0, dev_net_set)
DUMMY(0, dev_net_set)
DUMMY(0, dev_open)
DUMMY_SKIP(0, dev_hold)
DUMMY_SKIP(0, dev_put)
@ -406,7 +402,6 @@ DUMMY(0, request_firmware)
DUMMY(0, tcp_v4_check)
DUMMY(0, sk_attach_filter)
DUMMY(0, __class_create)
DUMMY(0, __module_get)
DUMMY(0, __sock_recv_timestamp)
DUMMY(0, __sock_recv_wifi_status)
@ -449,12 +444,6 @@ DUMMY(0, regulator_enable)
DUMMY(0, regulator_get_exclusive)
DUMMY(0, regulator_is_enabled)
DUMMY(0, regulator_put)
DUMMY(0, rfkill_epo)
DUMMY(0, rfkill_get_global_sw_state)
DUMMY(0, rfkill_is_epo_lock_active)
DUMMY(0, rfkill_remove_epo_lock)
DUMMY(0, rfkill_restore_states)
DUMMY(0, rfkill_switch_all)
DUMMY(0, send_sigurg)
DUMMY(0, simple_strtoul)
DUMMY(0, skb_gro_len)
@ -533,7 +522,6 @@ DUMMY(0, release_pages)
DUMMY(0, sk_busy_loop)
DUMMY(0, sk_can_busy_loop)
// DUMMY_SKIP(0, complete_all)
DUMMY_SKIP(0, simple_strtol)
DUMMY_SKIP(0, alg_test)
@ -550,7 +538,6 @@ DUMMY(0, config_enabled)
DUMMY(0, dev_change_proto_down)
DUMMY(0, dev_get_iflink)
DUMMY(0, dev_get_phys_port_name)
DUMMY(-1, device_create_with_groups)
DUMMY(0, device_enable_async_suspend)
DUMMY(0, fatal_signal_pending)
DUMMY_RET(1, file_ns_capable)
@ -586,7 +573,7 @@ DUMMY(0, netif_xmit_frozen_or_drv_stopped)
DUMMY(0, netif_xmit_frozen_or_stopped)
DUMMY_STOP(0, netif_rx_ni)
DUMMY_STOP(0, netif_tx_start_all_queues)
DUMMY_STOP(0, netif_tx_stop_all_queues)
DUMMY(0, netif_tx_stop_all_queues)
DUMMY(0, peernet_has_id)
DUMMY(0, peernet2id_alloc)

View File

@ -14,7 +14,7 @@
/* local includes */
#include <lx_emul.h>
#if 1
#if 0
#define TRACE \
do { \
lx_printf("%s not implemented from: %p\n", __func__, \
@ -141,12 +141,6 @@ unsigned int memalloc_noreclaim_save(void)
}
u64 ktime_get_ns(void)
{
TRACE;
return 0;
}
struct fq_flow *fq_flow_classify(struct fq *fq, struct fq_tin *tin,
struct sk_buff *skb,
fq_flow_get_default_t get_default_func)
@ -510,6 +504,13 @@ void wireless_nlevent_flush(void)
bool wq_has_sleeper(struct wait_queue_head *wq_head)
{
TRACE;
TRACE_OK;
return true;
}
bool sysfs_streq(const char *s1, const char *s2)
{
TRACE;
return false;
}

View File

@ -927,7 +927,7 @@ static inline int no_printk(const char *fmt, ...) { return 0; }
#define pr_warn(fmt, ...) printk(KERN_WARN fmt, ##__VA_ARGS__)
#define pr_warn_once pr_warn
#define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...) no_printk(KERN_INFO fmt, ##__VA_ARGS__)
#define pr_cont(fmt, ...) printk(KERN_CONT fmt, ##__VA_ARGS__)
/* pr_devel() should produce zero code unless DEBUG is defined */
#ifdef DEBUG
@ -2923,7 +2923,7 @@ unsigned int dev_get_flags(const struct net_device *);
struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, struct rtnl_link_stats64 *storage);
int dev_change_net_namespace(struct net_device *, struct net *, const char *);
int dev_alloc_name(struct net_device *dev, const char *name);
int dev_close(struct net_device *dev);
void dev_close(struct net_device *dev);
int dev_set_mac_address(struct net_device *, struct sockaddr *);
int dev_set_mtu(struct net_device *, int);
int dev_set_promiscuity(struct net_device *dev, int inc);
@ -3245,6 +3245,7 @@ struct file_operations {
int (*release) (struct inode *, struct file *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*fasync) (int, struct file *, int);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
};
static inline loff_t no_llseek(struct file *file, loff_t offset, int origin) {
@ -3287,13 +3288,6 @@ struct platform_device {
};
/* needed by net/rfkill/rfkill-gpio.c */
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
struct device_driver driver;
};
void *platform_get_drvdata(const struct platform_device *pdev);
void platform_set_drvdata(struct platform_device *pdev, void *data);
struct platform_device *platform_device_register_simple( const char *name, int id, const struct resource *res, unsigned int num);
@ -5634,4 +5628,12 @@ int device_property_read_string(struct device *dev, const char *propname, const
#include <lx_emul/extern_c_end.h>
/******************************
** uapi/asm-generic/ioctl.h **
******************************/
#define _IOC_NR(nr) (nr)
#define _IOC_TYPE(nr) (nr)
#endif /* _LX_EMUL_H_ */

View File

@ -29,6 +29,62 @@
#include <lx_kit/pci.h>
/*********************
** RFKILL handling **
*********************/
#include <linux/rfkill.h>
extern "C" void rfkill_switch_all(enum rfkill_type type, bool blocked);
extern "C" bool rfkill_get_any(enum rfkill_type type);
#include <wifi/rfkill.h>
bool wifi_get_rfkill(void)
{
return rfkill_get_any(RFKILL_TYPE_WLAN);
}
static Lx::Task *_lx_task = nullptr;
static bool _lx_init_done = false;
static bool _switch_rfkill = false;
static bool _new_blocked = false;
static Genode::Signal_context_capability _rfkill_sig_ctx;
void wifi_set_rfkill(bool blocked)
{
bool const cur = wifi_get_rfkill();
_switch_rfkill = blocked != cur;
if (_lx_init_done && _switch_rfkill) {
_new_blocked = blocked;
_lx_task->unblock();
Lx::scheduler().schedule();
}
}
/**************************
** socketcall poll hack **
**************************/
void wifi_kick_socketcall()
{
/*
* Kicking is going to unblock the socketcall task that
* probably is waiting in poll_all().
*/
Lx::socket_kick();
}
/*****************************
** Initialization handling **
*****************************/
extern "C" void core_netlink_proto_init(void);
extern "C" void core_sock_init(void);
extern "C" void module_packet_init(void);
@ -44,6 +100,7 @@ extern "C" void module_aes_init(void);
extern "C" void module_arc4_init(void);
// extern "C" void module_chainiv_module_init(void);
extern "C" void module_krng_mod_init(void);
extern "C" void subsys_leds_init(void);
extern "C" unsigned int *module_param_11n_disable;
@ -69,6 +126,7 @@ static void run_linux(void *args)
module_packet_init();
subsys_genl_init();
subsys_rfkill_init();
subsys_leds_init();
fs_cfg80211_init();
subsys_ieee80211_init();
@ -77,7 +135,6 @@ static void run_linux(void *args)
module_crypto_ctr_module_init();
module_aes_init();
module_arc4_init();
// module_chainiv_module_init();
try {
int const err = module_iwl_drv_init();
@ -91,15 +148,40 @@ static void run_linux(void *args)
_wpa_lock->unlock();
_lx_init_done = true;
while (1) {
Lx::scheduler().current()->block_and_schedule();
if (!_switch_rfkill) { continue; }
Genode::log("RFKILL: ", _new_blocked ? "BLOCKED" : "UNBLOCKED");
rfkill_switch_all(RFKILL_TYPE_WLAN, _new_blocked);
if (!_new_blocked) {
try {
bool const ok = Lx::open_device();
if (!ok) { throw -1; }
} catch (...) {
Genode::Env &env = *(Genode::Env*)args;
env.parent().exit(1);
Genode::sleep_forever();
}
}
/* notify front end */
Genode::Signal_transmitter(_rfkill_sig_ctx).submit();
}
}
unsigned long jiffies;
void wifi_init(Genode::Env &env, Genode::Lock &lock, bool disable_11n)
void wifi_init(Genode::Env &env, Genode::Lock &lock, bool disable_11n,
Genode::Signal_context_capability rfkill)
{
Lx_kit::construct_env(env);
@ -128,10 +210,14 @@ void wifi_init(Genode::Env &env, Genode::Lock &lock, bool disable_11n)
*module_param_11n_disable = 1;
}
_rfkill_sig_ctx = rfkill;
/* Linux task (handles the initialization only currently) */
static Lx::Task linux(run_linux, &env, "linux",
Lx::Task::PRIORITY_0, Lx::scheduler());
_lx_task = &linux;
/* give all task a first kick before returning */
Lx::scheduler().schedule();
}

View File

@ -28,6 +28,7 @@ namespace Lx
void emul_init(Genode::Env&, Genode::Allocator&);
void socket_init(Genode::Entrypoint&, Genode::Allocator&);
void socket_kick();
void nic_init(Genode::Env&, Genode::Allocator&);
@ -35,6 +36,8 @@ namespace Lx
void backend_free(Genode::Ram_dataspace_capability);
void get_mac_address(unsigned char *);
bool open_device();
}
#endif /* _LX_H_ */

View File

@ -443,7 +443,7 @@ core_initcall(sock_init);
codel_time_t codel_get_time(void)
{
u64 ns = ktime_get_ns();
u64 ns = ktime_get();
return ns >> CODEL_SHIFT;
}
@ -479,3 +479,41 @@ u64 ktime_get_boot_ns(void)
{
return (u64)ktime_get();
}
/********************
** linux/device.h **
********************/
struct device *device_create_with_groups(struct class *class,
struct device *parent, dev_t devt,
void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...)
{
long ret = -ENODEV;
if (class == NULL || IS_ERR(class)) { goto err; }
struct device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto err;
}
return dev;
err:
return (void*)ret;
}
struct class *__class_create(struct module *owner,
const char *name,
struct lock_class_key *key)
{
struct class *cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) { return (void*)-ENOMEM; }
cls->name = name;
return cls;
}

View File

@ -303,8 +303,9 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
{
/* XXX at some point check if i->count > bytes could be a problem */
if (bytes > i->count)
return false;
bytes = i->count;
if (bytes == 0)
return true;
@ -730,28 +731,6 @@ time64_t ktime_get_seconds(void)
}
/***********************
** linux/workqueue.h **
***********************/
struct workqueue_struct *create_singlethread_workqueue(char const *)
{
workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0);
return wq;
}
struct workqueue_struct *alloc_ordered_workqueue(char const *name , unsigned int flags, ...)
{
return create_singlethread_workqueue(name);
}
struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags,
int max_active, ...)
{
return create_singlethread_workqueue(nullptr);
}
/*************************
** linux/dma-mapping.h **
*************************/
@ -1375,11 +1354,11 @@ void pci_dev_put(struct pci_dev *pci_dev)
Genode::destroy(Lx_kit::env().heap(), pci_dev);
}
/***********************
** linux/workquque.h **
** linux/workqueue.h **
***********************/
/* Linux emul includes */
#include <lx_emul/impl/work.h>
@ -1391,6 +1370,88 @@ bool mod_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork,
}
struct workqueue_struct *alloc_ordered_workqueue(char const *fmt , unsigned int flags, ...)
{
return alloc_workqueue(fmt, flags, 1);
}
struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags,
int max_active, ...)
{
workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0);
Lx::Work *work = Lx::Work::alloc_work_queue(&Lx::Malloc::mem(), fmt);
wq->task = (void *)work;
return wq;
}
void flush_workqueue(struct workqueue_struct *wq)
{
Lx::Task *current = Lx::scheduler().current();
if (!current) {
Genode::error("BUG: flush_workqueue executed without task");
Genode::sleep_forever();
}
Lx::Work *lx_work = (wq && wq->task) ? (Lx::Work*) wq->task
: &Lx::Work::work_queue();
lx_work->flush(*current);
Lx::scheduler().current()->block_and_schedule();
}
static inline bool work_queued(struct workqueue_struct *wq, void *work)
{
Lx::Work *lx_work = (wq && wq->task) ? (Lx::Work*) wq->task
: &Lx::Work::work_queue();
return lx_work->work_queued(work);
}
bool flush_work(struct work_struct *work)
{
/* XXX AFAIU if the work was not queued it is already 'idle' and
* we just return false
*/
bool const queued = work_queued(work->wq, work);
if (queued) {
Genode::error(__func__, " work: ", work, " (", work->func, ") queued");
struct workqueue_struct *wq = work->wq;
Lx::Work *lx_work = (wq && wq->task) ? (Lx::Work*) wq->task
: &Lx::Work::work_queue();
Lx::Task *current = Lx::scheduler().current();
lx_work->wakeup_for(work, *current);
Lx::scheduler().current()->block_and_schedule();
return true;
}
return false;
}
bool flush_delayed_work(struct delayed_work *dwork)
{
/* XXX AFAIU if the work was not queued it is already 'idle' and
* we just return false
*/
bool const queued = work_queued(dwork->wq, dwork);
if (queued) {
Genode::error(__func__, " dwork: ", dwork, " (", dwork->work.func, ") queued");
Genode::sleep_forever();
return true;
}
return false;
}
/***********************
** linux/interrupt.h **
***********************/
@ -1512,7 +1573,7 @@ struct Idr
if (index == INVALID_ENTRY) { return INVALID_ENTRY; }
_barray.set(index, 1);
_ptr[index] = ptr;
_ptr[index] = (addr_t) ptr;
return index;
}

View File

@ -598,6 +598,57 @@ extern "C" size_t LL_RESERVED_SPACE(struct net_device *dev)
}
extern "C" void dev_close(struct net_device *ndev)
{
/*
* First instruct cfg80211 to leave the associated network
* and then shutdown the interface.
*/
net_notifier().call_all_blocks(NETDEV_GOING_DOWN, ndev);
net_notifier().call_all_blocks(NETDEV_DOWN, ndev);
ndev->state &= ~(1UL << __LINK_STATE_START);
netif_carrier_off(ndev);
const struct net_device_ops *ops = ndev->netdev_ops;
if (ops->ndo_stop) { ops->ndo_stop(ndev); }
ndev->flags &= ~IFF_UP;
}
bool Lx::open_device()
{
if (!Root::instance->device) {
Genode::error("no net_device available");
return false;
}
struct net_device * const ndev = Root::instance->device;
int err = ndev->netdev_ops->ndo_open(ndev);
if (err) {
Genode::error("Open device failed");
throw -1;
return err;
}
/*
* Important, otherwise netif_running checks fail and AF_PACKET
* will not bind and EAPOL will cease to work.
*/
ndev->flags |= IFF_UP;
ndev->state |= (1UL << __LINK_STATE_START);
if (ndev->netdev_ops->ndo_set_rx_mode)
ndev->netdev_ops->ndo_set_rx_mode(ndev);
net_notifier().call_all_blocks(NETDEV_UP, ndev);
return true;
}
extern "C" int register_netdevice(struct net_device *ndev)
{
static bool already_registered = false;

View File

@ -358,8 +358,9 @@ class Lx::Socket
case Call::NON_BLOCK: _do_non_block(); break;
default:
_call.err = -EINVAL;
Genode::warning("unknown opcode: ", (int)_call.opcode);
case Call::NONE: /* ignore silently */
_call.err = -EINVAL;
break;
}
@ -372,6 +373,11 @@ class Lx::Socket
_sender.submit();
_block.down();
}
void unblock_task()
{
_task.unblock();
}
};
@ -387,6 +393,15 @@ void Lx::socket_init(Genode::Entrypoint &ep, Genode::Allocator &alloc)
}
void Lx::socket_kick()
{
/* ignore silently, the function might be called to before init */
if (!_socket) { return; }
_socket->unblock_task();
}
static void run_socketcall(void *)
{
while (1) {

View File

@ -10,10 +10,15 @@
*Socket_call*;
/* Wifi::Socket_call instance */
socket_call;
/* rfkill interface */
_*wifi_*_rfkill*;
_*wifi_kick_*;
/* used by libnl's time() */
jiffies;
lx_printf*;
local:
*;

View File

@ -0,0 +1,89 @@
/*
* \brief RFKILL backend
* \author Josef Soentgen
* \date 2018-07-11
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*
* based on:
*
* Linux rfkill helper functions for driver wrappers
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
/* rep includes */
#include <wifi/rfkill.h>
extern "C" {
#include "includes.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include <drivers/rfkill.h>
} /* extern "C" */
struct rfkill_data {
struct rfkill_config *cfg;
int fd;
bool blocked;
};
static void rfkill_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
struct rfkill_data * const rfkill = (rfkill_data*)eloop_ctx;
bool const new_blocked = wifi_get_rfkill();
if (new_blocked != rfkill->blocked) {
rfkill->blocked = new_blocked;
if (new_blocked) {
rfkill->cfg->blocked_cb(rfkill->cfg->ctx);
} else {
rfkill->cfg->unblocked_cb(rfkill->cfg->ctx);
}
}
}
struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
{
struct rfkill_data *rfkill = (rfkill_data*) os_zalloc(sizeof(*rfkill));
if (!rfkill) { return NULL; }
rfkill->cfg = cfg;
rfkill->fd = Wifi::RFKILL_FD;
eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL);
return rfkill;
}
void rfkill_deinit(struct rfkill_data *rfkill)
{
if (!rfkill) { return; }
eloop_unregister_read_sock(rfkill->fd);
os_free(rfkill->cfg);
os_free(rfkill);
}
int rfkill_is_blocked(struct rfkill_data *rfkill)
{
return rfkill ? rfkill->blocked : 0;
}

View File

@ -12,6 +12,9 @@
poll;
/* needed by wpa_supplicant lib for wifi_drv */
nl_set_wpa_ctrl_fd;
local:
*;

View File

@ -1,4 +1,19 @@
/*
* \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>
*
@ -6,8 +21,8 @@
* See README for more details.
*/
/* wpa_supplicant includes */
#include "includes.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/list.h"
@ -17,8 +32,29 @@
#include "wpa_supplicant_i.h"
#include "ctrl_iface.h"
/* rep includes */
#include <wifi/ctrl.h>
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;
unsigned *send_id;
char *recv_buffer;
size_t recv_buffer_size;
unsigned *recv_id;
unsigned last_recv_id;
char *event_buffer;
size_t event_buffer_size;
unsigned *event_id;
};
@ -26,71 +62,201 @@ struct ctrl_iface_global_priv {
struct wpa_global *global;
};
struct ctrl_iface_msg {
struct wpa_supplicant *wpa_s;
};
extern void nl_set_wpa_ctrl_fd(void);
void wpa_ctrl_set_fd()
{
nl_set_wpa_ctrl_fd();
}
static int 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 (!msg || !len || (len > mlen)) { return -1; }
memset(msg, 0, mlen);
memcpy(msg, txt, len);
(*priv->send_id)++;
return 0;
}
/*
* 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);
// lx_printf("%s:%d %p %zu\n", __func__, __LINE__, reply, reply_len);
if (reply) {
wifi_notify_cmd_result();
send_reply(priv, reply, reply_len);
os_free(reply);
} else
if (reply_len == 1) {
send_reply(priv, "FAIL", 4);
} else
if (reply_len == 2) {
send_reply(priv, "OK", 2);
}
}
static void print_txt(char const *txt, size_t len)
{
char buffer[256];
memset(buffer, 0, sizeof(buffer));
memcpy(buffer, txt, len < sizeof(buffer) - 1 ? len : sizeof(buffer) - 1);
lx_printf(" %s\n", buffer);
}
static int 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 (!msg || !len || (len > mlen)) { return -1; }
memset(msg, 0, mlen);
memcpy(msg, txt, len);
(*priv->event_id)++;
return 0;
}
/*
* 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)
{
#if 0
int const dont_print =
strncmp(txt, "BSS:", 4) == 0
|| strncmp(txt, "BSS:", 4) == 0
|| strncmp(txt, "CTRL-EVENT-BSS", 14) == 0
|| strncmp(txt, " skip", 7) == 0
;
if (!dont_print) { print_txt(txt, len); }
#endif
/* 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
/* 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)
{
printf("%s:%d\n", __func__, __LINE__);
struct ctrl_iface_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
if (priv == NULL) { return NULL; }
if (wpa_s->conf->ctrl_interface == 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 ctrl_iface_priv *priv)
{
printf("%s:%d\n", __func__, __LINE__);
struct wpa_ctrl_dst *dst, *prev;
struct ctrl_iface_msg *msg, *prev_msg;
struct ctrl_iface_global_priv *gpriv;
os_free(priv);
}
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
{
printf("%s:%d\n", __func__, __LINE__);
}
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)
{
printf("%s:%d\n", __func__, __LINE__);
struct ctrl_iface_global_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
if (global->params.ctrl_interface == NULL)
return priv;
return priv;
}
void wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
void wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *p)
{
printf("%s:%d\n", __func__, __LINE__);
struct wpa_ctrl_dst *dst, *prev;
struct ctrl_iface_msg *msg, *prev_msg;
os_free(priv);
os_free(p);
}

View File

@ -36,25 +36,8 @@
#include "scan.h"
static char const *conf_file = "/config/wpa_supplicant.conf";
static int connected_scan_interval;
static void connected_scan_handler(void *eloop_ctx, void *user_ctx)
int wpa_main(void)
{
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)eloop_ctx;
if (wpa_s->wpa_state >= WPA_ASSOCIATED)
wpa_supplicant_req_scan(wpa_s, 0, 0);
eloop_register_timeout(connected_scan_interval, 0, connected_scan_handler, wpa_s, 0);
}
int wpa_main(int debug_msg, int interval)
{
connected_scan_interval = interval;
struct wpa_interface iface;
int exitcode = 0;
struct wpa_params params;
@ -62,7 +45,8 @@ int wpa_main(int debug_msg, int interval)
memset(&params, 0, sizeof(params));
params.wpa_debug_level = debug_msg ? MSG_DEBUG : MSG_INFO;
// TODO use CTRL interface for setting debug level
params.wpa_debug_level = 1 ? MSG_DEBUG : MSG_INFO;
params.ctrl_interface = "GENODE";
global = wpa_supplicant_init(&params);
@ -72,15 +56,12 @@ int wpa_main(int debug_msg, int interval)
memset(&iface, 0, sizeof(iface));
iface.ifname = "wlan0";
iface.confname = conf_file;
iface.confname = 0;
iface.ctrl_interface = "GENODE";
if (wpa_supplicant_add_iface(global, &iface, NULL) == NULL)
exitcode = -1;
if (connected_scan_interval > 0)
eloop_register_timeout(connected_scan_interval, 0,
connected_scan_handler, global->ifaces, 0);
if (exitcode == 0)
exitcode = wpa_supplicant_run(global);
@ -88,24 +69,3 @@ int wpa_main(int debug_msg, int interval)
return exitcode;
}
void eloop_handle_signal(int);
void wpa_conf_reload(void)
{
/* (ab)use POSIX signal to trigger reloading the conf file */
eloop_handle_signal(SIGHUP);
}
int wpa_write_conf(char const *buffer, size_t len)
{
int fd = open(conf_file, O_CREAT|O_TRUNC|O_WRONLY);
if (fd == -1)
return -1;
ssize_t n = write(fd, buffer, len);
close(fd);
return n > 0 ? 0 : -1;
}

View File

@ -1,153 +0,0 @@
/*
* \brief WPA Supplicant frontend
* \author Josef Soentgen
* \date 2014-12-08
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <base/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <util/string.h>
/* WPA Supplicant includes */
extern "C" {
#include "includes.h"
#include "common.h"
#include "drivers/driver.h"
#include "wpa_supplicant_i.h"
#include "bss.h"
#include "scan.h"
#include "common/ieee802_11_defs.h"
}
static Genode::Constructible<Genode::Reporter> accesspoints_reporter;
static Genode::Constructible<Genode::Reporter> state_reporter;
extern "C" void wpa_reporter_init(void *env)
{
accesspoints_reporter.construct(*static_cast<Genode::Env*>(env), "wlan_accesspoints");
accesspoints_reporter->enabled(true);
state_reporter.construct(*static_cast<Genode::Env*>(env), "wlan_state");
state_reporter->enabled(true);
}
enum { SSID_STRING_MAX_LEN = 32 + 1, MAC_STR_LEN = 6*2 + 5 + 1};
static inline void mac2str(char *buf, u8 const *mac)
{
Genode::snprintf(buf, MAC_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
extern "C" void wpa_report_connect_event(struct wpa_supplicant *wpa_s)
{
try {
Genode::Reporter::Xml_generator xml(*state_reporter, [&]() {
struct wpa_ssid *wpa_ssid = wpa_s->current_ssid;
/* FIXME ssid may contain any characters, even NUL */
Genode::String<SSID_STRING_MAX_LEN>
ssid(Genode::Cstring((char *)wpa_ssid->ssid, wpa_ssid->ssid_len));
char bssid_buf[MAC_STR_LEN];
mac2str(bssid_buf, wpa_s->bssid);
xml.node("accesspoint", [&]() {
xml.attribute("ssid", ssid.string());
xml.attribute("bssid", bssid_buf);
xml.attribute("state", "connected");
});
});
} catch (...) { Genode::warning("could not report connected state"); }
}
extern "C" void wpa_report_disconnect_event(struct wpa_supplicant *wpa_s)
{
try {
Genode::Reporter::Xml_generator xml(*state_reporter, [&]() {
struct wpa_ssid *wpa_ssid = wpa_s->current_ssid;
/* FIXME ssid may contain any characters, even NUL */
Genode::String<SSID_MAX_LEN>
ssid(Genode::Cstring((char *)wpa_ssid->ssid, wpa_ssid->ssid_len));
char bssid_buf[MAC_STR_LEN];
mac2str(bssid_buf, wpa_ssid->bssid);
unsigned auth_failures = wpa_ssid->auth_failures;
xml.node("accesspoint", [&]() {
xml.attribute("ssid", ssid.string());
xml.attribute("bssid", bssid_buf);
xml.attribute("state", "disconnected");
xml.attribute("auth_failures", auth_failures);
});
});
} catch (...) { Genode::warning("could not report disconnected state"); }
}
static inline int approximate_quality(struct wpa_bss *bss)
{
/*
* We provide an quality value by transforming the actual
* signal level [-50,-100] (dBm) to [100,0] (%).
*/
int level = bss->level;
if (level <= -100)
return 0;
else if (level >= -50)
return 100;
return 2 * (level + 100);
}
extern "C" void wpa_report_scan_results(struct wpa_supplicant *wpa_s)
{
try {
Genode::Reporter::Xml_generator xml(*accesspoints_reporter, [&]() {
for (unsigned i = 0; i < wpa_s->last_scan_res_used; i++) {
struct wpa_bss *bss = wpa_s->last_scan_res[i];
bool wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) != NULL;
bool wpa2 = wpa_bss_get_ie(bss, WLAN_EID_RSN) != NULL;
char bssid_buf[MAC_STR_LEN];
mac2str(bssid_buf, bss->bssid);
Genode::String<SSID_MAX_LEN>
ssid(Genode::Cstring((char *)bss->ssid, bss->ssid_len));
int quality = approximate_quality(bss);
xml.node("accesspoint", [&]() {
xml.attribute("ssid", ssid.string());
xml.attribute("bssid", bssid_buf);
xml.attribute("quality", quality);
/* XXX we forcefully only support WPA/WPA2 psk for now */
if (wpa || wpa2)
xml.attribute("protection", "WPA-PSK");
});
}
});
} catch (...) { Genode::warning("could not report scan results"); }
}

View File

@ -7,6 +7,7 @@
/* needed by wifi_drv */
wpa_main;
wpa_reporter_init;
wpa_ctrl_set_fd;
/* needed by wpa_driver_nl80211 */
__hide_aliasing_typecast;

View File

@ -359,7 +359,6 @@ linux-x.x.x/net/packet/af_packet.c
linux-x.x.x/net/packet/internal.h
linux-x.x.x/net/rfkill/core.c
linux-x.x.x/net/rfkill/input.c
linux-x.x.x/net/rfkill/rfkill-gpio.c
linux-x.x.x/net/rfkill/rfkill.h
linux-x.x.x/net/wireless/ap.c
linux-x.x.x/net/wireless/chan.c