[PATCH] station: Add missing netconfig_reset()
by Andrew Zaborowski
On NETDEV_EVENT_DISCONNECT_BY_* events during netconfig, we'd forget to
call netconfig_reset() before trying a new netconfig_configure()
resulting in the "netconfig: Failed to start DHCPv4 client for interface
%u" warning and a L_WARN_ON. Add the missing call.
---
src/station.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/station.c b/src/station.c
index 934815f2..1c073fc1 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2810,6 +2810,9 @@ static void station_disconnect_event(struct station *station, void *event_data)
switch (station->state) {
case STATION_STATE_CONNECTING:
case STATION_STATE_CONNECTING_AUTO:
+ if (station->netconfig)
+ netconfig_reset(station->netconfig);
+
station_connect_cb(station->netdev,
NETDEV_RESULT_HANDSHAKE_FAILED,
event_data, station);
--
2.30.2
9 months
[PATCH] station: Move netconfig_reset() to common path
by Andrew Zaborowski
Move the netconfig_reset calls to inside
station_reset_connection_state() instead of having each caller do
netconfig_reset() followed by station_reset_connection_state(). One of
the callers was missing the netconfig_reset() and this was resulting in
the "netconfig: Failed to start DHCPv4 client for interface %u" warning.
---
src/station.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/src/station.c b/src/station.c
index 934815f2..61649c74 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1501,6 +1501,9 @@ static void station_reset_connection_state(struct station *station)
if (!network)
return;
+ if (station->netconfig)
+ netconfig_reset(station->netconfig);
+
if (station->state == STATION_STATE_CONNECTED ||
station->state == STATION_STATE_CONNECTING ||
station->state == STATION_STATE_CONNECTING_AUTO ||
@@ -1530,9 +1533,6 @@ static void station_disassociated(struct station *station)
{
l_debug("%u", netdev_get_ifindex(station->netdev));
- if (station->netconfig)
- netconfig_reset(station->netconfig);
-
station_reset_connection_state(station);
station_enter_state(station, STATION_STATE_DISCONNECTED);
@@ -2930,9 +2930,6 @@ static void station_disconnect_onconnect(struct station *station,
return;
}
- if (station->netconfig)
- netconfig_reset(station->netconfig);
-
station_reset_connection_state(station);
station_enter_state(station, STATION_STATE_DISCONNECTING);
@@ -3234,9 +3231,6 @@ int station_disconnect(struct station *station)
if (!station->connected_bss)
return -ENOTCONN;
- if (station->netconfig)
- netconfig_reset(station->netconfig);
-
/*
* If the disconnect somehow fails we won't know if we're still
* connected so we may as well indicate now that we're no longer
--
2.30.2
9 months
[PATCH 1/8] netconfig: Track the IPv6 route add netlink command
by Andrew Zaborowski
For symmetry with IPv4, save the command id for this netlink command so
we can later add logic to the callback as well as be able to cancel the
command. No functional change in this commit alone.
---
src/netconfig.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/netconfig.c b/src/netconfig.c
index 421270c9..da775480 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -74,6 +74,7 @@ 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;
};
static struct l_netlink *rtnl;
@@ -739,6 +740,21 @@ static void netconfig_route_add_cmd_cb(int error, uint16_t type,
netconfig->notify = NULL;
}
+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;
+ }
+}
+
static bool netconfig_ipv4_routes_install(struct netconfig *netconfig)
{
L_AUTO_FREE_VAR(char *, gateway) = NULL;
@@ -859,10 +875,12 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,
gateway = netconfig_get_static6_gateway(netconfig, &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,
@@ -1360,6 +1378,11 @@ bool netconfig_reset(struct netconfig *netconfig)
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;
--
2.30.2
9 months
[PATCH 1/6] doc: add testing option to hostapd.config
by James Prestwood
This is required to be built in for hostapd to rekey on command.
---
doc/hostapd.config | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/hostapd.config b/doc/hostapd.config
index 91d1b4cf..c114e127 100644
--- a/doc/hostapd.config
+++ b/doc/hostapd.config
@@ -36,3 +36,4 @@ CONFIG_OCV=y
CONFIG_OWE=y
CONFIG_DPP=y
CONFIG_SAE=y
+CONFIG_TESTING_OPTIONS=y
--
2.31.1
9 months
[PATCH v3 1/5] ft: check authenticator_ie from ft_ds_info, not handshake
by James Prestwood
The handshake contains the current BSS's RSNE/WPA which may differ
from the FT-over-DS target. When verifying the target BSS's RSNE/WPA
IE needs to be checked, not the current BSS.
---
src/ft.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/ft.c b/src/ft.c
index fecb4c0e..7a4b16f3 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -354,6 +354,7 @@ static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
}
static int ft_parse_ies(struct handshake_state *hs,
+ const uint8_t *authenticator_ie,
const uint8_t *ies, size_t ies_len,
const uint8_t **mde_out,
const uint8_t **fte_out)
@@ -394,8 +395,7 @@ static int ft_parse_ies(struct handshake_state *hs,
is_rsn = hs->supplicant_ie != NULL;
if (is_rsn) {
- if (!ft_verify_rsne(rsne, hs->pmk_r0_name,
- hs->authenticator_ie))
+ if (!ft_verify_rsne(rsne, hs->pmk_r0_name, authenticator_ie))
goto ft_error;
} else if (rsne)
goto ft_error;
@@ -485,7 +485,8 @@ bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
const uint8_t *fte = NULL;
bool is_rsn = hs->supplicant_ie != NULL;
- if (ft_parse_ies(hs, ies, ies_len, &mde, &fte) < 0)
+ if (ft_parse_ies(hs, info->authenticator_ie, ies, ies_len,
+ &mde, &fte) < 0)
return false;
if (!mde_equal(info->mde, mde))
@@ -516,7 +517,8 @@ static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
if (!ies)
goto ft_error;
- if (ft_parse_ies(hs, ies, ies_len, &mde, &fte) < 0)
+ if (ft_parse_ies(hs, hs->authenticator_ie, ies, ies_len,
+ &mde, &fte) < 0)
goto ft_error;
if (!mde_equal(hs->mde, mde))
--
2.31.1
9 months
[PATCH v2 1/5] ft: check authenticator_ie from ft_ds_info, not handshake
by James Prestwood
The handshake contains the current BSS's RSNE/WPA which may differ
from the FT-over-DS target. When verifying the target BSS's RSNE/WPA
IE needs to be checked, not the current BSS.
---
src/ft.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/ft.c b/src/ft.c
index fecb4c0e..7a4b16f3 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -354,6 +354,7 @@ static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
}
static int ft_parse_ies(struct handshake_state *hs,
+ const uint8_t *authenticator_ie,
const uint8_t *ies, size_t ies_len,
const uint8_t **mde_out,
const uint8_t **fte_out)
@@ -394,8 +395,7 @@ static int ft_parse_ies(struct handshake_state *hs,
is_rsn = hs->supplicant_ie != NULL;
if (is_rsn) {
- if (!ft_verify_rsne(rsne, hs->pmk_r0_name,
- hs->authenticator_ie))
+ if (!ft_verify_rsne(rsne, hs->pmk_r0_name, authenticator_ie))
goto ft_error;
} else if (rsne)
goto ft_error;
@@ -485,7 +485,8 @@ bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
const uint8_t *fte = NULL;
bool is_rsn = hs->supplicant_ie != NULL;
- if (ft_parse_ies(hs, ies, ies_len, &mde, &fte) < 0)
+ if (ft_parse_ies(hs, info->authenticator_ie, ies, ies_len,
+ &mde, &fte) < 0)
return false;
if (!mde_equal(info->mde, mde))
@@ -516,7 +517,8 @@ static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
if (!ies)
goto ft_error;
- if (ft_parse_ies(hs, ies, ies_len, &mde, &fte) < 0)
+ if (ft_parse_ies(hs, hs->authenticator_ie, ies, ies_len,
+ &mde, &fte) < 0)
goto ft_error;
if (!mde_equal(hs->mde, mde))
--
2.31.1
9 months
[PATCH 1/9] fils: support OCI in reassociation
by James Prestwood
---
src/fils.c | 35 +++++++++++++++++++++++++++++++++--
src/fils.h | 2 ++
src/netdev.c | 1 +
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/src/fils.c b/src/fils.c
index f661f1bf..c05281bb 100644
--- a/src/fils.c
+++ b/src/fils.c
@@ -37,6 +37,7 @@
#include "src/missing.h"
#include "src/erp.h"
#include "src/auth-proto.h"
+#include "src/band.h"
#define FILS_NONCE_LEN 16
#define FILS_SESSION_LEN 8
@@ -49,6 +50,7 @@ struct fils_sm {
fils_tx_authenticate_func_t auth;
fils_tx_associate_func_t assoc;
+ fils_get_oci_func_t get_oci;
uint8_t nonce[FILS_NONCE_LEN];
uint8_t anonce[FILS_NONCE_LEN];
@@ -148,12 +150,13 @@ static int fils_derive_key_data(struct fils_sm *fils)
uint8_t data[44];
uint8_t *ptr = data;
size_t hash_len;
- struct iovec iov[4];
+ struct iovec iov[5];
size_t iov_elems = 0;
size_t fils_ft_len = 0;
bool sha384;
size_t ie_len;
uint8_t *rsne = NULL;
+ uint8_t oci[6];
rmsk = erp_get_rmsk(fils->erp, &rmsk_len);
@@ -302,6 +305,23 @@ static int fils_derive_key_data(struct fils_sm *fils)
iov_elems += 1;
}
+ /*
+ * IEEE 802.11 Section 12.11.2.6.2
+ * "If dot11RSNAOperatingChannelValidationActivated is true and AP
+ * indicates OCVC capability, the STA shall include OCI element in the
+ * request"
+ */
+ if (fils->hs->supplicant_ocvc && fils->hs->chandef) {
+ oci[0] = IE_TYPE_EXTENSION;
+ oci[1] = 4;
+ oci[2] = IE_TYPE_OCI & 0xff;
+ oci_from_chandef(fils->hs->chandef, oci + 3);
+
+ iov[iov_elems].iov_base = oci;
+ iov[iov_elems].iov_len = 6;
+ iov_elems++;
+ }
+
memcpy(data, fils->nonce, sizeof(fils->nonce));
memcpy(data + sizeof(fils->nonce), fils->anonce, sizeof(fils->anonce));
@@ -436,12 +456,20 @@ static int fils_rx_authenticate(struct auth_proto *driver, const uint8_t *frame,
if (erp_rx_packet(fils->erp, wrapped, wrapped_len) < 0)
goto invalid_ies;
- return fils_derive_key_data(fils);
+ return fils->get_oci(fils->user_data);
+
invalid_ies:
return MMPDU_STATUS_CODE_INVALID_ELEMENT;
}
+static int fils_rx_oci(struct auth_proto *driver)
+{
+ struct fils_sm *fils = l_container_of(driver, struct fils_sm, ap);
+
+ return fils_derive_key_data(fils);
+}
+
static int fils_rx_associate(struct auth_proto *driver, const uint8_t *frame,
size_t len)
{
@@ -564,6 +592,7 @@ invalid_ies:
struct auth_proto *fils_sm_new(struct handshake_state *hs,
fils_tx_authenticate_func_t auth,
fils_tx_associate_func_t assoc,
+ fils_get_oci_func_t get_oci,
void *user_data)
{
struct fils_sm *fils;
@@ -572,11 +601,13 @@ struct auth_proto *fils_sm_new(struct handshake_state *hs,
fils->auth = auth;
fils->assoc = assoc;
+ fils->get_oci = get_oci;
fils->user_data = user_data;
fils->hs = hs;
fils->ap.start = fils_start;
fils->ap.free = fils_free;
+ fils->ap.rx_oci = fils_rx_oci;
fils->ap.rx_authenticate = fils_rx_authenticate;
fils->ap.rx_associate = fils_rx_associate;
diff --git a/src/fils.h b/src/fils.h
index f9e83d94..3da4ee4e 100644
--- a/src/fils.h
+++ b/src/fils.h
@@ -30,8 +30,10 @@ typedef void (*fils_tx_associate_func_t)(struct iovec *iov, size_t iov_len,
const uint8_t *kek, size_t kek_len,
const uint8_t *nonces, size_t nonces_len,
void *user_data);
+typedef int (*fils_get_oci_func_t)(void *user_data);
struct auth_proto *fils_sm_new(struct handshake_state *hs,
fils_tx_authenticate_func_t auth,
fils_tx_associate_func_t assoc,
+ fils_get_oci_func_t get_oci,
void *user_data);
diff --git a/src/netdev.c b/src/netdev.c
index 91fffeb3..38598259 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -3689,6 +3689,7 @@ static void netdev_connect_common(struct netdev *netdev,
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
netdev->ap = fils_sm_new(hs, netdev_fils_tx_authenticate,
netdev_fils_tx_associate,
+ netdev_get_oci,
netdev);
break;
default:
--
2.31.1
9 months
[PATCH v3] ft: set OCVC false for FT-over-DS
by James Prestwood
FT-over-DS cannot use OCV due to how the kernel works. This means
we could connect initially with OCVC set, but a FT-over-DS attempt
needs to unset OCVC. Set OCVC false when rebuilding the RSNE for
reassociation.
---
src/ft.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/ft.c b/src/ft.c
index 9c5bc8b0..52506301 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -43,6 +43,8 @@ struct ft_sm {
ft_get_oci get_oci;
void *user_data;
+
+ bool over_ds:1;
};
/*
@@ -236,6 +238,10 @@ static int ft_tx_reassociate(struct ft_sm *ft)
rsn_info.num_pmkids = 1;
rsn_info.pmkids = hs->pmk_r1_name;
+ /* Always set OCVC false for FT-over-DS */
+ if (ft->over_ds)
+ rsn_info.ocvc = false;
+
rsne = alloca(256);
ie_build_rsne(&rsn_info, rsne);
@@ -929,6 +935,7 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
ft->tx_assoc = tx_assoc;
ft->hs = hs;
ft->user_data = user_data;
+ ft->over_ds = true;
ft->ap.rx_associate = ft_rx_associate;
ft->ap.start = ft_over_ds_start;
--
2.31.1
9 months
[PATCH v2 1/9] doc: add DisableOCV setting
by James Prestwood
---
src/iwd.config.rst | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/iwd.config.rst b/src/iwd.config.rst
index 78ec284e..5cd2b06b 100644
--- a/src/iwd.config.rst
+++ b/src/iwd.config.rst
@@ -181,6 +181,13 @@ The group ``[General]`` contains general settings.
off by default. If you want to easily utilize Hotspot 2.0 networks,
then setting ``DisableANQP`` to ``false`` is recommended.
+ * - DisableOCV
+ - Value: **false**, true
+
+ Disable Operating Channel Validation. Support for this is not advertised
+ by the kernel so if kernels/drivers exist which don't support OCV it can
+ be disabled here.
+
Network
-------
--
2.31.1
9 months
[PATCH] netconfig: Set address at configure time
by Denis Kenzior
netconfig_load_settings is called when establishing a new initial
association to a network. This function tries to update dhcp/dhcpv6
clients with the MAC address of the netdev being used. However, it is
too early to update the MAC here since netdev might need to powercycle
the underlying network device in order to update the MAC (i.e. when
AddressRandomization="network" is used).
If the MAC is set incorrectly, DHCP clients are unable to obtain the
lease properly and station is stuck in "connecting" mode indefinitely.
Fix this by delaying MAC address update until netconfig_configure() is
invoked.
Fixes: ad228461abbf ("netconfig: Move loading settings to new method, refactor")
---
src/netconfig.c | 17 +++++++++--------
src/netconfig.h | 3 +--
src/p2p.c | 3 +--
src/station.c | 3 +--
4 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/src/netconfig.c b/src/netconfig.c
index 421270c98c6b..1d6edcab02bf 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -1046,6 +1046,7 @@ static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data)
static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig)
{
+ struct netdev *netdev = netdev_find(netconfig->ifindex);
bool set_address = (netconfig->rtm_protocol == RTPROT_STATIC);
if (netconfig->rtm_protocol == RTPROT_DHCP &&
@@ -1106,6 +1107,9 @@ static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig)
return true;
}
+ l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER,
+ netdev_get_address(netdev), ETH_ALEN);
+
if (l_dhcp_client_start(netconfig->dhcp_client))
return true;
@@ -1162,7 +1166,10 @@ static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
return true;
}
- /* DHCP */
+ /* DHCPv6 or RA, update MAC */
+ l_dhcp6_client_set_address(netconfig->dhcp6_client, ARPHRD_ETHER,
+ netdev_get_address(netdev), ETH_ALEN);
+
return true;
}
@@ -1196,8 +1203,7 @@ static int validate_dns_list(int family, char **dns_list)
}
bool netconfig_load_settings(struct netconfig *netconfig,
- const struct l_settings *active_settings,
- const uint8_t *mac_address)
+ const struct l_settings *active_settings)
{
char *mdns;
bool send_hostname;
@@ -1302,11 +1308,6 @@ bool netconfig_load_settings(struct netconfig *netconfig,
resolve_set_mdns(netconfig->resolve, mdns);
l_free(mdns);
- l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER,
- mac_address, ETH_ALEN);
- l_dhcp6_client_set_address(netconfig->dhcp6_client, ARPHRD_ETHER,
- mac_address, ETH_ALEN);
-
netconfig->active_settings = active_settings;
netconfig->dns4_overrides = dns4_overrides;
netconfig->dns6_overrides = dns6_overrides;
diff --git a/src/netconfig.h b/src/netconfig.h
index fa46c7c80236..3c4e7641ed2a 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -32,8 +32,7 @@ typedef void (*netconfig_notify_func_t)(enum netconfig_event event,
void *user_data);
bool netconfig_load_settings(struct netconfig *netconfig,
- const struct l_settings *active_settings,
- const uint8_t *mac_address);
+ const struct l_settings *active_settings);
bool netconfig_configure(struct netconfig *netconfig,
netconfig_notify_func_t notify,
void *user_data);
diff --git a/src/p2p.c b/src/p2p.c
index 62df1ea5a7d0..90779f9500e5 100644
--- a/src/p2p.c
+++ b/src/p2p.c
@@ -1328,8 +1328,7 @@ static void p2p_start_client_netconfig(struct p2p_device *dev)
settings = dev->conn_netconfig_settings ?: p2p_dhcp_settings;
- if (!netconfig_load_settings(dev->conn_netconfig, settings,
- dev->conn_addr) ||
+ if (!netconfig_load_settings(dev->conn_netconfig, settings) ||
!netconfig_configure(dev->conn_netconfig,
p2p_netconfig_event_handler,
dev)) {
diff --git a/src/station.c b/src/station.c
index 672c48603d75..6bcf8dddadd0 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2869,8 +2869,7 @@ int __station_connect_network(struct station *station, struct network *network,
if (station->netconfig && !netconfig_load_settings(
station->netconfig,
- network_get_settings(network),
- netdev_get_address(station->netdev)))
+ network_get_settings(network)))
return -EINVAL;
hs = station_handshake_setup(station, network, bss);
--
2.26.3
9 months