[RFC connman v2 0/1] Add wpa_supplicant WPA3-SAE support
by Ariel D'Alessandro
Hi all,
Here's another attemp on adding WPA3-SAE support to connman
(wpa_supplicant backend).
I'd like comments on the following mainly:
Based on plugin/iwd.c, a private data struct is added to each network
in plugin/wifi.c so it can keep track of keymgmt capabilities, needed to
use WPA3-SAE if it's available. See RFC v1 thread for more details.
Note that this is an RFC patchset. Feel free to give any kind of
feedback, always appreciated :-)
Changes from v1:
* Dropped changes to service API.
* Unified WPA3-SAE under WPA-PSK.
* Added private data struct to network in plugin/wifi.c
Regards,
Ariel D'Alessandro (1):
WIP: Add wpa_supplicant WPA3-SAE support
gsupplicant/gsupplicant.h | 10 ++++++++++
gsupplicant/supplicant.c | 33 ++++++++++++++++++++++++++++++---
plugins/wifi.c | 21 +++++++++++++++++++++
3 files changed, 61 insertions(+), 3 deletions(-)
--
2.30.2
11 months
[PATCH 1/8] ip-pool: Track IPv4 addresses in use
by Andrew Zaborowski
Add the ip-pool submodule that tracks IPv4 addresses in use on the
system for use when selecting the address for a new AP. l_rtnl_address
is used internally because if we're going to return l_rtnl_address
objects it would be misleading if we didn't fill in all of their
properties like flags etc.
---
Makefile.am | 1 +
src/ip-pool.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/ip-pool.h | 23 +++++++
3 files changed, 199 insertions(+)
create mode 100644 src/ip-pool.c
create mode 100644 src/ip-pool.h
diff --git a/Makefile.am b/Makefile.am
index 68035e46..083bc95a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -243,6 +243,7 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
src/eap-wsc.c src/eap-wsc.h \
src/wscutil.h src/wscutil.c \
src/diagnostic.h src/diagnostic.c \
+ src/ip-pool.h src/ip-pool.c \
$(eap_sources) \
$(builtin_sources)
diff --git a/src/ip-pool.c b/src/ip-pool.c
new file mode 100644
index 00000000..51b3ef40
--- /dev/null
+++ b/src/ip-pool.c
@@ -0,0 +1,175 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ell/ell.h>
+
+#include "src/util.h"
+#include "src/iwd.h"
+#include "src/module.h"
+#include "src/netdev.h"
+#include "src/ip-pool.h"
+
+struct ip_pool_addr4_record {
+ uint32_t ifindex;
+ struct l_rtnl_address *addr;
+};
+
+static struct l_queue *used_addr4_list;
+static struct l_netlink *rtnl;
+
+static void ip_pool_addr4_record_free(void *data)
+{
+ struct ip_pool_addr4_record *rec = data;
+
+ l_rtnl_address_free(rec->addr);
+ l_free(rec);
+}
+
+static bool ip_pool_addr4_match_ifindex(const void *a, const void *b)
+{
+ const struct ip_pool_addr4_record *addr = a;
+
+ return addr->ifindex == L_PTR_TO_UINT(b);
+}
+
+struct l_rtnl_address *ip_pool_get_addr4(uint32_t ifindex)
+{
+ const struct ip_pool_addr4_record *rec =
+ l_queue_find(used_addr4_list, ip_pool_addr4_match_ifindex,
+ L_UINT_TO_PTR(ifindex));
+
+ return rec ? l_rtnl_address_dup(rec->addr) : 0;
+}
+
+static bool ip_pool_addr4_match_free(void *data, void *user_data)
+{
+ const struct ip_pool_addr4_record *a = data;
+ const struct ip_pool_addr4_record *b = user_data;
+ char a_addr_str[INET_ADDRSTRLEN];
+ char b_addr_str[INET_ADDRSTRLEN];
+
+ if (a->ifindex != b->ifindex ||
+ l_rtnl_address_get_prefix_length(a->addr) !=
+ l_rtnl_address_get_prefix_length(b->addr))
+ return false;
+
+ if (!l_rtnl_address_get_address(a->addr, a_addr_str) ||
+ !l_rtnl_address_get_address(b->addr, b_addr_str) ||
+ strcmp(a_addr_str, b_addr_str))
+ return false;
+
+ ip_pool_addr4_record_free(data);
+ return true;
+}
+
+static void ip_pool_addr_notify(uint16_t type, const void *data, uint32_t len,
+ void *user_data)
+{
+ const struct ifaddrmsg *ifa = data;
+ struct l_rtnl_address *addr;
+
+ if (ifa->ifa_family != AF_INET || ifa->ifa_prefixlen < 1)
+ return;
+
+ len -= NLMSG_ALIGN(sizeof(struct ifaddrmsg));
+
+ addr = l_rtnl_ifaddr_extract(ifa, len);
+ if (!addr)
+ return;
+
+ if (type == RTM_NEWADDR) {
+ struct ip_pool_addr4_record *rec;
+
+ rec = l_new(struct ip_pool_addr4_record, 1);
+ rec->ifindex = ifa->ifa_index;
+ rec->addr = l_steal_ptr(addr);
+ l_queue_push_tail(used_addr4_list, rec);
+ } else if (type == RTM_DELADDR) {
+ struct ip_pool_addr4_record rec;
+
+ rec.ifindex = ifa->ifa_index;
+ rec.addr = addr;
+
+ l_queue_foreach_remove(used_addr4_list,
+ ip_pool_addr4_match_free, &rec);
+ }
+
+ l_rtnl_address_free(addr);
+}
+
+static void ip_pool_addr4_dump_cb(int error,
+ uint16_t type, const void *data,
+ uint32_t len, void *user_data)
+{
+ if (error) {
+ l_error("addr4_dump_cb: %s (%i)", strerror(-error), -error);
+ return;
+ }
+
+ ip_pool_addr_notify(type, data, len, user_data);
+}
+
+static int ip_pool_init(void)
+{
+ const struct l_settings *settings = iwd_get_config();
+ bool netconfig_enabled;
+
+ if (!l_settings_get_bool(settings, "General",
+ "EnableNetworkConfiguration",
+ &netconfig_enabled))
+ netconfig_enabled = false;
+
+ if (!netconfig_enabled)
+ return 0;
+
+ rtnl = iwd_get_rtnl();
+
+ if (!l_netlink_register(rtnl, RTNLGRP_IPV4_IFADDR,
+ ip_pool_addr_notify, NULL, NULL)) {
+ l_error("Failed to register for RTNL link notifications");
+ return -EIO;
+ }
+
+ if (!l_rtnl_ifaddr4_dump(rtnl, ip_pool_addr4_dump_cb, NULL, NULL)) {
+ l_error("Sending the IPv4 addr dump req failed");
+ return -EIO;
+ }
+
+ used_addr4_list = l_queue_new();
+ return 0;
+}
+
+static void ip_pool_exit(void)
+{
+ l_queue_destroy(used_addr4_list, ip_pool_addr4_record_free);
+ used_addr4_list = NULL;
+}
+
+IWD_MODULE(ip_pool, ip_pool_init, ip_pool_exit)
diff --git a/src/ip-pool.h b/src/ip-pool.h
new file mode 100644
index 00000000..f3c3011d
--- /dev/null
+++ b/src/ip-pool.h
@@ -0,0 +1,23 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+struct l_rtnl_address *ip_pool_get_addr4(uint32_t ifindex);
--
2.27.0
1 year, 1 month
[PATCH 1/3] network: sync known network frequency on BSS update
by Alvin Šipraga
From: Alvin Šipraga <alsi(a)bang-olufsen.dk>
When a scan_bss is updated in the BSS list of a known network, it may be
on a new frequency. Sync the known frequencies list accordingly.
---
src/network.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/network.c b/src/network.c
index 617559e6b803..68542d52e24c 100644
--- a/src/network.c
+++ b/src/network.c
@@ -691,6 +691,12 @@ bool network_bss_update(struct network *network, struct scan_bss *bss)
l_queue_insert(network->bss_list, bss, scan_bss_rank_compare, NULL);
+ /* Sync frequency for already known networks */
+ if (network->info) {
+ known_network_add_frequency(network->info, bss->frequency);
+ known_network_frequency_sync(network->info);
+ }
+
return true;
}
--
2.31.1
1 year, 1 month
Re: [RFC connman 1/1] WIP: Add WPA3-SAE support
by Daniel Wagner
Hi Andrej,
On Thu, May 13, 2021 at 11:52:32AM +0200, Andrej Shadura wrote:
> On 12/05/2021 19:27, Ariel D'Alessandro wrote:
> > Implement WPA3-SAE authentication on connman side.
> >
> > Based on Tizen project:
> >
> > https://review.tizen.org/git/?p=platform/upstream/connman.git
> >
> > Signed-off-by: Ariel D'Alessandro <ariel.dalessandro(a)collabora.com>
>
> Based on my understanding how this should work, this looks reasonable to me.
Same here, this looks pretty straightforward. Thanks for picking this
up.
The patch should be spitted into one which adds the SAE to the Security
property of the Service API (please also update the documentation). The
second patch adds the plugins/wifi.c implementation.
I am not really into the WiFi topic anymore, so I am adding the iwd
mailing list. Maybe we get some input for the new SAE Security
property, e.g. how this could work with iwd.
Thanks,
Daniel
1 year, 1 month
How to NAT when using iwd ap mode?
by KeithG
I have been trying to get ap mode to NAT and am unsuccessful. Is this possible?
I can get AP mode to work with this in /etc/iwd/main.conf
and I can get an IP address associated and I can connect to the
computer running iwd in ap mode. What I cannot do is NAT the wifi
connected device to the eth0 which has a valid connection.
[General]
UseDefaultInterface=true
EnableNetworkConfiguration=true
APRanges=192.168.5.0/24
After I get my AP running and connect, I tried to run these commands
to enable NAT:
# sysctl net.ipv4.ip_forward=1
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
When I try this, I get no 'internet' traffic from eth0.
Is this due to dns? Do I need to use iptables to NAT this?
When I run connman in tether mode it works. I can connect and I get
internet traffic over wlan connected devices. When I have iwd running
in AP mode, though, I cannot figure out how to share the eth0
connection to the wifi connected device(s).
Is there a guide on how to use the ap.iwd provisioning file? I am not
clear on how to use it. I created a file: /etc/iwd/ap.iwd and it does
not seem to use it. Where do you set the hostname?
Keith
1 year, 1 month
Using iwd.py for a project
by Pranav Jerry
Hi!
I'm the developer of naxalnet [1], a shell
script to create a BATMAN-Advanced mesh network without bothering with
any
configuration.
It uses iwd to create an ad-hoc network and then configures the network
using
systemd-networkd.
It is currently in alpha stage.
I'm working on rewriting it in python and found out controlling iwd via
D-Bus
is not easy as I thought. I searched the web for python libraries to
control iwd
and found out on stackoverflow [2] that the iwd git repo had python3
examples
in `tests/`.
On further exploring, I found a python library for using iwd,
`autotests/util/iwd.py`. The python scripts used for testing in
`autotests`
showed it was easy to use and was just what I needed to use for
connecting
to iwd in my project.
But I couldn't find any information on the library on
iwd.wiki.kernel.org and
I think it was developed for internal use. The library is not on PyPi
either.
I want to use the library in naxalnet, which is at present a
single-file file that
starts with `#!/usr/bin/env python3`, meant to reside as
`/usr/bin/naxalnet`.
How do I make iwd.py importable? I don't want to include iwd.py as a
file
when I package naxalnet for distribution.
So it probably needs to be installed by pip as a library, or by the OS
package
manager. Can you or any other developers make iwd.py available as a
python
package installable by pip?
I'm not an experienced dev and I'm not used to python packaging, so
correct me
if I'm wrong anywhere.
[1]: https://git.disroot.org/pranav/naxalnet
[2]:
https://stackoverflow.com/questions/60358001/accessing-iwd-dbus-interface...
1 year, 1 month
[PATCH 1/7] ip-pool: Track IPv4 addresses in use
by Andrew Zaborowski
Add the ip-pool submodule that tracks IPv4 addresses in use on the
system for use when selecting the address for a new AP.
---
Makefile.am | 1 +
src/ip-pool.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/ip-pool.h | 32 ++++++++++
3 files changed, 193 insertions(+)
create mode 100644 src/ip-pool.c
create mode 100644 src/ip-pool.h
diff --git a/Makefile.am b/Makefile.am
index 68035e46..083bc95a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -243,6 +243,7 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
src/eap-wsc.c src/eap-wsc.h \
src/wscutil.h src/wscutil.c \
src/diagnostic.h src/diagnostic.c \
+ src/ip-pool.h src/ip-pool.c \
$(eap_sources) \
$(builtin_sources)
diff --git a/src/ip-pool.c b/src/ip-pool.c
new file mode 100644
index 00000000..1166383c
--- /dev/null
+++ b/src/ip-pool.c
@@ -0,0 +1,160 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ell/ell.h>
+
+#include "src/util.h"
+#include "src/iwd.h"
+#include "src/module.h"
+#include "src/netdev.h"
+#include "src/ip-pool.h"
+
+static struct l_queue *used_addr4_list;
+static struct l_netlink *rtnl;
+
+static bool ip_pool_addr4_match_ifindex(const void *a, const void *b)
+{
+ const struct ip_pool_addr4_record *addr = a;
+
+ return addr->ifindex == L_PTR_TO_UINT(b) && !addr->secondary;
+}
+
+const struct ip_pool_addr4_record *ip_pool_get_addr4(struct netdev *netdev)
+{
+ return l_queue_find(used_addr4_list, ip_pool_addr4_match_ifindex,
+ L_UINT_TO_PTR(netdev_get_ifindex(netdev)));
+}
+
+static bool ip_pool_addr4_match_free(void *data, void *user_data)
+{
+ const struct ip_pool_addr4_record *a = data;
+ const struct ip_pool_addr4_record *b = user_data;
+
+ if (a->ifindex != b->ifindex || a->addr != b->addr ||
+ a->prefix_len != b->prefix_len)
+ return false;
+
+ l_free(data);
+ return true;
+}
+
+static void ip_pool_addr_notify(uint16_t type, const void *data, uint32_t len,
+ void *user_data)
+{
+ const struct ifaddrmsg *ifa = data;
+ char *ip_str = NULL;
+ int r;
+ struct in_addr ip;
+
+ if (ifa->ifa_family != AF_INET || ifa->ifa_prefixlen < 1)
+ return;
+
+ len -= NLMSG_ALIGN(sizeof(struct ifaddrmsg));
+
+ l_rtnl_ifaddr4_extract(ifa, len, NULL, &ip_str, NULL);
+ if (!ip_str)
+ return;
+
+ r = inet_aton(ip_str, &ip);
+ l_free(ip_str);
+
+ if (r < 0)
+ return;
+
+ if (type == RTM_NEWADDR) {
+ struct ip_pool_addr4_record *addr;
+
+ addr = l_new(struct ip_pool_addr4_record, 1);
+ addr->addr = ntohl(ip.s_addr);
+ addr->prefix_len = ifa->ifa_prefixlen;
+ addr->ifindex = ifa->ifa_index;
+ addr->secondary = !!(ifa->ifa_flags & IFA_F_SECONDARY);
+ l_queue_push_tail(used_addr4_list, addr);
+ } else if (type == RTM_DELADDR) {
+ struct ip_pool_addr4_record addr;
+
+ addr.addr = ntohl(ip.s_addr);
+ addr.prefix_len = ifa->ifa_prefixlen;
+ addr.ifindex = ifa->ifa_index;
+
+ l_queue_foreach_remove(used_addr4_list,
+ ip_pool_addr4_match_free, &addr);
+ }
+}
+
+static void ip_pool_addr4_dump_cb(int error,
+ uint16_t type, const void *data,
+ uint32_t len, void *user_data)
+{
+ if (error) {
+ l_error("addr4_dump_cb: %s (%i)", strerror(-error), -error);
+ return;
+ }
+
+ ip_pool_addr_notify(type, data, len, user_data);
+}
+
+static int ip_pool_init(void)
+{
+ const struct l_settings *settings = iwd_get_config();
+ bool netconfig_enabled;
+
+ if (!l_settings_get_bool(settings, "General",
+ "EnableNetworkConfiguration",
+ &netconfig_enabled))
+ netconfig_enabled = false;
+
+ if (!netconfig_enabled)
+ return 0;
+
+ rtnl = iwd_get_rtnl();
+
+ if (!l_netlink_register(rtnl, RTNLGRP_IPV4_IFADDR,
+ ip_pool_addr_notify, NULL, NULL)) {
+ l_error("Failed to register for RTNL link notifications");
+ return -EIO;
+ }
+
+ if (!l_rtnl_ifaddr4_dump(rtnl, ip_pool_addr4_dump_cb, NULL, NULL)) {
+ l_error("Sending the IPv4 addr dump req failed");
+ return -EIO;
+ }
+
+ used_addr4_list = l_queue_new();
+ return 0;
+}
+
+static void ip_pool_exit(void)
+{
+ l_queue_destroy(used_addr4_list, l_free);
+ used_addr4_list = NULL;
+}
+
+IWD_MODULE(ip_pool, ip_pool_init, ip_pool_exit)
diff --git a/src/ip-pool.h b/src/ip-pool.h
new file mode 100644
index 00000000..6a220735
--- /dev/null
+++ b/src/ip-pool.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * Wireless daemon for Linux
+ *
+ * Copyright (C) 2021 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+struct netdev;
+
+struct ip_pool_addr4_record {
+ uint32_t addr;
+ uint8_t prefix_len;
+ uint32_t ifindex;
+ bool secondary;
+};
+
+const struct ip_pool_addr4_record *ip_pool_get_addr4(struct netdev *netdev);
--
2.27.0
1 year, 1 month
[PATCH] scan: parse NL80211_BSS_LAST_SEEN_BOOTTIME in units of
nanoseconds
by Alvin Šipraga
NL80211_BSS_LAST_SEEN_BOOTTIME is expressed in nanoseconds, while BSS
timestamps are expressed in microseconds internally. Convert the
attribute to microseconds when using it to timestamp a BSS. This makes
iwd expire absent BSSes within 30 seconds as intended.
---
src/scan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/scan.c b/src/scan.c
index a6f97c08f09b..8967706f35b9 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -1231,7 +1231,7 @@ static struct scan_bss *scan_parse_attr_bss(struct l_genl_attr *attr,
if (L_WARN_ON(len != sizeof(uint64_t)))
break;
- bss->time_stamp = l_get_u64(data);
+ bss->time_stamp = l_get_u64(data) / L_NSEC_PER_USEC;
break;
}
}
--
2.31.1
1 year, 1 month
[PATCH] netdev: station: support channel switch events
by Alvin Šipraga
If the connected BSS announces that it is switching operating channel,
the kernel may emit the NL80211_CMD_CH_SWTICH_NOTIFY event when the
switch is complete. Handle this event in netdev in a way similar to the
NL80211_CMD_ROAM event by getting the new BSS info and passing it to
station. station will then update its current_bss member.
This enables iwd to keep track of the current operating frequency after
a channel switch. Previously iwd would ignore this event and the output
of 'iwctl station wlan0 show' would show the old frequency.
---
src/netdev.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/netdev.h | 1 +
src/station.c | 21 +++++++++++++++
3 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/src/netdev.c b/src/netdev.c
index 9a2afe1d18be..9f185cc1a333 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -145,6 +145,7 @@ struct netdev {
uint8_t set_mac_once[6];
struct scan_bss *fw_roam_bss;
+ struct scan_bss *channel_switch_bss;
uint32_t set_powered_cmd_id;
netdev_command_cb_t set_powered_cb;
@@ -1307,6 +1308,17 @@ static void netdev_connect_ok(struct netdev *netdev)
netdev->ft_ds_list = NULL;
}
+ if (netdev->channel_switch_bss) {
+ if (netdev->event_filter)
+ netdev->event_filter(netdev, NETDEV_EVENT_CHANNEL_SWITCHED,
+ netdev->channel_switch_bss,
+ netdev->user_data);
+ else
+ scan_bss_free(netdev->channel_switch_bss);
+
+ netdev->channel_switch_bss = NULL;
+ }
+
if (netdev->connect_cb) {
netdev->connect_cb(netdev, NETDEV_RESULT_OK, NULL,
netdev->user_data);
@@ -4407,7 +4419,7 @@ static bool match_addr(const void *a, const void *b)
return memcmp(bss->addr, b, 6) == 0;
}
-static bool netdev_get_fw_scan_cb(int err, struct l_queue *bss_list,
+static bool netdev_get_fw_scan_roam_cb(int err, struct l_queue *bss_list,
const struct scan_freq_set *freqs,
void *user_data)
{
@@ -4520,7 +4532,7 @@ static void netdev_roam_event(struct l_genl_msg *msg, struct netdev *netdev)
get_fw_scan:
handshake_state_set_authenticator_address(netdev->handshake, mac);
- if (!scan_get_firmware_scan(netdev->wdev_id, netdev_get_fw_scan_cb,
+ if (!scan_get_firmware_scan(netdev->wdev_id, netdev_get_fw_scan_roam_cb,
netdev, NULL))
goto failed;
@@ -4536,6 +4548,58 @@ failed:
}
+static bool netdev_get_fw_scan_channel_switch_cb(int err, struct l_queue *bss_list,
+ const struct scan_freq_set *freqs,
+ void *user_data)
+{
+ struct netdev *netdev = user_data;
+ struct scan_bss *bss = NULL;
+
+ if (!netdev->connected)
+ return false;
+
+ if (err < 0) {
+ l_error("Failed to get scan after channel switch (%d)", err);
+ goto failed;
+ }
+
+ bss = l_queue_remove_if(bss_list, match_addr, netdev->handshake->aa);
+
+ if (!bss) {
+ l_error("Channel switch BSS not found in scan results");
+ goto failed;
+ }
+
+ netdev->channel_switch_bss = bss;
+
+ netdev_connect_ok(netdev);
+
+ return false;
+
+failed:
+ netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED,
+ MMPDU_REASON_CODE_UNSPECIFIED);
+ return false;
+}
+
+static void netdev_channel_switch_event(struct l_genl_msg *msg,
+ struct netdev *netdev)
+{
+ l_debug("");
+
+ if (!scan_get_firmware_scan(netdev->wdev_id,
+ netdev_get_fw_scan_channel_switch_cb, netdev, NULL))
+ goto failed;
+
+ return;
+
+failed:
+ l_error("Failed to handle channel switch");
+ netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED,
+ MMPDU_REASON_CODE_UNSPECIFIED);
+
+}
+
static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
{
struct netdev *netdev = NULL;
@@ -4561,6 +4625,9 @@ static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
case NL80211_CMD_ROAM:
netdev_roam_event(msg, netdev);
break;
+ case NL80211_CMD_CH_SWITCH_NOTIFY:
+ netdev_channel_switch_event(msg, netdev);
+ break;
case NL80211_CMD_CONNECT:
netdev_connect_event(msg, netdev);
break;
diff --git a/src/netdev.h b/src/netdev.h
index f625957bb760..ee944bceef8a 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -43,6 +43,7 @@ enum netdev_event {
NETDEV_EVENT_ASSOCIATING,
NETDEV_EVENT_ROAMING,
NETDEV_EVENT_ROAMED,
+ NETDEV_EVENT_CHANNEL_SWITCHED,
NETDEV_EVENT_DISCONNECT_BY_AP,
NETDEV_EVENT_DISCONNECT_BY_SME,
NETDEV_EVENT_RSSI_THRESHOLD_LOW,
diff --git a/src/station.c b/src/station.c
index 5fb3a03d6831..a613aad460eb 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2324,6 +2324,24 @@ static void station_event_roamed(struct station *station, struct scan_bss *new)
station_roamed(station);
}
+static void station_event_channel_switched(struct station *station,
+ struct scan_bss *new)
+{
+ struct scan_bss *stale;
+
+ network_bss_update(station->connected_network, new);
+
+ /* Remove new BSS if it exists in past scan results */
+ stale = l_queue_remove_if(station->bss_list, bss_match_bssid,
+ new->addr);
+ if (stale)
+ scan_bss_free(stale);
+
+ station->connected_bss = new;
+
+ l_queue_insert(station->bss_list, new, scan_bss_rank_compare, NULL);
+}
+
static void station_rssi_level_changed(struct station *station,
uint8_t level_idx);
@@ -2358,6 +2376,9 @@ static void station_netdev_event(struct netdev *netdev, enum netdev_event event,
case NETDEV_EVENT_ROAMED:
station_event_roamed(station, (struct scan_bss *) event_data);
break;
+ case NETDEV_EVENT_CHANNEL_SWITCHED:
+ station_event_channel_switched(station, (struct scan_bss *) event_data);
+ break;
}
}
--
2.31.1
1 year, 1 month
Re: How to configure an IoT wifi setup
by Denis Kenzior
Hi Diego,
>>> In theory 2 can be done today, either by iwd or combo iwd/hostapd with
>> some
>>> manual magic.
>
> We do exactly this on our devices, when we explored things a while back it was not really an option to do it all with iwd, so we use iwd for the client part, create a new interface on the same WiFi adapter and fire up a hostapd + dnsmasq combo on it as a "configuration AP", if the device is not configured yet. The advantage is that iwd works in parallel in client mode so we can get the list of available networks and test that the configuration provided by the user really works without having to disconnect the user from the "configuration AP" until configuration is complete.
Awesome, thanks for confirming that this can be done. In theory iwd should be
getting to the point where our AP mode support should be good enough for simple
scenarios like this one.
>
> Creating a second interface in AP mode works on all the WiFi adapters we have encountered, which are mainly Intel and Qualcomm.
>
Keith,
Any P2P capable adapter should be able to do this (so pretty much any modern
hardware). There was an earlier discussion on the list where I suggested that
we add a config option to main.conf to start iwd either in station + p2p or
station + ap mode.
Patches are always welcome!
Regards,
-Denis
1 year, 1 month