Re: iwd 1.18 doesn't connect to network on boot
by 58e33db1-f428-4823-8cc3-d962d0fb8aa8@slmail.me
> Hi Jason,
>
> On 9/23/21 6:04 AM, 58e33db1-f428-4823-8cc3-d962d0fb8aa8(a)slmail.me wrote:
> > Hi,
> >
> > I'm on Arch Linux and after recent iwd upgrade to version 1.18 I'm no longer connected to my home network when booting. Previous version works just fine. I've managed to workaround the issue simply by going to iwctl and manually doing disconnect/connect every time I boot the computer.
>
> Not much to go on. Can you tell us what the previous version of iwd was? How
> is your AP configured? WPA2-Personal? WPA3-Personal? At a minimum we also need
> logs from iwd and preferably iwmon. See https://iwd.wiki.kernel.org/debugging
>
> Regards,
> -Denis
Hi Denis,
AP authentication is WPA2-Personal. I turned on logging and these are the relevant lines:
iwd[4842]: src/station.c:station_autoconnect_next() autoconnect: Trying SSID: xxxxxxxx
iwd[4842]: src/station.c:station_autoconnect_next() autoconnect: 'xx:xx:xx:xx:xx:xx' freq: 2447, rank: 2184, strength: -6500
iwd[4842]: src/netdev.c:netdev_cqm_rssi_update()
iwd[4842]: src/wiphy.c:wiphy_radio_work_insert() Inserting work item 2
iwd[4842]: src/station.c:__station_connect_network() connecting to BSS xx:xx:xx:xx:xx:xx
iwd[4842]: src/station.c:station_enter_state() Old State: autoconnect_quick, new state: connecting (auto)
iwd[4842]: src/scan.c:scan_cancel() Trying to cancel scan id 1 for wdev 8
iwd[4842]: src/wiphy.c:wiphy_radio_work_done() Work item 1 done
iwd[4842]: src/wiphy.c:wiphy_radio_work_next() Starting work item 2
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/netdev.c:netdev_mac_power_down_cb() Setting generated address on ifindex: 8 to: 9a:a7:a9:ba:16:52
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/wiphy.c:wiphy_reg_notify() Notification of command Wiphy Reg Change(113)
iwd[4842]: src/wiphy.c:wiphy_update_reg_domain() New reg domain country code for phy0 is XX
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/scan.c:scan_notify() Scan notification Trigger Scan(33)
iwd[4842]: src/station.c:station_netdev_event() Associating
iwd[4842]: src/scan.c:scan_notify() Scan notification New Scan Results(34)
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
kernel: wlan0: authenticate with xx:xx:xx:xx:xx:xx
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification New Station(19)
kernel: wlan0: send auth to xx:xx:xx:xx:xx:xx (try 1/3)
kernel: wlan0: send auth to xx:xx:xx:xx:xx:xx (try 2/3)
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
iwd[4842]: src/netdev.c:netdev_authenticate_event()
kernel: wlan0: authenticated
kernel: wlan0: associate with xx:xx:xx:xx:xx:xx (try 1/3)
kernel: wlan0: RX AssocResp from xx:xx:xx:xx:xx:xx (capab=0x1411 status=0 aid=1)
iwd[4842]: src/netdev.c:netdev_unicast_notify() Unicast notification 129
iwd[4842]: src/netdev.c:netdev_control_port_frame_event()
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Associate(38)
iwd[4842]: src/netdev.c:netdev_associate_event()
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Connect(46)
iwd[4842]: src/netdev.c:netdev_connect_event()
iwd[4842]: src/eapol.c:eapol_handle_ptk_1_of_4() ifindex=8
kernel: wlan0: associated
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Control Port TX Status(139)
iwd[4842]: src/netdev.c:netdev_unicast_notify() Unicast notification 129
iwd[4842]: src/netdev.c:netdev_control_port_frame_event()
iwd[4842]: src/eapol.c:eapol_handle_ptk_3_of_4() ifindex=8
iwd[4842]: src/netdev.c:netdev_set_gtk() 8
iwd[4842]: src/station.c:station_handshake_event() Setting keys
iwd[4842]: src/netdev.c:netdev_set_tk() 8
iwd[4842]: src/netdev.c:netdev_set_rekey_offload() 8
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Control Port TX Status(139)
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Notify CQM(64)
iwd[4842]: src/station.c:station_connect_cb() 8, result: 0
iwd[4842]: src/station.c:station_connect_ok()
iwd[4842]: src/netconfig.c:netconfig_ipv6_select_and_install() IPV6 configuration disabled
iwd[4842]: src/wiphy.c:wiphy_radio_work_done() Work item 2 done
iwd[4842]: src/netdev.c:netdev_link_notify() event 16 on ifindex 8
iwd[4842]: src/netdev.c:netdev_mlme_notify() MLME notification Frame TX Status(60)
iwd[4842]: src/station.c:station_early_neighbor_report_cb() ifindex: 8, error: -110(Connection timed out)
This is the point where connection is stuck and iwctl reports 'connecting' indefinitely despite being authenticated already.
Anything else just tell me.
Thanks.
7 months, 3 weeks
[PATCH 1/5] test: choose default device in force-roam
by James Prestwood
This makes the usage much more convenient if the system has only
a single device.
---
test/force-roam | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/test/force-roam b/test/force-roam
index b45ad2e6..a6df854a 100755
--- a/test/force-roam
+++ b/test/force-roam
@@ -3,14 +3,33 @@
import sys
import dbus
-if (len(sys.argv) != 3):
- print("Usage: %s <device> <mac>" % (sys.argv[0]))
+if len(sys.argv) < 2 or len(sys.argv) > 3:
+ print("Usage: %s [device] <mac>" % (sys.argv[0]))
sys.exit(1)
bus = dbus.SystemBus()
-device = dbus.Interface(bus.get_object("net.connman.iwd", sys.argv[1]),
+device = None
+
+if len(sys.argv) == 2:
+ manager = dbus.Interface(bus.get_object("net.connman.iwd", "/"),
+ "org.freedesktop.DBus.ObjectManager")
+ objects = manager.GetManagedObjects()
+ for path in objects:
+ for interface in objects[path]:
+ if interface == "net.connman.iwd.StationDebug":
+ device = dbus.Interface(bus.get_object("net.connman.iwd", path),
"net.connman.iwd.StationDebug")
+ break
+
+ if not device:
+ print("StationDebug interface not found")
+ exit()
-mac = sys.argv[2].replace(':', '')
+ mac = sys.argv[1]
+else:
+ device = dbus.Interface(bus.get_object("net.connman.iwd", sys.argv[1]),
+ "net.connman.iwd.StationDebug")
+ mac = sys.argv[2]
+mac = mac.replace(':', '')
device.Roam(dbus.ByteArray.fromhex(mac))
--
2.31.1
7 months, 3 weeks
iwd 1.18 doesn't connect to network on boot
by 58e33db1-f428-4823-8cc3-d962d0fb8aa8@slmail.me
Hi,
I'm on Arch Linux and after recent iwd upgrade to version 1.18 I'm no longer connected to my home network when booting. Previous version works just fine. I've managed to workaround the issue simply by going to iwctl and manually doing disconnect/connect every time I boot the computer.
Before doing this iwctl reports 'connecting' state indefinitely. Network coverage is always good. I have the laptop sitting on a table very close to the router and AFAIK, it didn't receive any firmware upgrade recently.
A little bit more of context in case it helps:
/etc/iwd/main.conf
[General]
EnableNetworkConfiguration=true
AddressRandomization=network
[Network]
NameResolvingService=resolvconf
iwevent
Waiting for Wireless Events from interfaces...
10:10:55.646290 wlan0 Scan request completed
10:10:57.801675 wlan0 Scan request completed
10:10:58.106493 wlan0 New Access Point/Cell address:Not-Associated => this is the disconnect
10:11:31.786703 wlan0 Scan request completed
10:11:31.871341 wlan0 Association Request IEs:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
10:11:31.871401 wlan0 Association Response IEs:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
10:11:31.871436 wlan0 New Access Point/Cell address:xx:xx:xx:xx:xx:xx
Distro mantainers just upgraded to latest upstream release, without any other modification on PKGBUILD.
https://github.com/archlinux/svntogit-community/blob/9b59977cbb8eb2ffe42a...
Thanks for helping!
--
Jason
7 months, 3 weeks
[PATCH] netconfig: Add IP configuration properties on Station and P2P
by Andrew Zaborowski
Add the IPv{4,6}Configuration D-Bus interfaces on the station and P2P
objects that expose current netconfig values. Access Point and P2P-GO
are not handled yet.
---
src/dbus.h | 2 +
src/netconfig.c | 651 +++++++++++++++++++++++++++++++++++++++++++-----
src/netconfig.h | 2 +-
src/p2p.c | 4 +-
src/station.c | 8 +-
5 files changed, 604 insertions(+), 63 deletions(-)
diff --git a/src/dbus.h b/src/dbus.h
index 7703b37f..a345f7ac 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -43,6 +43,8 @@
#define IWD_STATION_DIAGNOSTIC_INTERFACE "net.connman.iwd.StationDiagnostic"
#define IWD_AP_DIAGNOSTIC_INTERFACE "net.connman.iwd.AccessPointDiagnostic"
#define IWD_STATION_DEBUG_INTERFACE "net.connman.iwd.StationDebug"
+#define IWD_IPV4_CONFIG_INTERFACE "net.connman.iwd.IPv4Configuration"
+#define IWD_IPV6_CONFIG_INTERFACE "net.connman.iwd.IPv6Configuration"
#define IWD_BASE_PATH "/net/connman/iwd"
#define IWD_AGENT_MANAGER_PATH IWD_BASE_PATH
diff --git a/src/netconfig.c b/src/netconfig.c
index 421270c9..a529fad4 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -49,6 +49,7 @@
#include "src/resolve.h"
#include "src/util.h"
#include "src/ie.h"
+#include "src/dbus.h"
#include "src/netconfig.h"
struct netconfig {
@@ -58,14 +59,23 @@ struct netconfig {
uint8_t rtm_protocol;
uint8_t rtm_v6_protocol;
struct l_rtnl_address *v4_address;
+ struct l_rtnl_address *v6_address;
char **dns4_overrides;
char **dns6_overrides;
+ char **dns4_list;
+ char **dns6_list;
struct ie_fils_ip_addr_response_info *fils_override;
+ char *v4_gateway_str;
+ char *v6_gateway_str;
+ char *v4_domain;
+ char **v6_domains;
const struct l_settings *active_settings;
netconfig_notify_func_t notify;
void *user_data;
+ bool v4_configured;
+ bool v6_configured;
struct resolve *resolve;
@@ -74,6 +84,13 @@ struct netconfig {
uint32_t addr4_add_cmd_id;
uint32_t addr6_add_cmd_id;
uint32_t route4_add_gateway_cmd_id;
+ uint32_t route6_add_cmd_id;
+
+ char *dbus_path;
+ struct interface_data {
+ bool is_ipv4;
+ struct netconfig *netconfig;
+ } v4_data, v6_data;
};
static struct l_netlink *rtnl;
@@ -132,6 +149,7 @@ static void netconfig_free(void *data)
l_dhcp_client_destroy(netconfig->dhcp_client);
l_dhcp6_client_destroy(netconfig->dhcp6_client);
+ l_free(netconfig->dbus_path);
l_free(netconfig);
}
@@ -257,6 +275,18 @@ static void netconfig_set_neighbor_entry_cb(int error,
strerror(-error), error);
}
+static bool netconfig_strv_eq(char *const *a, char *const *b)
+{
+ if (l_strv_length((char **) a) != l_strv_length((char **) b))
+ return false;
+
+ for (; a && *a; a++, b++)
+ if (strcmp(*a, *b))
+ return false;
+
+ return true;
+}
+
static int netconfig_set_dns(struct netconfig *netconfig)
{
const uint8_t *fils_dns4_mac = NULL;
@@ -270,23 +300,25 @@ static int netconfig_set_dns(struct netconfig *netconfig)
char **dns_list;
const struct ie_fils_ip_addr_response_info *fils =
netconfig->fils_override;
+ struct l_dbus *dbus = dbus_get_bus();
- if (!dns4_list && !dns6_list)
- return 0;
+ if (dns6_list) {
+ dns_list = l_malloc(sizeof(char *) *
+ (n_entries4 + n_entries6 + 1));
- dns_list = dns4_list;
+ if (dns4_list)
+ memcpy(dns_list, dns4_list,
+ sizeof(char *) * n_entries4);
- if (dns6_list) {
- dns_list = l_realloc(dns_list,
- sizeof(char *) * (n_entries4 + n_entries6 + 1));
memcpy(dns_list + n_entries4, dns6_list,
sizeof(char *) * (n_entries6 + 1));
- /* Contents now belong to dns_list, so no l_strfreev */
- l_free(dns6_list);
- }
+ } else
+ dns_list = dns4_list;
resolve_set_dns(netconfig->resolve, dns_list);
- l_strv_free(dns_list);
+
+ if (dns6_list)
+ l_free(dns_list);
if (fils_dns4_mac && !l_rtnl_neighbor_set_hwaddr(rtnl,
netconfig->ifindex, AF_INET,
@@ -302,6 +334,30 @@ static int netconfig_set_dns(struct netconfig *netconfig)
NULL))
l_debug("l_rtnl_neighbor_set_hwaddr failed");
+ if (netconfig_strv_eq(netconfig->dns4_list, dns4_list))
+ l_strv_free(dns4_list);
+ else {
+ l_strv_free(netconfig->dns4_list);
+ netconfig->dns4_list = dns4_list;
+
+ if (netconfig->dbus_path && netconfig->v4_configured)
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE,
+ "DomainNameServers");
+ }
+
+ if (netconfig_strv_eq(netconfig->dns6_list, dns6_list))
+ l_strv_free(dns6_list);
+ else {
+ l_strv_free(netconfig->dns6_list);
+ netconfig->dns6_list = dns6_list;
+
+ if (netconfig->dbus_path && netconfig->v6_configured)
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE,
+ "DomainNameServers");
+ }
+
return 0;
}
@@ -328,6 +384,7 @@ static int netconfig_set_domains(struct netconfig *netconfig)
char *v4_domain = NULL;
char **v6_domains = NULL;
char **p;
+ struct l_dbus *dbus = dbus_get_bus();
memset(domains, 0, sizeof(domains));
@@ -358,8 +415,30 @@ static int netconfig_set_domains(struct netconfig *netconfig)
L_ARRAY_SIZE(domains) - 1, *p);
resolve_set_domains(netconfig->resolve, domains);
- l_strv_free(v6_domains);
- l_free(v4_domain);
+
+ if (l_streq0(v4_domain, netconfig->v4_domain))
+ l_free(v4_domain);
+ else {
+ l_free(netconfig->v4_domain);
+ netconfig->v4_domain = v4_domain;
+
+ if (netconfig->dbus_path && netconfig->v4_configured)
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE,
+ "DomainNames");
+ }
+
+ if (netconfig_strv_eq(netconfig->v6_domains, v6_domains))
+ l_strv_free(v6_domains);
+ else {
+ l_strv_free(netconfig->v6_domains);
+ netconfig->v6_domains = v6_domains;
+
+ if (netconfig->dbus_path && netconfig->v6_configured)
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE,
+ "DomainNames");
+ }
return 0;
}
@@ -417,6 +496,8 @@ static char *netconfig_ipv4_get_gateway(struct netconfig *netconfig,
{
const struct l_dhcp_lease *lease;
char *gateway;
+ const struct ie_fils_ip_addr_response_info *fils =
+ netconfig->fils_override;
switch (netconfig->rtm_protocol) {
case RTPROT_STATIC:
@@ -430,15 +511,12 @@ static char *netconfig_ipv4_get_gateway(struct netconfig *netconfig,
return gateway;
case RTPROT_DHCP:
- if (netconfig->fils_override &&
- netconfig->fils_override->ipv4_gateway) {
- gateway = netconfig_ipv4_to_string(
- netconfig->fils_override->ipv4_gateway);
+ if (fils && fils->ipv4_gateway) {
+ gateway = netconfig_ipv4_to_string(fils->ipv4_gateway);
- if (gateway && !l_memeqzero(netconfig->fils_override->
- ipv4_gateway_mac, 6))
- *out_mac = netconfig->fils_override->
- ipv4_gateway_mac;
+ if (gateway && out_mac &&
+ !l_memeqzero(fils->ipv4_gateway_mac, 6))
+ *out_mac = fils->ipv4_gateway_mac;
return gateway;
}
@@ -476,7 +554,7 @@ static struct l_rtnl_address *netconfig_get_static6_address(
prefix_len = strtoul(p, NULL, 10);
if (!unlikely(errno == EINVAL || errno == ERANGE ||
!prefix_len || prefix_len > 128)) {
- l_error("netconfig: Invalid prefix '%s' provided in network"
+ l_error("netconfig: Invalid prefix '%s' provided in network"
" configuration file", p);
return NULL;
}
@@ -492,10 +570,12 @@ no_prefix_len:
static struct l_rtnl_route *netconfig_get_static6_gateway(
struct netconfig *netconfig,
+ char **out_str,
const uint8_t **out_mac)
{
L_AUTO_FREE_VAR(char *, gateway);
struct l_rtnl_route *ret;
+ const uint8_t *mac = NULL;
gateway = l_settings_get_string(netconfig->active_settings,
"IPv6", "Gateway");
@@ -507,7 +587,7 @@ static struct l_rtnl_route *netconfig_get_static6_gateway(
netconfig->fils_override->ipv6_gateway);
if (!l_memeqzero(netconfig->fils_override->ipv6_gateway_mac, 6))
- *out_mac = netconfig->fils_override->ipv6_gateway_mac;
+ mac = netconfig->fils_override->ipv6_gateway_mac;
} else if (!gateway)
return NULL;
@@ -521,6 +601,8 @@ static struct l_rtnl_route *netconfig_get_static6_gateway(
l_rtnl_route_set_priority(ret, ROUTE_PRIORITY_OFFSET);
l_rtnl_route_set_protocol(ret, RTPROT_STATIC);
+ *out_str = l_steal_ptr(gateway);
+ *out_mac = mac;
return ret;
}
@@ -623,6 +705,99 @@ static void netconfig_ifaddr_cmd_cb(int error, uint16_t type,
netconfig_ifaddr_notify(type, data, len, user_data);
}
+static void netconfig_connected(struct netconfig *netconfig)
+{
+ if (netconfig->notify) {
+ netconfig->notify(NETCONFIG_EVENT_CONNECTED,
+ netconfig->user_data);
+ netconfig->notify = NULL;
+ }
+}
+
+static void netconfig_connected_v4(struct netconfig *netconfig)
+{
+ struct l_dbus *dbus = dbus_get_bus();
+
+ netconfig_connected(netconfig);
+
+ netconfig->v4_configured = true;
+
+ if (!netconfig->dbus_path)
+ return;
+
+ if (unlikely(!l_dbus_object_add_interface(dbus,
+ netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE,
+ &netconfig->v4_data)))
+ l_info("Unable to add %s at %s",
+ IWD_IPV4_CONFIG_INTERFACE, netconfig->dbus_path);
+
+ if (!netconfig->v6_configured &&
+ !l_dbus_object_add_interface(dbus, netconfig->dbus_path,
+ L_DBUS_INTERFACE_PROPERTIES,
+ netconfig))
+ /* Properties may already exist on the object, not an error */
+ l_debug("Unable to add %s at %s",
+ L_DBUS_INTERFACE_PROPERTIES, netconfig->dbus_path);
+}
+
+static void netconfig_disconnected_v4(struct netconfig *netconfig)
+{
+ struct l_dbus *dbus = dbus_get_bus();
+
+ netconfig->v4_configured = false;
+
+ if (!netconfig->dbus_path)
+ return;
+
+ if (unlikely(!l_dbus_object_remove_interface(dbus,
+ netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE)))
+ l_info("l_dbus_object_remove_interface failed for %s at %s",
+ IWD_IPV4_CONFIG_INTERFACE, netconfig->dbus_path);
+}
+
+static void netconfig_disconnected_v6(struct netconfig *netconfig)
+{
+ struct l_dbus *dbus = dbus_get_bus();
+
+ netconfig->v6_configured = false;
+
+ if (!netconfig->dbus_path)
+ return;
+
+ if (unlikely(!l_dbus_object_remove_interface(dbus,
+ netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE)))
+ l_info("l_dbus_object_remove_interface failed for %s at %s",
+ IWD_IPV6_CONFIG_INTERFACE, netconfig->dbus_path);
+}
+
+static void netconfig_connected_v6(struct netconfig *netconfig)
+{
+ struct l_dbus *dbus = dbus_get_bus();
+
+ netconfig->v6_configured = true;
+
+ if (!netconfig->dbus_path)
+ return;
+
+ if (unlikely(!l_dbus_object_add_interface(dbus,
+ netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE,
+ &netconfig->v6_data)))
+ l_info("Unable to add %s at %s",
+ IWD_IPV6_CONFIG_INTERFACE, netconfig->dbus_path);
+
+ if (!netconfig->v4_configured &&
+ !l_dbus_object_add_interface(dbus, netconfig->dbus_path,
+ L_DBUS_INTERFACE_PROPERTIES,
+ netconfig))
+ /* Properties may already exist on the object, not an error */
+ l_debug("Unable to add %s at %s",
+ L_DBUS_INTERFACE_PROPERTIES, netconfig->dbus_path);
+}
+
static void netconfig_ifaddr_ipv6_added(struct netconfig *netconfig,
const struct ifaddrmsg *ifa,
uint32_t len)
@@ -732,11 +907,24 @@ static void netconfig_route_add_cmd_cb(int error, uint16_t type,
return;
}
- if (!netconfig->notify)
+ netconfig_connected_v4(netconfig);
+}
+
+static void netconfig_route6_add_cb(int error, uint16_t type,
+ const void *data, uint32_t len,
+ void *user_data)
+{
+ struct netconfig *netconfig = user_data;
+
+ netconfig->route6_add_cmd_id = 0;
+
+ if (error) {
+ l_error("netconfig: Failed to add route. Error %d: %s",
+ error, strerror(-error));
return;
+ }
- netconfig->notify(NETCONFIG_EVENT_CONNECTED, netconfig->user_data);
- netconfig->notify = NULL;
+ netconfig_connected_v6(netconfig);
}
static bool netconfig_ipv4_routes_install(struct netconfig *netconfig)
@@ -775,12 +963,7 @@ static bool netconfig_ipv4_routes_install(struct netconfig *netconfig)
netconfig->rtm_protocol == RTPROT_STATIC ?
"setting file" : "DHCPv4 lease");
- if (netconfig->notify) {
- netconfig->notify(NETCONFIG_EVENT_CONNECTED,
- netconfig->user_data);
- netconfig->notify = NULL;
- }
-
+ netconfig_connected_v4(netconfig);
return true;
}
@@ -847,7 +1030,7 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,
{
struct netconfig *netconfig = user_data;
struct l_rtnl_route *gateway;
- const uint8_t *gateway_mac = NULL;
+ const uint8_t *gateway_mac;
netconfig->addr6_add_cmd_id = 0;
@@ -857,12 +1040,16 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,
return;
}
- gateway = netconfig_get_static6_gateway(netconfig, &gateway_mac);
+ gateway = netconfig_get_static6_gateway(netconfig,
+ &netconfig->v6_gateway_str,
+ &gateway_mac);
if (gateway) {
- L_WARN_ON(!l_rtnl_route_add(rtnl, netconfig->ifindex,
- gateway,
- netconfig_route_generic_cb,
- netconfig, NULL));
+ netconfig->route6_add_cmd_id = l_rtnl_route_add(rtnl,
+ netconfig->ifindex,
+ gateway,
+ netconfig_route6_add_cb,
+ netconfig, NULL);
+ L_WARN_ON(unlikely(!netconfig->route6_add_cmd_id));
l_rtnl_route_free(gateway);
if (gateway_mac && !l_rtnl_neighbor_set_hwaddr(rtnl,
@@ -876,6 +1063,9 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,
netconfig_set_dns(netconfig);
netconfig_set_domains(netconfig);
+
+ if (!netconfig->route6_add_cmd_id)
+ netconfig_connected_v6(netconfig);
}
static void netconfig_ifaddr_del_cmd_cb(int error, uint16_t type,
@@ -898,11 +1088,44 @@ static void netconfig_ifaddr_del_cmd_cb(int error, uint16_t type,
"Error %d: %s", error, strerror(-error));
}
+static bool netconfig_address_cmp_address(const struct l_rtnl_address *a,
+ const struct l_rtnl_address *b)
+{
+ char str_a[INET6_ADDRSTRLEN];
+ char str_b[INET6_ADDRSTRLEN];
+
+ if (a == b)
+ return true;
+
+ if (!a || !b)
+ return false;
+
+ if (!l_rtnl_address_get_address(a, str_a) ||
+ !l_rtnl_address_get_address(b, str_b))
+ return false;
+
+ return !strcmp(str_a, str_b);
+}
+
+static bool netconfig_address_cmp_prefix_len(const struct l_rtnl_address *a,
+ const struct l_rtnl_address *b)
+{
+ if (a == b)
+ return true;
+
+ if (!a || !b)
+ return false;
+
+ return l_rtnl_address_get_prefix_length(a) ==
+ l_rtnl_address_get_prefix_length(b);
+}
+
static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
enum l_dhcp_client_event event,
void *userdata)
{
struct netconfig *netconfig = userdata;
+ struct l_dbus *dbus = dbus_get_bus();
l_debug("DHCPv4 event %d", event);
@@ -912,10 +1135,47 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
netconfig->v4_address,
netconfig_ifaddr_del_cmd_cb,
netconfig, NULL));
- l_rtnl_address_free(netconfig->v4_address);
/* Fall through. */
case L_DHCP_CLIENT_EVENT_LEASE_OBTAINED:
- netconfig->v4_address = netconfig_get_dhcp4_address(netconfig);
+ {
+ char *gateway_str;
+ struct l_rtnl_address *address;
+
+ gateway_str = netconfig_ipv4_get_gateway(netconfig, NULL);
+ if (l_streq0(netconfig->v4_gateway_str, gateway_str))
+ l_free(gateway_str);
+ else {
+ l_free(netconfig->v4_gateway_str);
+ netconfig->v4_gateway_str = gateway_str;
+
+ if (netconfig->dbus_path && netconfig->v4_configured)
+ l_dbus_property_changed(dbus,
+ netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE,
+ "Gateway");
+ }
+
+ address = netconfig_get_dhcp4_address(netconfig);
+
+ if (netconfig->dbus_path && netconfig->v4_configured &&
+ !netconfig_address_cmp_prefix_len(
+ netconfig->v4_address,
+ address))
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE,
+ "Netmask");
+
+ if (netconfig->dbus_path && netconfig->v4_configured &&
+ netconfig_address_cmp_address(
+ netconfig->v4_address,
+ address))
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV4_CONFIG_INTERFACE,
+ "Address");
+
+ l_rtnl_address_free(netconfig->v4_address);
+ netconfig->v4_address = address;
+
if (!netconfig->v4_address) {
l_error("netconfig: Failed to obtain IP addresses from "
"DHCPv4 lease.");
@@ -928,6 +1188,7 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
netconfig_ipv4_ifaddr_add_cmd_cb,
netconfig, NULL)));
break;
+ }
case L_DHCP_CLIENT_EVENT_LEASE_RENEWED:
break;
case L_DHCP_CLIENT_EVENT_LEASE_EXPIRED:
@@ -937,6 +1198,10 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
netconfig, NULL));
l_rtnl_address_free(netconfig->v4_address);
netconfig->v4_address = NULL;
+ l_free(l_steal_ptr(netconfig->v4_gateway_str));
+
+ if (netconfig->v4_configured)
+ netconfig_disconnected_v4(netconfig);
/* Fall through. */
case L_DHCP_CLIENT_EVENT_NO_LEASE:
@@ -960,18 +1225,76 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
void *userdata)
{
struct netconfig *netconfig = userdata;
+ struct l_dbus *dbus = dbus_get_bus();
switch (event) {
case L_DHCP6_CLIENT_EVENT_IP_CHANGED:
case L_DHCP6_CLIENT_EVENT_LEASE_OBTAINED:
case L_DHCP6_CLIENT_EVENT_LEASE_RENEWED:
+ {
+ __auto_type lease =
+ l_dhcp6_client_get_lease(netconfig->dhcp6_client);
+ L_AUTO_FREE_VAR(char *, addr_str) =
+ l_dhcp6_lease_get_address(lease);
+ struct l_rtnl_address *address;
+ __auto_type icmp6 =
+ l_dhcp6_client_get_icmp6(netconfig->dhcp6_client);
+ __auto_type router = l_icmp6_client_get_router(icmp6);
+ char *gateway_str = l_icmp6_router_get_address(router);
+
+ if (l_streq0(netconfig->v6_gateway_str, gateway_str))
+ l_free(gateway_str);
+ else {
+ l_free(netconfig->v6_gateway_str);
+ netconfig->v6_gateway_str = gateway_str;
+
+ if (netconfig->dbus_path && netconfig->v6_configured)
+ l_dbus_property_changed(dbus,
+ netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE,
+ "Gateway");
+ }
+
+ address = l_rtnl_address_new(addr_str,
+ l_dhcp6_lease_get_prefix_length(lease));
+
+ if (netconfig->dbus_path && netconfig->v6_configured &&
+ !netconfig_address_cmp_prefix_len(
+ netconfig->v6_address,
+ address))
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE,
+ "Netmask");
+
+ if (netconfig->dbus_path && netconfig->v6_configured &&
+ netconfig_address_cmp_address(
+ netconfig->v6_address,
+ address))
+ l_dbus_property_changed(dbus, netconfig->dbus_path,
+ IWD_IPV6_CONFIG_INTERFACE,
+ "Address");
+
+ l_rtnl_address_free(netconfig->v6_address);
+ netconfig->v6_address = address;
+
netconfig_set_dns(netconfig);
netconfig_set_domains(netconfig);
+
+ if (!netconfig->v6_configured)
+ netconfig_connected_v6(netconfig);
+
break;
+ }
case L_DHCP6_CLIENT_EVENT_LEASE_EXPIRED:
l_debug("Lease for interface %u expired", netconfig->ifindex);
netconfig_set_dns(netconfig);
netconfig_set_domains(netconfig);
+ l_rtnl_address_free(netconfig->v6_address);
+ netconfig->v6_address = NULL;
+ l_free(l_steal_ptr(netconfig->v6_gateway_str));
+
+ if (netconfig->v6_configured)
+ netconfig_disconnected_v6(netconfig);
/* Fall through */
case L_DHCP6_CLIENT_EVENT_NO_LEASE:
@@ -993,6 +1316,9 @@ static void netconfig_remove_v4_address(struct netconfig *netconfig)
netconfig, NULL));
l_rtnl_address_free(netconfig->v4_address);
netconfig->v4_address = NULL;
+
+ if (netconfig->v4_configured)
+ netconfig_disconnected_v4(netconfig);
}
static void netconfig_reset_v4(struct netconfig *netconfig)
@@ -1000,14 +1326,19 @@ static void netconfig_reset_v4(struct netconfig *netconfig)
if (netconfig->rtm_protocol) {
netconfig_remove_v4_address(netconfig);
- l_strfreev(netconfig->dns4_overrides);
- netconfig->dns4_overrides = NULL;
+ l_strv_free(l_steal_ptr(netconfig->dns4_overrides));
+ l_strv_free(l_steal_ptr(netconfig->dns4_list));
l_dhcp_client_stop(netconfig->dhcp_client);
netconfig->rtm_protocol = 0;
l_acd_destroy(netconfig->acd);
netconfig->acd = NULL;
+
+ l_free(netconfig->v4_gateway_str);
+ netconfig->v4_gateway_str = NULL;
+
+ l_free(l_steal_ptr(netconfig->v4_domain));
}
}
@@ -1117,7 +1448,6 @@ static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig)
static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
{
struct netdev *netdev = netdev_find(netconfig->ifindex);
- struct l_rtnl_address *address = NULL;
if (netconfig->rtm_v6_protocol == RTPROT_UNSPEC) {
l_debug("IPV6 configuration disabled");
@@ -1126,10 +1456,7 @@ static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "0");
- if (netconfig->rtm_v6_protocol == RTPROT_STATIC)
- address = netconfig_get_static6_address(
- netconfig->active_settings);
- else if (netconfig->rtm_v6_protocol == RTPROT_DHCP &&
+ if (netconfig->rtm_v6_protocol == RTPROT_DHCP &&
netconfig->fils_override &&
!l_memeqzero(netconfig->fils_override->ipv6_addr, 16)) {
uint8_t prefix_len = netconfig->fils_override->ipv6_prefix_len;
@@ -1139,11 +1466,12 @@ static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
if (unlikely(!addr_str))
return false;
- if (L_WARN_ON(unlikely(!(address = l_rtnl_address_new(addr_str,
- prefix_len)))))
+ netconfig->v6_address = l_rtnl_address_new(addr_str,
+ prefix_len);
+ if (L_WARN_ON(unlikely(!netconfig->v6_address)))
return false;
- l_rtnl_address_set_noprefixroute(address, true);
+ l_rtnl_address_set_noprefixroute(netconfig->v6_address, true);
/*
* TODO: If netconfig->fils_override->ipv6_lifetime is set,
@@ -1153,12 +1481,12 @@ static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
*/
}
- if (address) {
+ if (netconfig->v6_address) {
L_WARN_ON(!(netconfig->addr6_add_cmd_id =
- l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, address,
+ l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
+ netconfig->v6_address,
netconfig_ipv6_ifaddr_add_cmd_cb,
netconfig, NULL)));
- l_rtnl_address_free(address);
return true;
}
@@ -1273,7 +1601,6 @@ bool netconfig_load_settings(struct netconfig *netconfig,
if (l_settings_has_key(active_settings, "IPv6", "Address")) {
v6_address = netconfig_get_static6_address(active_settings);
- l_rtnl_address_free(v6_address);
if (unlikely(!v6_address)) {
l_error("netconfig: Can't parse IPv6 address");
@@ -1291,11 +1618,14 @@ bool netconfig_load_settings(struct netconfig *netconfig,
if (!v6_enabled)
netconfig->rtm_v6_protocol = RTPROT_UNSPEC;
- else if (v6_address)
+ else if (v6_address) {
+ netconfig->v6_address = l_steal_ptr(v6_address);
netconfig->rtm_v6_protocol = RTPROT_STATIC;
- else
+ } else
netconfig->rtm_v6_protocol = RTPROT_DHCP;
+ l_rtnl_address_free(v6_address);
+
if (send_hostname)
l_dhcp_client_set_hostname(netconfig->dhcp_client, hostname);
@@ -1355,11 +1685,22 @@ bool netconfig_reset(struct netconfig *netconfig)
{
struct netdev *netdev = netdev_find(netconfig->ifindex);
+ if (netconfig->v4_configured)
+ netconfig_disconnected_v4(netconfig);
+
+ if (netconfig->v6_configured)
+ netconfig_disconnected_v6(netconfig);
+
if (netconfig->route4_add_gateway_cmd_id) {
l_netlink_cancel(rtnl, netconfig->route4_add_gateway_cmd_id);
netconfig->route4_add_gateway_cmd_id = 0;
}
+ if (netconfig->route6_add_cmd_id) {
+ l_netlink_cancel(rtnl, netconfig->route6_add_cmd_id);
+ netconfig->route6_add_cmd_id = 0;
+ }
+
if (netconfig->addr4_add_cmd_id) {
l_netlink_cancel(rtnl, netconfig->addr4_add_cmd_id);
netconfig->addr4_add_cmd_id = 0;
@@ -1376,14 +1717,22 @@ bool netconfig_reset(struct netconfig *netconfig)
netconfig_reset_v4(netconfig);
if (netconfig->rtm_v6_protocol) {
- l_strfreev(netconfig->dns6_overrides);
- netconfig->dns6_overrides = NULL;
+ l_rtnl_address_free(netconfig->v6_address);
+ netconfig->v6_address = NULL;
+
+ l_strv_free(l_steal_ptr(netconfig->dns6_overrides));
+ l_strv_free(l_steal_ptr(netconfig->dns6_list));
l_dhcp6_client_stop(netconfig->dhcp6_client);
netconfig->rtm_v6_protocol = 0;
sysfs_write_ipv6_setting(netdev_get_name(netdev),
"disable_ipv6", "1");
+
+ l_free(netconfig->v6_gateway_str);
+ netconfig->v6_gateway_str = NULL;
+
+ l_strv_free(l_steal_ptr(netconfig->v6_domains));
}
l_free(l_steal_ptr(netconfig->fils_override));
@@ -1434,7 +1783,7 @@ void netconfig_handle_fils_ip_resp(struct netconfig *netconfig,
netconfig->fils_override = l_memdup(info, sizeof(*info));
}
-struct netconfig *netconfig_new(uint32_t ifindex)
+struct netconfig *netconfig_new(uint32_t ifindex, const char *dbus_path)
{
struct netdev *netdev = netdev_find(ifindex);
struct netconfig *netconfig;
@@ -1451,6 +1800,7 @@ struct netconfig *netconfig_new(uint32_t ifindex)
netconfig = l_new(struct netconfig, 1);
netconfig->ifindex = ifindex;
+ netconfig->dbus_path = l_strdup(dbus_path);
netconfig->resolve = resolve_new(ifindex);
netconfig->dhcp_client = l_dhcp_client_new(ifindex);
@@ -1483,6 +1833,19 @@ struct netconfig *netconfig_new(uint32_t ifindex)
sysfs_write_ipv6_setting(netdev_get_name(netdev), "accept_ra", "0");
sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "1");
+ /*
+ * Use struct interface_data as interface user_data so that the
+ * property getters can check which interface they're being called
+ * for. For the org.freedesktop.DBus.Properties.{Get,GetAll} calls
+ * we can read the interface name from the first argument but the
+ * getters are also called when the InterfaceAdded signal messages
+ * is being built.
+ */
+ netconfig->v4_data.is_ipv4 = true;
+ netconfig->v4_data.netconfig = netconfig;
+ netconfig->v6_data.is_ipv4 = false;
+ netconfig->v6_data.netconfig = netconfig;
+
return netconfig;
}
@@ -1500,6 +1863,167 @@ void netconfig_destroy(struct netconfig *netconfig)
netconfig_free(netconfig);
}
+static bool netconfig_property_get_method(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+ uint8_t protocol;
+
+ protocol = data->is_ipv4 ? data->netconfig->rtm_protocol :
+ data->netconfig->rtm_v6_protocol;
+
+ l_dbus_message_builder_append_basic(builder, 's',
+ protocol == RTPROT_DHCP ?
+ "auto" : "static");
+ return true;
+}
+
+static bool netconfig_property_get_address(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+ const struct l_rtnl_address *address;
+ char ip_str[INET6_ADDRSTRLEN];
+
+ address = data->is_ipv4 ? data->netconfig->v4_address :
+ data->netconfig->v6_address;
+
+ if (!address || !l_rtnl_address_get_address(address, ip_str))
+ return false;
+
+ l_dbus_message_builder_append_basic(builder, 's', ip_str);
+ return true;
+}
+
+static bool netconfig_property_get_prefix(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+ const struct l_rtnl_address *address;
+ uint8_t prefix_len;
+
+ address = data->is_ipv4 ?
+ data->netconfig->v4_address : data->netconfig->v6_address;
+
+ if (!address || !(prefix_len =
+ l_rtnl_address_get_prefix_length(address)))
+ return false;
+
+ l_dbus_message_builder_append_basic(builder, 'y', &prefix_len);
+ return true;
+}
+
+static bool netconfig_property_get_gateway(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+ const char *gateway_str = data->is_ipv4 ?
+ data->netconfig->v4_gateway_str :
+ data->netconfig->v6_gateway_str;
+
+ if (!gateway_str)
+ return false;
+
+ l_dbus_message_builder_append_basic(builder, 's', gateway_str);
+ return true;
+}
+
+static bool netconfig_property_get_dnses(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+ char **dns_str_list = data->is_ipv4 ?
+ data->netconfig->dns4_list : data->netconfig->dns6_list;
+ char **i;
+
+ if (!dns_str_list)
+ return false;
+
+ l_dbus_message_builder_enter_array(builder, "s");
+
+ for (i = dns_str_list; i && *i; i++)
+ l_dbus_message_builder_append_basic(builder, 's', *i);
+
+ l_dbus_message_builder_leave_array(builder);
+ return true;
+}
+
+static bool netconfig_property_get_v4_domains(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+
+ if (!data->netconfig->v4_domain)
+ return false;
+
+ l_dbus_message_builder_enter_array(builder, "s");
+ l_dbus_message_builder_append_basic(builder, 's',
+ data->netconfig->v4_domain);
+ l_dbus_message_builder_leave_array(builder);
+ return true;
+}
+
+static bool netconfig_property_get_v6_domains(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ void *user_data)
+{
+ const struct interface_data *data = user_data;
+ char **i;
+
+ if (!data->netconfig->v6_domains)
+ return false;
+
+ l_dbus_message_builder_enter_array(builder, "s");
+
+ for (i = data->netconfig->v6_domains; *i; i++)
+ l_dbus_message_builder_append_basic(builder, 's', *i);
+
+ l_dbus_message_builder_leave_array(builder);
+ return true;
+}
+
+static void netconfig_setup_interface(struct l_dbus_interface *interface,
+ bool is_ipv4)
+{
+ l_dbus_interface_property(interface, "Method", 0, "s",
+ netconfig_property_get_method, NULL);
+ l_dbus_interface_property(interface, "Address", 0, "s",
+ netconfig_property_get_address, NULL);
+ l_dbus_interface_property(interface, "PrefixLength", 0, "y",
+ netconfig_property_get_prefix, NULL);
+ l_dbus_interface_property(interface, "Gateway", 0, "s",
+ netconfig_property_get_gateway, NULL);
+ l_dbus_interface_property(interface, "DomainNameServers", 0, "as",
+ netconfig_property_get_dnses, NULL);
+ l_dbus_interface_property(interface, "DomainNames", 0, "as", is_ipv4 ?
+ netconfig_property_get_v4_domains :
+ netconfig_property_get_v6_domains,
+ NULL);
+}
+
+static void netconfig_setup_v4_interface(struct l_dbus_interface *interface)
+{
+ netconfig_setup_interface(interface, true);
+}
+
+static void netconfig_setup_v6_interface(struct l_dbus_interface *interface)
+{
+ netconfig_setup_interface(interface, false);
+}
+
static int netconfig_init(void)
{
uint32_t r;
@@ -1551,6 +2075,14 @@ static int netconfig_init(void)
netconfig_list = l_queue_new();
+ L_WARN_ON(unlikely(!l_dbus_register_interface(dbus_get_bus(),
+ IWD_IPV4_CONFIG_INTERFACE,
+ netconfig_setup_v4_interface,
+ NULL, false)));
+ L_WARN_ON(unlikely(!l_dbus_register_interface(dbus_get_bus(),
+ IWD_IPV6_CONFIG_INTERFACE,
+ netconfig_setup_v6_interface,
+ NULL, false)));
return 0;
error:
@@ -1567,6 +2099,9 @@ static void netconfig_exit(void)
rtnl = NULL;
l_queue_destroy(netconfig_list, netconfig_free);
+
+ l_dbus_unregister_interface(dbus_get_bus(), IWD_IPV4_CONFIG_INTERFACE);
+ l_dbus_unregister_interface(dbus_get_bus(), IWD_IPV6_CONFIG_INTERFACE);
}
IWD_MODULE(netconfig, netconfig_init, netconfig_exit)
diff --git a/src/netconfig.h b/src/netconfig.h
index fa46c7c8..5d54d9cc 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -45,5 +45,5 @@ bool netconfig_get_fils_ip_req(struct netconfig *netconfig,
void netconfig_handle_fils_ip_resp(struct netconfig *netconfig,
const struct ie_fils_ip_addr_response_info *info);
-struct netconfig *netconfig_new(uint32_t ifindex);
+struct netconfig *netconfig_new(uint32_t ifindex, const char *dbus_path);
void netconfig_destroy(struct netconfig *netconfig);
diff --git a/src/p2p.c b/src/p2p.c
index 3328271b..b68e4f7c 100644
--- a/src/p2p.c
+++ b/src/p2p.c
@@ -1320,7 +1320,9 @@ static void p2p_start_client_netconfig(struct p2p_device *dev)
struct l_settings *settings;
if (!dev->conn_netconfig) {
- dev->conn_netconfig = netconfig_new(ifindex);
+ const char *peer_path = p2p_peer_get_path(dev->conn_peer);
+
+ dev->conn_netconfig = netconfig_new(ifindex, peer_path);
if (!dev->conn_netconfig) {
p2p_connect_failed(dev);
return;
diff --git a/src/station.c b/src/station.c
index 6de5fd4a..105d0ad8 100644
--- a/src/station.c
+++ b/src/station.c
@@ -3577,6 +3577,7 @@ static struct station *station_create(struct netdev *netdev)
struct station *station;
struct l_dbus *dbus = dbus_get_bus();
bool autoconnect = true;
+ const char *path;
station = l_new(struct station, 1);
watchlist_init(&station->state_watches, NULL);
@@ -3594,11 +3595,12 @@ static struct station *station_create(struct netdev *netdev)
l_queue_push_head(station_list, station);
- l_dbus_object_add_interface(dbus, netdev_get_path(netdev),
- IWD_STATION_INTERFACE, station);
+ path = netdev_get_path(netdev);
+ l_dbus_object_add_interface(dbus, path, IWD_STATION_INTERFACE, station);
if (netconfig_enabled)
- station->netconfig = netconfig_new(netdev_get_ifindex(netdev));
+ station->netconfig = netconfig_new(netdev_get_ifindex(netdev),
+ path);
station->anqp_pending = l_queue_new();
--
2.30.2
7 months, 4 weeks
[PATCH v2 1/4] ie: parse operating class/channel for ie_owe_transition_info
by James Prestwood
This operating class/channel is also verified while parsing and
parsing will fail if band_oci_frequency fails.
This does put a requirement on anything that uses ie.c to also
include band.c. Makefile has been updated.
---
src/ie.c | 28 +++++++++++++++++-----------
src/ie.h | 2 ++
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/src/ie.c b/src/ie.c
index 0abc01cb..f0163ea2 100644
--- a/src/ie.c
+++ b/src/ie.c
@@ -33,6 +33,7 @@
#include "src/util.h"
#include "src/crypto.h"
#include "src/ie.h"
+#include "src/band.h"
const unsigned char ieee_oui[3] = { 0x00, 0x0f, 0xac };
const unsigned char microsoft_oui[3] = { 0x00, 0x50, 0xf2 };
@@ -2504,6 +2505,10 @@ int ie_parse_owe_transition(const void *data, size_t len,
struct ie_owe_transition_info *info)
{
const uint8_t *ie = data;
+ const uint8_t *bssid;
+ const uint8_t *ssid;
+ uint8_t oper_class = 0;
+ uint8_t channel = 0;
size_t slen;
if (len < 14 || ie[0] != IE_TYPE_VENDOR_SPECIFIC)
@@ -2521,22 +2526,23 @@ int ie_parse_owe_transition(const void *data, size_t len,
*
* "Band Info and Channel Info are optional fields. If configured,
* both fields shall be included in an OWE Transition Mode element"
- *
- * TODO: Support Band/Channel bytes:
- * For the time being the OWE transition AP is assumed to be on the same
- * channel as the open AP. This means there should be no band/channel
- * bytes at the end of the IE. Currently hostapd has no support for this
- * so it can be skipped. In addition 802.11 Appendix E-1 needs to be
- * encoded as a table to map Country/operating class to channels to make
- * any sense of it.
*/
- if (len != slen + 13)
+ if (len != slen + 13 && len != slen + 15)
return -ENOMSG;
- memcpy(info->bssid, ie + 6, 6);
+ bssid = ie + 6;
+ ssid = ie + 13;
+
+ if (len == slen + 15) {
+ oper_class = l_get_u8(ie + 13 + slen);
+ channel = l_get_u8(ie + 14 + slen);
+ }
- memcpy(info->ssid, ie + 13, slen);
+ memcpy(info->bssid, bssid, 6);
+ memcpy(info->ssid, ssid, slen);
info->ssid_len = slen;
+ info->oper_class = oper_class;
+ info->channel = channel;
return 0;
}
diff --git a/src/ie.h b/src/ie.h
index 81388496..c912d6c3 100644
--- a/src/ie.h
+++ b/src/ie.h
@@ -493,6 +493,8 @@ struct ie_owe_transition_info {
uint8_t bssid[6];
uint8_t ssid[32];
size_t ssid_len;
+ uint8_t oper_class;
+ uint8_t channel;
};
extern const unsigned char ieee_oui[3];
--
2.31.1
7 months, 4 weeks
[PATCH 1/6] ie: add info struct for OWE transition
by James Prestwood
These members are currently stored in scan_bss but with the
addition of operating class/band info this will become 5
separate members. This is a bit excessive to store in scan_bss
separately so instead this structure can hold everything related
to the OWE transition IE.
---
src/ie.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/ie.h b/src/ie.h
index f64072b3..02892724 100644
--- a/src/ie.h
+++ b/src/ie.h
@@ -488,6 +488,12 @@ struct ie_fils_ip_addr_response_info {
uint8_t ipv6_lifetime; /* Zero if not provided */
};
+struct ie_owe_transition_info {
+ uint8_t bssid[6];
+ uint8_t ssid[32];
+ size_t ssid_len;
+};
+
extern const unsigned char ieee_oui[3];
extern const unsigned char microsoft_oui[3];
extern const unsigned char wifi_alliance_oui[3];
--
2.31.1
7 months, 4 weeks
Possible bug - DISASSOC_LOW_ACK
by Michael Johnson
Hi everyone,
In my use case that involves heavy roaming, I've been noticing that
occasionally `iwd` disconnects completely from the network before
rejoining which can cause a few seconds of downtime. In addition to
the downtime it seems to put the network in an odd state which is
hitting a bunch of corner cases in code that uses the network more
than just a normal disconnect. Looking at the logs, it seems like iwd
might be getting locked up somewhere as it also stops reacting to
threshold notifications?
I'm not sure how to reproduce this as it's relatively rare, happening
3 times in about a week. The logs below are from a machine running
version 1.17.
I'll see if I can start a rolling iwmon capture to get more info. Is
there anything else that would be useful?
```
Sep 21 15:40:22.138376 p3-683 iwd[425]:
src/netdev.c:netdev_mlme_notify() MLME notification Frame TX
Status(60)
Sep 21 15:40:22.140101 p3-683 iwd[425]:
src/netdev.c:netdev_unicast_notify() Unicast notification 59
Sep 21 15:40:22.140101 p3-683 iwd[425]:
src/station.c:station_early_neighbor_report_cb() ifindex: 5, error:
0()
Sep 21 15:40:22.140101 p3-683 iwd[425]:
src/station.c:parse_neighbor_report() Neighbor report received for
ea:9e:38:78:07:b1: ch 44 (oper class 0), MD not set
Sep 21 15:40:22.141734 p3-683 iwd[425]:
src/netdev.c:netdev_unicast_notify() Unicast notification 59
Sep 21 15:40:22.142298 p3-683 iwd[425]:
src/netdev.c:netdev_unicast_notify() Unicast notification 59
Sep 21 15:40:22.166050 p3-683 kernel: wlan0: Limiting TX power to 27
(30 - 3) dBm as advertised by ea:9e:38:78:08:71
Sep 21 15:40:22.473706 p3-683 iwd[425]:
src/netdev.c:netdev_mlme_notify() MLME notification Notify CQM(64)
Sep 21 15:41:12.767433 p3-683 iwd[425]:
src/netdev.c:netdev_mlme_notify() MLME notification Notify CQM(64)
Sep 21 15:46:41.998639 p3-683 kernel: wlan0: deauthenticated from
ea:9e:38:78:08:71 (Reason: 34=DISASSOC_LOW_ACK)
Sep 21 15:46:41.997194 p3-683 systemd-networkd[341]: wlan0: Lost carrier
Sep 21 15:46:41.999173 p3-683 iwd[425]:
src/netdev.c:netdev_link_notify() event 16 on ifindex 5
Sep 21 15:46:42.107670 p3-683 iwd[425]:
src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
Sep 21 15:46:42.111369 p3-683 iwd[425]:
src/netdev.c:netdev_mlme_notify() MLME notification Deauthenticate(39)
Sep 21 15:46:42.111369 p3-683 iwd[425]:
src/netdev.c:netdev_deauthenticate_event()
Sep 21 15:46:42.111369 p3-683 iwd[425]:
src/netdev.c:netdev_mlme_notify() MLME notification Disconnect(48)
Sep 21 15:46:42.111369 p3-683 iwd[425]: src/netdev.c:netdev_disconnect_event()
Sep 21 15:46:42.111369 p3-683 iwd[425]: Received Deauthentication
event, reason: 34, from_ap: true
Sep 21 15:46:42.111369 p3-683 iwd[425]:
src/station.c:station_disconnect_event() 5
Sep 21 15:46:42.111369 p3-683 iwd[425]: src/station.c:station_disassociated() 5
Sep 21 15:46:42.111369 p3-683 iwd[425]:
src/resolve.c:resolve_systemd_revert() ifindex: 5
Sep 21 15:46:42.136257 p3-683 iwd[425]:
src/station.c:station_enter_state() Old State: connected, new state:
disconnected
Sep 21 15:46:42.136257 p3-683 iwd[425]:
src/station.c:station_enter_state() Old State: disconnected, new
state: autoconnect_quick
```
Kind Regards,
Michael
7 months, 4 weeks
[PATCH 1/4] ie: parse RSNXE Present bit
by James Prestwood
---
src/ie.c | 1 +
src/ie.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/ie.c b/src/ie.c
index 0440373c..b2a8102a 100644
--- a/src/ie.c
+++ b/src/ie.c
@@ -1732,6 +1732,7 @@ int ie_parse_fast_bss_transition(struct ie_tlv_iter *iter, uint32_t mic_len,
memset(info, 0, sizeof(*info));
+ info->rsnxe_used = test_bit(data, 0);
info->mic_element_count = data[1];
memcpy(info->mic, data + 2, mic_len);
diff --git a/src/ie.h b/src/ie.h
index f64072b3..844e9950 100644
--- a/src/ie.h
+++ b/src/ie.h
@@ -419,6 +419,7 @@ enum ie_bss_capability {
struct ie_ft_info {
uint8_t mic_element_count;
+ bool rsnxe_used;
uint8_t mic[24];
uint8_t anonce[32];
uint8_t snonce[32];
--
2.31.1
7 months, 4 weeks
[PATCH v2] src/sae.c: fix build without reallocarray
by Fabrice Fontaine
reallocarray has been added to glibc relatively recently (version 2.26,
from 2017) and apparently not all users run new enough glibc. Moreover,
reallocarray is not available with uclibc-ng. So use realloc if
reallocarray is not available to avoid the following build failure
raised since commit 891b78e9e892a3bcd800eb3a298e6380e9a15dd1:
/home/giuliobenetti/autobuild/run/instance-3/output-1/host/lib/gcc/xtensa-buildroot-linux-uclibc/10.3.0/../../../../xtensa-buildroot-linux-uclibc/bin/ld: src/sae.o: in function `sae_rx_authenticate':
sae.c:(.text+0xd74): undefined reference to `reallocarray'
Fixes:
- http://autobuild.buildroot.org/results/c6d3f86282c44645b4f1c61882dc63ccfc...
---
Changes v1 -> v2 (after review of Denis Kenzior):
- Remove SoB
- Add reallocarray to missing.h
configure.ac | 1 +
src/missing.h | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/configure.ac b/configure.ac
index c6250401..51d9da93 100644
--- a/configure.ac
+++ b/configure.ac
@@ -129,6 +129,7 @@ AC_DEFINE_UNQUOTED(WIRED_STORAGEDIR, "${wired_storagedir}",
AC_CHECK_FUNCS(explicit_bzero)
AC_CHECK_FUNCS(rawmemchr)
+AC_CHECK_FUNCS(reallocarray)
AC_CHECK_HEADERS(linux/types.h linux/if_alg.h)
diff --git a/src/missing.h b/src/missing.h
index 2cc80aee..a5b92952 100644
--- a/src/missing.h
+++ b/src/missing.h
@@ -37,3 +37,10 @@ _Pragma("GCC diagnostic ignored \"-Wstringop-overflow=\"")
_Pragma("GCC diagnostic pop")
}
#endif
+
+#ifndef HAVE_REALLOCARRAY
+static inline void *reallocarray(void *ptr, size_t nmemb, size_t size)
+{
+ return realloc(ptr, nmemb * size);
+}
+#endif
--
2.33.0
8 months
[PATCH] src/sae.c: Use realloc(3) instead of reallocarray(3)
by Fabrice Fontaine
reallocarray(3) has been added to glibc relatively recently (version
2.26, from 2017) and apparently not all users run new enough glibc.
Moreover, reallocarray is not available with uclibc-ng. Just use
realloc(3) for now since in this case there's no real risk of overflow.
This will avoid the following build failure since commit
891b78e9e892a3bcd800eb3a298e6380e9a15dd1:
/home/giuliobenetti/autobuild/run/instance-3/output-1/host/lib/gcc/xtensa-buildroot-linux-uclibc/10.3.0/../../../../xtensa-buildroot-linux-uclibc/bin/ld: src/sae.o: in function `sae_rx_authenticate':
sae.c:(.text+0xd74): undefined reference to `reallocarray'
Fixes:
- http://autobuild.buildroot.org/results/c6d3f86282c44645b4f1c61882dc63ccfc...
Signed-off-by: Fabrice Fontaine <fontaine.fabrice(a)gmail.com>
---
src/sae.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/sae.c b/src/sae.c
index 7e6377f5..d04891e7 100644
--- a/src/sae.c
+++ b/src/sae.c
@@ -104,7 +104,7 @@ static void sae_rejected_groups_append(struct sae_sm *sm, uint16_t group)
uint16_t i;
if (!sm->rejected_groups) {
- sm->rejected_groups = reallocarray(NULL, 2, sizeof(uint16_t));
+ sm->rejected_groups = realloc(NULL, 2 * sizeof(uint16_t));
sm->rejected_groups[0] = 1;
sm->rejected_groups[1] = group;
return;
@@ -114,8 +114,8 @@ static void sae_rejected_groups_append(struct sae_sm *sm, uint16_t group)
if (sm->rejected_groups[i] == group)
return;
- sm->rejected_groups = reallocarray(sm->rejected_groups,
- i + 1, sizeof(uint16_t));
+ sm->rejected_groups = realloc(sm->rejected_groups,
+ (i + 1) * sizeof(uint16_t));
sm->rejected_groups[0] += 1;
sm->rejected_groups[i] = group;
}
--
2.33.0
8 months